diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..12f727b0 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,27 @@ +## Related Issue + + +## Summary of Changes + + +## Need Regression Testing + +- [ ] Yes +- [ ] No + +## Risk Assessment + +- [ ] Low +- [ ] Medium +- [ ] High + +## Additional Notes + + +## Screenshots (if applicable) + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..cfcb4597 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,99 @@ +name: Production Build + +on: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + push: + branches: [dev, master] + +jobs: + build: + runs-on: ubuntu-latest + environment: production + + strategy: + matrix: + node-version: [22.x] + + steps: + - uses: actions/checkout@v3 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 9 + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Create .env.pro file + run: | + cat << EOF > .env.pro + # Git info + COMMIT_SHA="${{ github.sha }}" + BRANCH_NAME="${{ github.ref_name }}" + PR_TITLE="${{ github.event.pull_request.title || '' }}" + PR_NUMBER="${{ github.event.pull_request.number || '' }}" + + # Google drive + GD_BACKUP_NAME="${{ vars.GD_BACKUP_NAME }}" + GD_FOLDER="${{ vars.GD_FOLDER }}" + GD_AES_KEY="${{ secrets.GD_AES_KEY }}" + GD_IV="${{ secrets.GD_IV }}" + GOOGLE_API="${{ secrets.GOOGLE_API }}" + FB_TOKEN="${{ secrets.FB_TOKEN }}" + # firebase + FB_API_KEY="${{ secrets.FB_API_KEY }}" + FB_AUTH_DOMAIN="${{ secrets.FB_AUTH_DOMAIN }}" + FB_DATABASE_URL="${{ secrets.FB_DATABASE_URL }}" + FB_PROJECTID="${{ secrets.FB_PROJECTID }}" + FB_STORAGE_BUCKET="${{ secrets.FB_STORAGE_BUCKET }}" + FB_MESSAGING_SENDER_ID="${{ secrets.FB_MESSAGING_SENDER_ID }}" + FB_APP_ID="${{ secrets.FB_APP_ID }}" + FB_MEASUREMENT_ID="${{ secrets.FB_MEASUREMENT_ID }}" + FB_FUNCTIONS="${{ secrets.FB_FUNCTIONS }}" + # manifest + OAUTH2_CLIENT_ID="${{ secrets.OAUTH2_CLIENT_ID }}" + OAUTH2_SCOPES="${{ vars.OAUTH2_SCOPES }}" + WC_PROJECTID="${{ secrets.WC_PROJECTID }}" + MIXPANEL_TOKEN="${{ secrets.MIXPANEL_TOKEN }}" + EOF + + - name: Build production + run: pnpm run build:ci + env: + CI: true + COMMIT_SHA: ${{ github.sha }} + BRANCH_NAME: ${{ github.ref_name }} + PR_TITLE: ${{ github.event.pull_request.title || '' }} + PR_NUMBER: ${{ github.event.pull_request.number || '' }} + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: extension-build + path: dist/ + + - name: Check build size + run: | + echo "Build size:" + du -sh dist/ diff --git a/.gitignore b/.gitignore index f7c28877..914837a1 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ yarn.lock .env.pro dist.zip _raw/manifest.json +_raw/react-devtools.js yarn-error.log dist2 src/background/utils/firebase.config.json diff --git a/_raw/manifest/manifest.dev.json b/_raw/manifest/manifest.dev.json index 3ce6a452..12a10d07 100644 --- a/_raw/manifest/manifest.dev.json +++ b/_raw/manifest/manifest.dev.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "FlowWallet-dev", "short_name": "__MSG_appName__", - "version": "2.5.21", + "version": "2.6.0", "default_locale": "en", "description": "__MSG_appDescription__", "icons": { diff --git a/_raw/manifest/manifest.pro.json b/_raw/manifest/manifest.pro.json index d2dc321a..bcd732c1 100644 --- a/_raw/manifest/manifest.pro.json +++ b/_raw/manifest/manifest.pro.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "2.5.21", + "version": "2.6.0", "default_locale": "en", "description": "__MSG_appDescription__", "icons": { diff --git a/build/plugins/AssetReplacePlugin.js b/build/plugins/AssetReplacePlugin.js index b6c47ee2..fcf20a4b 100644 --- a/build/plugins/AssetReplacePlugin.js +++ b/build/plugins/AssetReplacePlugin.js @@ -40,7 +40,7 @@ class AssetReplacePlugin { for (const chunk of compilation.chunks.values()) { const fileName = chunk.files.values().next().value; - if (!replaceArr.includes(([, assetName]) => assetName === fileName)) { + if (!replaceArr.some(([, assetName]) => assetName === fileName)) { compilation.updateAsset(fileName, (content) => { const result = replaceFn(content.source()); diff --git a/build/plugins/FirebaseFixPlugin.js b/build/plugins/FirebaseFixPlugin.js index e6ea9537..e8e60f10 100644 --- a/build/plugins/FirebaseFixPlugin.js +++ b/build/plugins/FirebaseFixPlugin.js @@ -12,9 +12,15 @@ class FirebaseFixPlugin { if (/\.(js|jsx)$/.test(name)) { let content = asset.source(); - console.log('About to fix firebase stuff', name); - console.log('typeof content', typeof content); + // Convert Buffer to string if needed + if (Buffer.isBuffer(content)) { + content = content.toString('utf-8'); + } + // Convert other types to string if needed + if (typeof content !== 'string') { + content = content.toString(); + } // Replace the _loadJS function content = content.replace( /function\s*\w*\s*_loadJS\([\w\s,]*\)\s*\{([\w\W]*?)\}$/gim, @@ -27,6 +33,9 @@ class FirebaseFixPlugin { '' ); + // https://apis.google.com/js/api.js + content = content.replace(/https:\/\/apis\.google\.com\/js\/api\.js/g, ''); + content = content.replace( /_loadJS\(`https:\/\/apis\.google\.com\/js\/api\.js(\?onload=\$\{([^}]+)\})?`\)/g, '_loadJS(`${$1}`)' diff --git a/build/prepareManifest.js b/build/prepareManifest.js index 7a50a591..c5149a70 100644 --- a/build/prepareManifest.js +++ b/build/prepareManifest.js @@ -1,5 +1,6 @@ const path = require('path'); const fs = require('fs-extra'); +const http = require('http'); // require('dotenv').config(); const PROJECT_ROOT = path.resolve(__dirname, '..'); @@ -8,6 +9,35 @@ const mode = args[0]; require('dotenv').config({ path: `.env.${mode}` }); +const OAUTH2_SCOPES = process.env.OAUTH2_SCOPES || ''; + +const DEVTOOLS_URL = 'http://localhost:8097'; + +async function fetchDevTools() { + return new Promise((resolve, reject) => { + const request = http.get(DEVTOOLS_URL, (response) => { + if (response.statusCode !== 200) { + reject(new Error(`Failed to fetch: ${response.statusCode}`)); + return; + } + + let data = ''; + response.on('data', (chunk) => (data += chunk)); + response.on('end', () => { + const modifiedScript = ` + // React DevTools for Chrome Extension + (function() { + ${data} + })(); + `; + resolve(modifiedScript); + }); + }); + + request.on('error', reject); + }); +} + async function prepare() { console.log(process.env.NODE_ENV); console.log(process.env.OAUTH2_CLIENT_ID); @@ -17,12 +47,25 @@ async function prepare() { manifest.oauth2 = { client_id: process.env.OAUTH2_CLIENT_ID, - scopes: process.env.OAUTH2_SCOPES.split(','), + scopes: OAUTH2_SCOPES.split(','), }; if (mode == 'dev') { manifest.key = process.env.MANIFEST_KEY; + try { + const devToolsScript = await fetchDevTools(); + fs.writeFileSync(path.resolve(__dirname, '../_raw/react-devtools.js'), devToolsScript); + console.log('✅ React DevTools source fetched successfully'); + } catch (error) { + console.warn('⚠️ Failed to fetch React DevTools. Run the devtools server first'); + // Write empty file if fetch fails + fs.writeFileSync( + path.resolve(__dirname, '../_raw/react-devtools.js'), + '// React DevTools not available' + ); + } } + fs.writeJSONSync(manifestPath, manifest, { spaces: 2 }); return ''; diff --git a/build/release.js b/build/release.js index 6b4e1425..ed85f499 100644 --- a/build/release.js +++ b/build/release.js @@ -1,5 +1,5 @@ const path = require('path'); -const { prompt } = require('enquirer'); +const { prompt: enquirerPrompt } = require('enquirer'); const fs = require('fs-extra'); const shell = require('shelljs'); const zipdir = require('zip-dir'); @@ -7,7 +7,7 @@ const zipdir = require('zip-dir'); const PROJECT_ROOT = path.resolve(__dirname, '..'); async function release() { - const input = await prompt({ + const input = await enquirerPrompt({ type: 'input', name: 'version', message: '[Flow Wallet] Please input the release version:', diff --git a/build/webpack.common.config.js b/build/webpack.common.config.js index 522fa4cb..659fb29e 100644 --- a/build/webpack.common.config.js +++ b/build/webpack.common.config.js @@ -1,6 +1,6 @@ const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -const TSConfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); const ESLintWebpackPlugin = require('eslint-webpack-plugin'); // const tsImportPluginFactory = require('ts-import-plugin'); const AssetReplacePlugin = require('./plugins/AssetReplacePlugin'); @@ -8,196 +8,215 @@ const FirebaseFixPlugin = require('./plugins/FirebaseFixPlugin'); const { version } = require('../_raw/manifest.json'); const path = require('path'); const CopyPlugin = require('copy-webpack-plugin'); +const fs = require('fs'); const paths = require('./paths'); -const config = { - resolve: { - fallback: { - http: require.resolve('stream-http'), +const config = (env) => { + console.log('env', env); + const isDevelopment = env.config === 'dev'; + const devToolsExists = + isDevelopment && fs.existsSync(path.resolve(__dirname, '../_raw/react-devtools.js')); + + const htmlPluginConfig = { + templateParameters: { + devMode: isDevelopment, + hasDevTools: devToolsExists, }, - }, - entry: { - background: paths.rootResolve('src/background/index.ts'), - 'content-script': paths.rootResolve('src/content-script/index.ts'), - pageProvider: paths.rootResolve('src/content-script/pageProvider/eth/index.ts'), - // pageProvider: paths.rootResolve( - // 'node_modules/@rabby-wallet/page-provider/dist/index.js' - // ), - ui: paths.rootResolve('src/ui/index.tsx'), - script: paths.rootResolve('src/content-script/script.js'), - }, - output: { - path: paths.dist, - filename: '[name].js', - publicPath: '/', - }, - experiments: { - topLevelAwait: true, - asyncWebAssembly: true, - syncWebAssembly: true, - }, - module: { - rules: [ - { - test: /\.jsx?$|\.tsx?$/, - exclude: /node_modules/, - oneOf: [ - { - // prevent webpack remove this file's output even it's not been used in entry - sideEffects: true, - test: /[\\/]pageProvider[\\/]index.ts/, - loader: 'ts-loader', - }, - { - test: /[\\/]ui[\\/]index.tsx/, - use: [ - { - loader: 'ts-loader', - options: { - transpileOnly: true, - compilerOptions: { - module: 'es2015', + }; + + return { + entry: { + background: paths.rootResolve('src/background/index.ts'), + 'content-script': paths.rootResolve('src/content-script/index.ts'), + pageProvider: paths.rootResolve('src/content-script/pageProvider/eth/index.ts'), + // pageProvider: paths.rootResolve( + // 'node_modules/@rabby-wallet/page-provider/dist/index.js' + // ), + ui: paths.rootResolve('src/ui/index.tsx'), + script: paths.rootResolve('src/content-script/script.js'), + }, + output: { + path: paths.dist, + filename: '[name].js', + publicPath: '/', + }, + experiments: { + topLevelAwait: true, + asyncWebAssembly: true, + syncWebAssembly: true, + }, + module: { + rules: [ + { + test: /\.jsx?$|\.tsx?$/, + exclude: /node_modules/, + oneOf: [ + { + // prevent webpack remove this file's output even it's not been used in entry + sideEffects: true, + test: /[\\/]pageProvider[\\/]index.ts/, + loader: 'ts-loader', + }, + { + test: /[\\/]ui[\\/]index.tsx/, + use: [ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + compilerOptions: { + module: 'es2015', + }, }, }, + ], + }, + { + loader: 'ts-loader', + }, + ], + }, + { + test: /\.css$/, + use: [ + { + loader: 'style-loader', + }, + { + loader: 'css-loader', + options: { + importLoaders: 1, }, - ], - }, - { - loader: 'ts-loader', - }, - ], - }, - { - test: /\.css$/, - use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', - options: { - importLoaders: 1, }, + { + loader: 'postcss-loader', + }, + ], + }, + { + test: /\.svg$/, + use: ['@svgr/webpack', 'url-loader'], + }, + { + test: /\.(png|jpe?g|gif)$/i, + loader: 'file-loader', + options: { + name: '[name].[ext]', }, - { - loader: 'postcss-loader', - }, - ], - }, - { - test: /\.svg$/, - use: ['@svgr/webpack', 'url-loader'], - }, - { - test: /\.(png|jpe?g|gif)$/i, - loader: 'file-loader', - options: { - name: '[name].[ext]', }, - }, - // { - // test: /\.wasm$/, - // include: path.resolve(__dirname, 'node_modules/@trustwallet/wallet-core/dist/lib'), - // use: [{ - // loader: 'file-loader', - // options: { - // name: '[name].[ext]', - // outputPath: '/', - // }, - // }], - // type: 'javascript/auto', + // { + // test: /\.wasm$/, + // include: path.resolve(__dirname, 'node_modules/@trustwallet/wallet-core/dist/lib'), + // use: [{ + // loader: 'file-loader', + // options: { + // name: '[name].[ext]', + // outputPath: '/', + // }, + // }], + // type: 'javascript/auto', - // }, - { - test: /\.wasm$/, - type: 'webassembly/async', - include: /node_modules/, - }, - { - test: /\.md$/, - use: 'raw-loader', - }, - { - test: /\.(woff|woff2|eot|ttf|otf)$/, - use: [ - { - loader: 'file-loader', - options: { - outputPath: 'fonts/', // output folder for fonts - name: '[name].[ext]', // keep the original file name - }, - }, - ], - }, - ], - }, - plugins: [ - new FirebaseFixPlugin(), - // new ESLintWebpackPlugin({ - // files: '**/*.{ts,tsx,js,jsx}', - // }), - new CopyPlugin({ - patterns: [ + // }, + { + test: /\.wasm$/, + type: 'webassembly/async', + include: /node_modules/, + }, { - from: 'node_modules/@trustwallet/wallet-core/dist/lib/wallet-core.wasm', - to: 'wallet-core.wasm', + test: /\.md$/, + use: 'raw-loader', + }, + { + test: /\.(woff|woff2|eot|ttf|otf)$/, + use: [ + { + loader: 'file-loader', + options: { + outputPath: 'fonts/', // output folder for fonts + name: '[name].[ext]', // keep the original file name + }, + }, + ], }, ], - }), - new HtmlWebpackPlugin({ - inject: true, - template: paths.popupHtml, - chunks: ['ui'], - filename: 'popup.html', - }), - new HtmlWebpackPlugin({ - inject: true, - template: paths.notificationHtml, - chunks: ['ui'], - filename: 'notification.html', - }), - new HtmlWebpackPlugin({ - inject: true, - template: paths.indexHtml, - chunks: ['ui'], - filename: 'index.html', - }), - new HtmlWebpackPlugin({ - inject: true, - template: paths.notificationHtml, - chunks: ['background'], - filename: 'background.html', - }), - new webpack.ProvidePlugin({ - Buffer: ['buffer', 'Buffer'], - process: 'process', - dayjs: 'dayjs', - }), - // new AssetReplacePlugin({ - // '#PAGEPROVIDER#': 'pageProvider', - // }), - new webpack.DefinePlugin({ - 'process.env.version': JSON.stringify(`version: ${version}`), - 'process.env.release': JSON.stringify(version), - }), - ], - resolve: { - alias: { - moment: require.resolve('dayjs'), }, - plugins: [new TSConfigPathsPlugin()], - fallback: { - stream: require.resolve('stream-browserify'), - crypto: require.resolve('crypto-browserify'), - os: require.resolve('os-browserify/browser'), - path: require.resolve('path-browserify'), - fs: false, - 'fs/promises': false, + plugins: [ + new FirebaseFixPlugin(), + // new ESLintWebpackPlugin({ + // files: '**/*.{ts,tsx,js,jsx}', + // }), + new CopyPlugin({ + patterns: [ + { + from: 'node_modules/@trustwallet/wallet-core/dist/lib/wallet-core.wasm', + to: 'wallet-core.wasm', + }, + ], + }), + new HtmlWebpackPlugin({ + inject: true, + template: paths.popupHtml, + chunks: ['ui'], + filename: 'popup.html', + ...htmlPluginConfig, + }), + new HtmlWebpackPlugin({ + inject: true, + template: paths.notificationHtml, + chunks: ['ui'], + filename: 'notification.html', + ...htmlPluginConfig, + }), + new HtmlWebpackPlugin({ + inject: true, + template: paths.indexHtml, + chunks: ['ui'], + filename: 'index.html', + ...htmlPluginConfig, + }), + new HtmlWebpackPlugin({ + inject: true, + template: paths.notificationHtml, + chunks: ['background'], + filename: 'background.html', + ...htmlPluginConfig, + }), + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + process: 'process', + dayjs: 'dayjs', + }), + // new AssetReplacePlugin({ + // '#PAGEPROVIDER#': 'pageProvider', + // }), + new webpack.DefinePlugin({ + 'process.env.version': JSON.stringify(`version: ${version}`), + 'process.env.release': JSON.stringify(version), + }), + ], + resolve: { + alias: { + moment: require.resolve('dayjs'), + // Forces all cross-fetch imports to use the same instance + 'cross-fetch': require.resolve('cross-fetch'), + }, + plugins: [new TsconfigPathsPlugin()], + fallback: { + // Removes polyfills that were interfering with native fetch + http: false, + https: false, + stream: require.resolve('stream-browserify'), + crypto: require.resolve('crypto-browserify'), + os: require.resolve('os-browserify/browser'), + path: require.resolve('path-browserify'), + fs: false, + 'fs/promises': false, + }, + extensions: ['.js', 'jsx', '.ts', '.tsx'], }, - extensions: ['.js', 'jsx', '.ts', '.tsx'], - }, - stats: 'minimal', + stats: 'minimal', + }; }; module.exports = config; diff --git a/build/webpack.dev.config.js b/build/webpack.dev.config.js index 21d935bc..336b2138 100644 --- a/build/webpack.dev.config.js +++ b/build/webpack.dev.config.js @@ -1,5 +1,6 @@ const webpack = require('webpack'); const Dotenv = require('dotenv-webpack'); +const CopyPlugin = require('copy-webpack-plugin'); // for extension local test, can build each time const config = { @@ -20,6 +21,14 @@ const config = { new Dotenv({ path: '.env.dev', }), + new CopyPlugin({ + patterns: [ + { + from: '_raw/react-devtools.js', + to: 'react-devtools.js', + }, + ], + }), ], resolve: { fallback: { diff --git a/build/webpack.pro.config.js b/build/webpack.pro.config.js index 0789f7b0..aa7fbc3f 100644 --- a/build/webpack.pro.config.js +++ b/build/webpack.pro.config.js @@ -28,8 +28,6 @@ const config = { ], resolve: { fallback: { - http: require.resolve('stream-http'), - https: require.resolve('https-browserify'), buffer: require.resolve('buffer'), url: require.resolve('url/'), vm: require.resolve('vm-browserify'), diff --git a/eslint.config.mjs b/eslint.config.mjs index 4b5b62ef..e486f3f1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -49,13 +49,16 @@ export default [ '@typescript-eslint/no-explicit-any': 'warn', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], - '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }], + '@typescript-eslint/consistent-type-imports': [ + 'error', + { prefer: 'type-imports', fixStyle: 'inline-type-imports', disallowTypeAnnotations: false }, + ], // React rules 'react/react-in-jsx-scope': 'error', // Required for React 17 'react/prop-types': 'off', 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'warn', + 'react-hooks/exhaustive-deps': 'error', // Import rules 'import/no-unresolved': 'error', @@ -78,9 +81,6 @@ export default [ eqeqeq: ['error', 'always'], 'no-unused-expressions': 'error', 'no-duplicate-imports': 'error', - - // Chrome extension specific - 'no-restricted-globals': ['error', 'window', 'document'], }, }, @@ -92,4 +92,33 @@ export default [ '@typescript-eslint/no-explicit-any': 'off', }, }, + + // Background-specific config for chrome extension + { + files: ['**/src/background/**/*.{js,jsx,ts,tsx}'], + rules: { + 'no-restricted-globals': [ + 'error', + { + name: 'window', + message: 'Do not use window in background scripts - use globalThis instead', + }, + { + name: 'document', + message: 'DOM APIs are not available in background scripts', + }, + ], + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['ui/*', '**/ui/**'], + message: 'UI components/modules cannot be imported into background scripts', + }, + ], + }, + ], + }, + }, ]; diff --git a/package.json b/package.json index df7a017a..06e200f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flow-reference-wallet", - "version": "2.5.21", + "version": "2.6.0", "description": "Digital wallet created for everyone.", "scripts": { "prepare:dev": "node ./build/prepareManifest.js dev", @@ -10,6 +10,7 @@ "winBuild:dev": "set NODE_OPTIONS=--max-old-space-size=8192 && copy _raw\\manifest\\manifest.dev.json _raw\\manifest.json && pnpm run prepare:dev && pnpm run winClean && webpack --progress --env config=dev", "build:dev": "NODE_OPTIONS=--max-old-space-size=8192 && cp _raw/manifest/manifest.dev.json _raw/manifest.json && pnpm run prepare:dev && pnpm run clean && webpack --progress --env config=dev", "winBuild:pro": "copy _raw\\manifest\\manifest.pro.json _raw\\manifest.json && pnpm run prepare:pro && pnpm run winClean && webpack --progress --env config=pro", + "build:ci": "cp _raw/manifest/manifest.pro.json _raw/manifest.json && pnpm run prepare:pro && pnpm run clean && webpack --env config=pro", "build:pro": "cp _raw/manifest/manifest.pro.json _raw/manifest.json && pnpm run prepare:pro && pnpm run clean && webpack --progress --env config=pro", "build:test": "cp _raw/manifest/manifest.dev.json _raw/manifest.json && pnpm run clean && webpack --progress --env config=none", "lint:fix": "eslint --fix .", @@ -20,196 +21,191 @@ "test": "jest", "pub": "node build/release.js", "prepare": "husky", - "preinstall": "npx only-allow pnpm" + "preinstall": "npx only-allow pnpm", + "setup-secrets": "node build/setup-github-secrets.js" }, "dependencies": { - "@coinbase/cbpay-js": "^1.1.0", + "@coinbase/cbpay-js": "^1.10.0", "@debank/common": "^0.3.60", - "@dnd-kit/core": "^4.0.3", - "@dnd-kit/sortable": "^5.1.0", - "@dnd-kit/utilities": "^3.0.2", - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", - "@firebase/auth": "^1.0.0", - "@firebase/remote-config": "^0.4.4", - "@firebase/util": "^1.10.2", - "@ledgerhq/hw-app-eth": "^6.0.2", - "@ledgerhq/hw-transport-webusb": "^6.0.2", - "@metamask/eth-sig-util": "^4.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@emotion/react": "^11.13.5", + "@emotion/styled": "^11.13.5", + "@ledgerhq/hw-app-eth": "^6.41.1", + "@ledgerhq/hw-transport-webusb": "^6.29.4", + "@metamask/eth-sig-util": "^4.0.1", "@metamask/obs-store": "^6.0.2", - "@mui/base": "^5.0.0-beta.3", - "@mui/core": "^5.0.0-alpha.54", - "@mui/icons-material": "^5.2.5", - "@mui/lab": "^5.0.0-alpha.65", - "@mui/material": "^5.14.11", - "@mui/styles": "^5.3.0", + "@mui/base": "5.0.0-beta.62", + "@mui/icons-material": "^5.16.7", + "@mui/lab": "5.0.0-alpha.173", + "@mui/material": "^5.16.7", + "@mui/styles": "^5.16.7", "@mui/system": "^5.16.7", - "@noble/secp256k1": "^1.5.1", - "@onflow/fcl": "^1.9.0", - "@onflow/fcl-wc": "^5.0.1", - "@onflow/transport-http": "1.5.0-alpha.1", - "@onflow/types": "^1.0.3", - "@rabby-wallet/eth-hd-keyring": "^3.6.5", - "@rabby-wallet/eth-lattice-keyring": "^0.4.2", + "@noble/secp256k1": "^1.7.1", + "@onflow/fcl": "^1.12.3", + "@onflow/fcl-wc": "^5.4.0", + "@onflow/transport-http": "1.10.2", + "@onflow/types": "^1.4.0", + "@rabby-wallet/eth-hd-keyring": "^3.6.12", + "@rabby-wallet/eth-lattice-keyring": "^0.4.4", "@rabby-wallet/eth-simple-keyring": "^4.2.1", "@rabby-wallet/eth-watch-keyring": "^1.0.0", - "@rabby-wallet/page-provider": "^0.3.2", - "@sentry/browser": "^6.7.2", - "@sentry/react": "^6.7.2", - "@sentry/tracing": "^6.7.2", - "@trustwallet/wallet-core": "^4.0.17", - "@types/bignumber.js": "^5.0.0", - "@types/lodash": "^4.14.172", - "@walletconnect/client": "^1.5.5", - "@walletconnect/core": "2.10.3", + "@rabby-wallet/page-provider": "^0.3.5", + "@reown/walletkit": "^1.1.1", + "@sentry/browser": "^6.19.7", + "@sentry/react": "^6.19.7", + "@sentry/tracing": "^6.19.7", + "@trustwallet/wallet-core": "^4.1.19", + "@tsparticles/engine": "^3.6.0", + "@tsparticles/react": "^3.0.0", + "@types/mixpanel-browser": "^2.50.2", + "@walletconnect/core": "^2.17.2", "@walletconnect/jsonrpc-utils": "^1.0.8", - "@walletconnect/modal": "^2.6.2", - "@walletconnect/sign-client": "^2.10.6", - "@walletconnect/types": "^2.10.6", + "@walletconnect/modal": "^2.7.0", + "@walletconnect/sign-client": "^2.17.2", + "@walletconnect/types": "^2.17.2", "@walletconnect/utils": "^2.17.2", - "@walletconnect/web3wallet": "^1.9.3", + "@walletconnect/web3wallet": "^1.16.1", "@zxing/library": "0.8.0", "aes-js": "^3.1.2", - "assert": "^2.0.0", - "axios": "^0.21.1", - "axios-rate-limit": "^1.3.0", - "bignumber.js": "^9.0.1", - "bip39": "^3.0.3", + "assert": "^2.1.0", + "axios": "^0.21.4", + "axios-rate-limit": "^1.4.0", + "bignumber.js": "^9.1.2", + "bip39": "^3.1.0", "browser-passworder": "^2.0.3", "buffer": "^6.0.3", - "clipboard": "^2.0.8", - "clsx": "^1.1.1", - "compare-versions": "^4.1.1", + "clipboard": "^2.0.11", + "clsx": "^1.2.1", + "compare-versions": "^4.1.4", "copy-webpack-plugin": "^12.0.2", - "crypto-browserify": "^3.12.0", - "dayjs": "^1.10.7", + "cross-fetch": "^4.0.0", + "crypto-browserify": "^3.12.1", + "dayjs": "^1.11.13", "debounce": "^1.2.1", "dedent": "^0.7.0", - "eth-hd-keyring": "^3.5.0", + "eth-hd-keyring": "^3.6.0", "eth-rpc-errors": "^4.0.3", - "eth-sig-util": "^3.0.1", "ethereum-hdwallet": "^0.0.26", "ethereumjs-util": "^7.1.5", - "ethers": "^6.12.0", + "ethers": "^6.13.4", "events": "^3.3.0", "file-saver": "^2.0.5", - "firebase": "^10.0.0", + "firebase": "^10.14.1", "flow-native-token-registry": "0.1.6", "hdkey": "0.8.0", - "history": "4", + "history": "^4.10.1", "koa-compose": "^4.1.0", "lodash": "^4.17.21", - "loglevel": "^1.7.1", + "loglevel": "^1.9.2", "lru-cache": "^6.0.0", - "nanoid": "^3.1.23", + "mixpanel-browser": "^2.56.0", + "nanoid": "^3.3.7", "obs-store": "^4.0.3", "process": "^0.11.10", - "qr-code-styling": "^1.6.0-rc.1", + "qr-code-styling": "^1.8.4", "qr-scanner": "^1.4.2", "raw-loader": "^4.0.2", - "react": "^17.0.1", - "react-component-transition": "^2.1.1", - "react-dom": "^17.0.1", + "react": "^18.3.1", + "react-component-transition": "^2.1.2", + "react-dom": "^18.3.1", "react-highlight": "^0.14.0", - "react-hook-form": "^7.27.0", + "react-hook-form": "^7.53.2", "react-infinite-scroll-component": "^6.1.0", "react-infinite-scroller": "^1.2.6", - "react-markdown": "^7.1.0", - "react-number-format": "^4.9.1", + "react-markdown": "^7.1.2", + "react-number-format": "^4.9.4", "react-placeholder-image": "^0.1.8", - "react-qrcode-logo": "^2.9.0", - "react-router-dom": "^5.2.0", - "react-router-transition": "^2.1.0", + "react-qrcode-logo": "^2.10.0", + "react-router-dom": "^5.3.4", "react-spring": "^8.0.27", "react-swipeable-views": "^0.14.0", - "react-text-transition": "^2.0.0", - "react-tsparticles": "^1.39.0", - "react-use": "^17.2.4", - "react-window": "^1.8.6", - "recharts": "^2.1.9", - "reflect-metadata": "^0.1.13", + "react-use": "^17.5.1", + "react-window": "^1.8.10", + "recharts": "^2.13.3", + "reflect-metadata": "^0.1.14", "remark-gfm": "^3.0.1", "rlp": "^3.0.0", - "secp256k1": "^4.0.2", + "secp256k1": "^4.0.4", "sha3": "^2.1.4", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "ts-toolbelt": "^9.6.0", - "util": "^0.12.3", + "tsparticles": "~3.6.0", + "util": "^0.12.5", "uuid": "^11.0.3", "vm-browserify": "^1.1.2", - "wagmi": "^1.4.6", - "web3": "^4.7.0", - "web3-utils": "^4.2.2", + "wagmi": "^1.4.13", + "web3": "^4.15.0", + "web3-utils": "^4.3.2", "webextension-polyfill": "^0.12.0", "zxcvbn": "^4.4.2" }, "devDependencies": { - "@eslint/js": "^9.14.0", + "@eslint/js": "^9.15.0", "@svgr/webpack": "^5.5.0", "@types/chrome": "^0.0.281", - "@types/events": "^3.0.0", - "@types/jest": "^27.4.0", - "@types/koa-compose": "^3.2.5", - "@types/lru-cache": "^5.1.0", - "@types/node": "^17.0.14", - "@types/react": "^17.0.4", - "@types/react-dom": "^17.0.3", - "@types/react-router-dom": "^5.1.7", - "@typescript-eslint/eslint-plugin": "^8.13.0", - "@typescript-eslint/parser": "^8.13.0", - "@welldone-software/why-did-you-render": "^6.2.1", + "@types/events": "^3.0.3", + "@types/jest": "^27.5.2", + "@types/koa-compose": "^3.2.8", + "@types/lodash": "^4.17.13", + "@types/lru-cache": "^5.1.1", + "@types/node": "^22.9.3", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@types/react-router-dom": "^5.3.3", + "@typescript-eslint/eslint-plugin": "^8.15.0", + "@typescript-eslint/parser": "^8.15.0", + "@welldone-software/why-did-you-render": "^6.2.3", "autoprefixer": "latest", - "css-loader": "^5.1.3", - "dotenv": "^16.3.1", - "dotenv-webpack": "^8.0.1", - "enquirer": "^2.3.6", - "eslint": "^9.14.0", + "css-loader": "^5.2.7", + "dotenv": "^16.4.5", + "dotenv-webpack": "^8.1.0", + "enquirer": "^2.4.1", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", - "eslint-config-react-app": "^6.0.0", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-prettier": "^3.4.1", "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", - "eslint-plugin-unused-imports": "^2.0.0", - "eslint-webpack-plugin": "^2.5.10", + "eslint-webpack-plugin": "^4.2.0", "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", + "fs-extra": "^10.1.0", "globals": "^15.12.0", - "html-webpack-plugin": "^5.3.1", + "html-webpack-plugin": "^5.6.3", "https-browserify": "^1.0.0", - "husky": "^9.1.6", - "i18next": "^20.3.2", - "jest": "^27.4.7", - "lint-staged": ">=10", + "husky": "^9.1.7", + "i18next": "^24.0.0", + "jest": "^27.5.1", + "libsodium-wrappers": "^0.7.15", + "lint-staged": "^15.2.10", "os-browserify": "^0.3.0", "path-browserify": "^1.0.1", "pinst": "^3.0.0", - "postcss": "^8.2.8", + "postcss": "^8.4.49", "postcss-custom-properties": "^11.0.0", - "postcss-import": "^14.0.0", - "postcss-loader": "^5.2.0", - "postcss-nested": "^5.0.5", + "postcss-import": "^14.1.0", + "postcss-loader": "^5.3.0", + "postcss-nested": "^5.0.6", "prettier": "^3.3.3", - "react-i18next": "^11.11.0", + "react-devtools": "^4.x.x", + "react-i18next": "^15.1.1", "react-iconfont-cli": "^2.0.2", - "shelljs": "^0.8.4", + "shelljs": "^0.8.5", "sinon-chrome": "^3.0.1", "style-loader": "^2.0.0", "ts-import-plugin": "^1.6.7", - "ts-jest": "^27.1.2", - "ts-loader": "^9.1.1", - "tsconfig-paths-webpack-plugin": "^3.5.1", - "typescript": "^4.5.4", - "typescript-eslint": "^8.13.0", - "typescript-transform-paths": "^3.0.0", + "ts-loader": "^9.5.1", + "tsconfig-paths-webpack-plugin": "^3.5.2", + "typescript": "^5.7.2", + "typescript-eslint": "^8.15.0", + "typescript-transform-paths": "^3.5.2", "url-loader": "^4.1.1", - "webpack": "^5.26.3", - "webpack-bundle-analyzer": "^4.4.0", - "webpack-cli": "^4.5.0", - "webpack-dev-server": "^3.11.2", - "webpack-merge": "^5.7.3", + "webpack": "^5.96.1", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-cli": "^4.10.0", + "webpack-dev-server": "^3.11.3", + "webpack-merge": "^5.10.0", "zip-dir": "^2.0.0" }, "keywords": [], @@ -222,5 +218,11 @@ "engines": { "node": ">=22.11.0", "pnpm": ">=9" + }, + "pnpm": { + "shamefully-hoist": true, + "node-linker": "hoisted", + "strict-peer-dependencies": false, + "auto-install-peers": true } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37971a7e..28dd6e8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,88 +9,70 @@ importers: .: dependencies: '@coinbase/cbpay-js': - specifier: ^1.1.0 - version: 1.10.0(regenerator-runtime@0.13.11) + specifier: ^1.10.0 + version: 1.10.0 '@debank/common': specifier: ^0.3.60 version: 0.3.60 - '@dnd-kit/core': - specifier: ^4.0.3 - version: 4.0.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@dnd-kit/sortable': - specifier: ^5.1.0 - version: 5.1.0(@dnd-kit/core@4.0.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react@17.0.2) '@dnd-kit/utilities': - specifier: ^3.0.2 - version: 3.2.2(react@17.0.2) + specifier: ^3.2.2 + version: 3.2.2(react@18.3.1) '@emotion/react': - specifier: ^11.7.1 - version: 11.13.5(@types/react@17.0.83)(react@17.0.2) + specifier: ^11.13.5 + version: 11.13.5(@types/react@18.3.12)(react@18.3.1) '@emotion/styled': - specifier: ^11.6.0 - version: 11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) - '@firebase/auth': - specifier: ^1.0.0 - version: 1.8.1(@firebase/app@0.10.13) - '@firebase/remote-config': - specifier: ^0.4.4 - version: 0.4.11(@firebase/app@0.10.13) - '@firebase/util': - specifier: ^1.10.2 - version: 1.10.2 + specifier: ^11.13.5 + version: 11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) '@ledgerhq/hw-app-eth': - specifier: ^6.0.2 + specifier: ^6.41.1 version: 6.41.1 '@ledgerhq/hw-transport-webusb': - specifier: ^6.0.2 + specifier: ^6.29.4 version: 6.29.4 '@metamask/eth-sig-util': - specifier: ^4.0.0 + specifier: ^4.0.1 version: 4.0.1 '@metamask/obs-store': specifier: ^6.0.2 version: 6.0.2 '@mui/base': - specifier: ^5.0.0-beta.3 - version: 5.0.0-beta.62(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@mui/core': - specifier: ^5.0.0-alpha.54 - version: 5.0.0-alpha.54(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: 5.0.0-beta.62 + version: 5.0.0-beta.62(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/icons-material': - specifier: ^5.2.5 - version: 5.16.7(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) + specifier: ^5.16.7 + version: 5.16.7(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) '@mui/lab': - specifier: ^5.0.0-alpha.65 - version: 5.0.0-alpha.173(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: 5.0.0-alpha.173 + version: 5.0.0-alpha.173(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': - specifier: ^5.14.11 - version: 5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^5.16.7 + version: 5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/styles': - specifier: ^5.3.0 - version: 5.16.7(@types/react@17.0.83)(react@17.0.2) + specifier: ^5.16.7 + version: 5.16.7(@types/react@18.3.12)(react@18.3.1) '@mui/system': specifier: ^5.16.7 - version: 5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) + version: 5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) '@noble/secp256k1': - specifier: ^1.5.1 + specifier: ^1.7.1 version: 1.7.1 '@onflow/fcl': - specifier: ^1.9.0 - version: 1.12.3(@types/react@17.0.83)(google-protobuf@3.21.4)(react@17.0.2) + specifier: ^1.12.3 + version: 1.12.3(@types/react@18.3.12)(google-protobuf@3.21.4)(react@18.3.1) '@onflow/fcl-wc': - specifier: ^5.0.1 - version: 5.4.0(@onflow/fcl-core@1.12.0(google-protobuf@3.21.4))(@types/react@17.0.83)(react@17.0.2) + specifier: ^5.4.0 + version: 5.4.0(@onflow/fcl-core@1.12.0(google-protobuf@3.21.4))(@types/react@18.3.12)(react@18.3.1) '@onflow/transport-http': - specifier: 1.5.0-alpha.1 - version: 1.5.0-alpha.1 + specifier: 1.10.2 + version: 1.10.2 '@onflow/types': - specifier: ^1.0.3 + specifier: ^1.4.0 version: 1.4.0 '@rabby-wallet/eth-hd-keyring': - specifier: ^3.6.5 + specifier: ^3.6.12 version: 3.6.12 '@rabby-wallet/eth-lattice-keyring': - specifier: ^0.4.2 + specifier: ^0.4.4 version: 0.4.4 '@rabby-wallet/eth-simple-keyring': specifier: ^4.2.1 @@ -99,49 +81,52 @@ importers: specifier: ^1.0.0 version: 1.0.0 '@rabby-wallet/page-provider': - specifier: ^0.3.2 + specifier: ^0.3.5 version: 0.3.5 + '@reown/walletkit': + specifier: ^1.1.1 + version: 1.1.1 '@sentry/browser': - specifier: ^6.7.2 + specifier: ^6.19.7 version: 6.19.7 '@sentry/react': - specifier: ^6.7.2 - version: 6.19.7(react@17.0.2) + specifier: ^6.19.7 + version: 6.19.7(react@18.3.1) '@sentry/tracing': - specifier: ^6.7.2 + specifier: ^6.19.7 version: 6.19.7 '@trustwallet/wallet-core': - specifier: ^4.0.17 + specifier: ^4.1.19 version: 4.1.19 - '@types/bignumber.js': - specifier: ^5.0.0 - version: 5.0.4 - '@types/lodash': - specifier: ^4.14.172 - version: 4.17.13 - '@walletconnect/client': - specifier: ^1.5.5 - version: 1.8.0 + '@tsparticles/engine': + specifier: ^3.6.0 + version: 3.7.1 + '@tsparticles/react': + specifier: ^3.0.0 + version: 3.0.0(@tsparticles/engine@3.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/mixpanel-browser': + specifier: ^2.50.2 + version: 2.50.2 '@walletconnect/core': - specifier: 2.10.3 - version: 2.10.3 + specifier: ^2.17.2 + version: 2.17.2 '@walletconnect/jsonrpc-utils': specifier: ^1.0.8 version: 1.0.8 '@walletconnect/modal': - specifier: ^2.6.2 - version: 2.7.0(@types/react@17.0.83)(react@17.0.2) + specifier: ^2.7.0 + version: 2.7.0(@types/react@18.3.12)(react@18.3.1) '@walletconnect/sign-client': - specifier: ^2.10.6 + specifier: ^2.17.2 version: 2.17.2 '@walletconnect/types': - specifier: ^2.10.6 + specifier: ^2.17.2 version: 2.17.2 '@walletconnect/utils': specifier: ^2.17.2 version: 2.17.2 '@walletconnect/web3wallet': - specifier: ^1.9.3 + specifier: ^1.16.1 version: 1.16.1 '@zxing/library': specifier: 0.8.0 @@ -150,19 +135,19 @@ importers: specifier: ^3.1.2 version: 3.1.2 assert: - specifier: ^2.0.0 + specifier: ^2.1.0 version: 2.1.0 axios: - specifier: ^0.21.1 + specifier: ^0.21.4 version: 0.21.4 axios-rate-limit: - specifier: ^1.3.0 + specifier: ^1.4.0 version: 1.4.0(axios@0.21.4) bignumber.js: - specifier: ^9.0.1 + specifier: ^9.1.2 version: 9.1.2 bip39: - specifier: ^3.0.3 + specifier: ^3.1.0 version: 3.1.0 browser-passworder: specifier: ^2.0.3 @@ -171,22 +156,25 @@ importers: specifier: ^6.0.3 version: 6.0.3 clipboard: - specifier: ^2.0.8 + specifier: ^2.0.11 version: 2.0.11 clsx: - specifier: ^1.1.1 + specifier: ^1.2.1 version: 1.2.1 compare-versions: - specifier: ^4.1.1 + specifier: ^4.1.4 version: 4.1.4 copy-webpack-plugin: specifier: ^12.0.2 version: 12.0.2(webpack@5.96.1) + cross-fetch: + specifier: ^4.0.0 + version: 4.0.0 crypto-browserify: - specifier: ^3.12.0 + specifier: ^3.12.1 version: 3.12.1 dayjs: - specifier: ^1.10.7 + specifier: ^1.11.13 version: 1.11.13 debounce: specifier: ^1.2.1 @@ -195,14 +183,11 @@ importers: specifier: ^0.7.0 version: 0.7.0 eth-hd-keyring: - specifier: ^3.5.0 + specifier: ^3.6.0 version: 3.6.0 eth-rpc-errors: specifier: ^4.0.3 version: 4.0.3 - eth-sig-util: - specifier: ^3.0.1 - version: 3.0.1 ethereum-hdwallet: specifier: ^0.0.26 version: 0.0.26 @@ -210,7 +195,7 @@ importers: specifier: ^7.1.5 version: 7.1.5 ethers: - specifier: ^6.12.0 + specifier: ^6.13.4 version: 6.13.4 events: specifier: ^3.3.0 @@ -219,7 +204,7 @@ importers: specifier: ^2.0.5 version: 2.0.5 firebase: - specifier: ^10.0.0 + specifier: ^10.14.1 version: 10.14.1 flow-native-token-registry: specifier: 0.1.6 @@ -228,7 +213,7 @@ importers: specifier: 0.8.0 version: 0.8.0 history: - specifier: '4' + specifier: ^4.10.1 version: 4.10.1 koa-compose: specifier: ^4.1.0 @@ -237,13 +222,16 @@ importers: specifier: ^4.17.21 version: 4.17.21 loglevel: - specifier: ^1.7.1 + specifier: ^1.9.2 version: 1.9.2 lru-cache: specifier: ^6.0.0 version: 6.0.0 + mixpanel-browser: + specifier: ^2.56.0 + version: 2.56.0 nanoid: - specifier: ^3.1.23 + specifier: ^3.3.7 version: 3.3.7 obs-store: specifier: ^4.0.3 @@ -252,7 +240,7 @@ importers: specifier: ^0.11.10 version: 0.11.10 qr-code-styling: - specifier: ^1.6.0-rc.1 + specifier: ^1.8.4 version: 1.8.4 qr-scanner: specifier: ^1.4.2 @@ -261,67 +249,58 @@ importers: specifier: ^4.0.2 version: 4.0.2(webpack@5.96.1) react: - specifier: ^17.0.1 - version: 17.0.2 + specifier: ^18.3.1 + version: 18.3.1 react-component-transition: - specifier: ^2.1.1 - version: 2.1.2(@types/react-dom@17.0.25)(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^2.1.2 + version: 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-dom: - specifier: ^17.0.1 - version: 17.0.2(react@17.0.2) + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) react-highlight: specifier: ^0.14.0 - version: 0.14.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + version: 0.14.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-hook-form: - specifier: ^7.27.0 - version: 7.53.2(react@17.0.2) + specifier: ^7.53.2 + version: 7.53.2(react@18.3.1) react-infinite-scroll-component: specifier: ^6.1.0 - version: 6.1.0(react@17.0.2) + version: 6.1.0(react@18.3.1) react-infinite-scroller: specifier: ^1.2.6 - version: 1.2.6(react@17.0.2) + version: 1.2.6(react@18.3.1) react-markdown: - specifier: ^7.1.0 - version: 7.1.2(@types/react@17.0.83)(react@17.0.2) + specifier: ^7.1.2 + version: 7.1.2(@types/react@18.3.12)(react@18.3.1) react-number-format: - specifier: ^4.9.1 - version: 4.9.4(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^4.9.4 + version: 4.9.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-placeholder-image: specifier: ^0.1.8 - version: 0.1.8(react@17.0.2) + version: 0.1.8(react@18.3.1) react-qrcode-logo: - specifier: ^2.9.0 - version: 2.10.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^2.10.0 + version: 2.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: - specifier: ^5.2.0 - version: 5.3.4(react@17.0.2) - react-router-transition: - specifier: ^2.1.0 - version: 2.1.0(react-dom@17.0.2(react@17.0.2))(react-router-dom@5.3.4(react@17.0.2))(react@17.0.2) + specifier: ^5.3.4 + version: 5.3.4(react@18.3.1) react-spring: specifier: ^8.0.27 - version: 8.0.27(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + version: 8.0.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-swipeable-views: specifier: ^0.14.0 - version: 0.14.0(react@17.0.2) - react-text-transition: - specifier: ^2.0.0 - version: 2.0.0(@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0))(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react-zdog@1.2.2)(react@17.0.2)(three@0.170.0)(zdog@1.1.3) - react-tsparticles: - specifier: ^1.39.0 - version: 1.43.1(react@17.0.2) + version: 0.14.0(react@18.3.1) react-use: - specifier: ^17.2.4 - version: 17.5.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^17.5.1 + version: 17.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-window: - specifier: ^1.8.6 - version: 1.8.10(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^1.8.10 + version: 1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) recharts: - specifier: ^2.1.9 - version: 2.13.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + specifier: ^2.13.3 + version: 2.13.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) reflect-metadata: - specifier: ^0.1.13 + specifier: ^0.1.14 version: 0.1.14 remark-gfm: specifier: ^3.0.1 @@ -330,7 +309,7 @@ importers: specifier: ^3.0.0 version: 3.0.0 secp256k1: - specifier: ^4.0.2 + specifier: ^4.0.4 version: 4.0.4 sha3: specifier: ^2.1.4 @@ -344,8 +323,11 @@ importers: ts-toolbelt: specifier: ^9.6.0 version: 9.6.0 + tsparticles: + specifier: ~3.6.0 + version: 3.6.0 util: - specifier: ^0.12.3 + specifier: ^0.12.5 version: 0.12.5 uuid: specifier: ^11.0.3 @@ -354,13 +336,13 @@ importers: specifier: ^1.1.2 version: 1.1.2 wagmi: - specifier: ^1.4.6 - version: 1.4.13(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(typescript@4.9.5)(viem@2.21.49(typescript@4.9.5)(zod@3.23.8))(zod@3.23.8) + specifier: ^1.4.13 + version: 1.4.13(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)(viem@2.21.50(typescript@5.7.2)(zod@3.23.8))(zod@3.23.8) web3: - specifier: ^4.7.0 - version: 4.15.0(typescript@4.9.5)(zod@3.23.8) + specifier: ^4.15.0 + version: 4.15.0(typescript@5.7.2)(zod@3.23.8) web3-utils: - specifier: ^4.2.2 + specifier: ^4.3.2 version: 4.3.2 webextension-polyfill: specifier: ^0.12.0 @@ -370,7 +352,7 @@ importers: version: 4.4.2 devDependencies: '@eslint/js': - specifier: ^9.14.0 + specifier: ^9.15.0 version: 9.15.0 '@svgr/webpack': specifier: ^5.5.0 @@ -379,70 +361,70 @@ importers: specifier: ^0.0.281 version: 0.0.281 '@types/events': - specifier: ^3.0.0 + specifier: ^3.0.3 version: 3.0.3 '@types/jest': - specifier: ^27.4.0 + specifier: ^27.5.2 version: 27.5.2 '@types/koa-compose': - specifier: ^3.2.5 + specifier: ^3.2.8 version: 3.2.8 + '@types/lodash': + specifier: ^4.17.13 + version: 4.17.13 '@types/lru-cache': - specifier: ^5.1.0 + specifier: ^5.1.1 version: 5.1.1 '@types/node': - specifier: ^17.0.14 - version: 17.0.45 + specifier: ^22.9.3 + version: 22.9.3 '@types/react': - specifier: ^17.0.4 - version: 17.0.83 + specifier: ^18.3.12 + version: 18.3.12 '@types/react-dom': - specifier: ^17.0.3 - version: 17.0.25 + specifier: ^18.3.1 + version: 18.3.1 '@types/react-router-dom': - specifier: ^5.1.7 + specifier: ^5.3.3 version: 5.3.3 '@typescript-eslint/eslint-plugin': - specifier: ^8.13.0 - version: 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + specifier: ^8.15.0 + version: 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) '@typescript-eslint/parser': - specifier: ^8.13.0 - version: 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + specifier: ^8.15.0 + version: 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) '@welldone-software/why-did-you-render': - specifier: ^6.2.1 - version: 6.2.3(react@17.0.2) + specifier: ^6.2.3 + version: 6.2.3(react@18.3.1) autoprefixer: specifier: latest version: 10.4.20(postcss@8.4.49) css-loader: - specifier: ^5.1.3 + specifier: ^5.2.7 version: 5.2.7(webpack@5.96.1) dotenv: - specifier: ^16.3.1 + specifier: ^16.4.5 version: 16.4.5 dotenv-webpack: - specifier: ^8.0.1 + specifier: ^8.1.0 version: 8.1.0(webpack@5.96.1) enquirer: - specifier: ^2.3.6 + specifier: ^2.4.1 version: 2.4.1 eslint: - specifier: ^9.14.0 + specifier: ^9.15.0 version: 9.15.0(jiti@2.4.0) eslint-config-prettier: specifier: ^9.1.0 version: 9.1.0(eslint@9.15.0(jiti@2.4.0)) - eslint-config-react-app: - specifier: ^6.0.0 - version: 6.0.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(babel-eslint@10.1.0(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-flowtype@5.10.0(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-react-hooks@5.0.0(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-react@7.37.2(eslint@9.15.0(jiti@2.4.0)))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) eslint-import-resolver-typescript: specifier: ^3.6.3 - version: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)) + version: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)) eslint-plugin-import: specifier: ^2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) + version: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) eslint-plugin-prettier: - specifier: ^3.4.0 + specifier: ^3.4.1 version: 3.4.1(eslint-config-prettier@9.1.0(eslint@9.15.0(jiti@2.4.0)))(eslint@9.15.0(jiti@2.4.0))(prettier@3.3.3) eslint-plugin-react: specifier: ^7.37.2 @@ -450,38 +432,38 @@ importers: eslint-plugin-react-hooks: specifier: ^5.0.0 version: 5.0.0(eslint@9.15.0(jiti@2.4.0)) - eslint-plugin-unused-imports: - specifier: ^2.0.0 - version: 2.0.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0)) eslint-webpack-plugin: - specifier: ^2.5.10 - version: 2.7.0(eslint@9.15.0(jiti@2.4.0))(webpack@5.96.1) + specifier: ^4.2.0 + version: 4.2.0(eslint@9.15.0(jiti@2.4.0))(webpack@5.96.1) file-loader: specifier: ^6.2.0 version: 6.2.0(webpack@5.96.1) fs-extra: - specifier: ^10.0.0 + specifier: ^10.1.0 version: 10.1.0 globals: specifier: ^15.12.0 version: 15.12.0 html-webpack-plugin: - specifier: ^5.3.1 + specifier: ^5.6.3 version: 5.6.3(webpack@5.96.1) https-browserify: specifier: ^1.0.0 version: 1.0.0 husky: - specifier: ^9.1.6 + specifier: ^9.1.7 version: 9.1.7 i18next: - specifier: ^20.3.2 - version: 20.6.1 + specifier: ^24.0.0 + version: 24.0.0(typescript@5.7.2) jest: - specifier: ^27.4.7 - version: 27.5.1 + specifier: ^27.5.1 + version: 27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)) + libsodium-wrappers: + specifier: ^0.7.15 + version: 0.7.15 lint-staged: - specifier: '>=10' + specifier: ^15.2.10 version: 15.2.10 os-browserify: specifier: ^0.3.0 @@ -493,31 +475,34 @@ importers: specifier: ^3.0.0 version: 3.0.0 postcss: - specifier: ^8.2.8 + specifier: ^8.4.49 version: 8.4.49 postcss-custom-properties: specifier: ^11.0.0 version: 11.0.0(postcss@8.4.49) postcss-import: - specifier: ^14.0.0 + specifier: ^14.1.0 version: 14.1.0(postcss@8.4.49) postcss-loader: - specifier: ^5.2.0 + specifier: ^5.3.0 version: 5.3.0(postcss@8.4.49)(webpack@5.96.1) postcss-nested: - specifier: ^5.0.5 + specifier: ^5.0.6 version: 5.0.6(postcss@8.4.49) prettier: specifier: ^3.3.3 version: 3.3.3 + react-devtools: + specifier: ^4.x.x + version: 4.28.5 react-i18next: - specifier: ^11.11.0 - version: 11.18.6(i18next@20.6.1)(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2) + specifier: ^15.1.1 + version: 15.1.1(i18next@24.0.0(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-iconfont-cli: specifier: ^2.0.2 - version: 2.0.2(react@17.0.2) + version: 2.0.2(react@18.3.1) shelljs: - specifier: ^0.8.4 + specifier: ^0.8.5 version: 0.8.5 sinon-chrome: specifier: ^3.0.1 @@ -528,41 +513,38 @@ importers: ts-import-plugin: specifier: ^1.6.7 version: 1.6.7 - ts-jest: - specifier: ^27.1.2 - version: 27.1.5(@babel/core@7.26.0)(@types/jest@27.5.2)(babel-jest@27.5.1(@babel/core@7.26.0))(jest@27.5.1)(typescript@4.9.5) ts-loader: - specifier: ^9.1.1 - version: 9.5.1(typescript@4.9.5)(webpack@5.96.1) + specifier: ^9.5.1 + version: 9.5.1(typescript@5.7.2)(webpack@5.96.1) tsconfig-paths-webpack-plugin: - specifier: ^3.5.1 + specifier: ^3.5.2 version: 3.5.2 typescript: - specifier: ^4.5.4 - version: 4.9.5 + specifier: ^5.7.2 + version: 5.7.2 typescript-eslint: - specifier: ^8.13.0 - version: 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + specifier: ^8.15.0 + version: 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) typescript-transform-paths: - specifier: ^3.0.0 - version: 3.5.2(typescript@4.9.5) + specifier: ^3.5.2 + version: 3.5.2(typescript@5.7.2) url-loader: specifier: ^4.1.1 version: 4.1.1(file-loader@6.2.0(webpack@5.96.1))(webpack@5.96.1) webpack: - specifier: ^5.26.3 + specifier: ^5.96.1 version: 5.96.1(webpack-cli@4.10.0) webpack-bundle-analyzer: - specifier: ^4.4.0 + specifier: ^4.10.2 version: 4.10.2 webpack-cli: - specifier: ^4.5.0 + specifier: ^4.10.0 version: 4.10.0(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@3.11.3)(webpack@5.96.1) webpack-dev-server: - specifier: ^3.11.2 + specifier: ^3.11.3 version: 3.11.3(webpack-cli@4.10.0)(webpack@5.96.1) webpack-merge: - specifier: ^5.7.3 + specifier: ^5.10.0 version: 5.10.0 zip-dir: specifier: ^2.0.0 @@ -725,33 +707,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-proposal-class-properties@7.18.6': - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-export-default-from@7.25.9': - resolution: {integrity: sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6': - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-optional-chaining@7.21.0': - resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} @@ -779,23 +734,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-dynamic-import@7.8.3': - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-export-default-from@7.25.9': - resolution: {integrity: sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-flow@7.26.0': - resolution: {integrity: sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.26.0': resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} engines: {node: '>=6.9.0'} @@ -974,12 +912,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-flow-strip-types@7.25.9': - resolution: {integrity: sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.25.9': resolution: {integrity: sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==} engines: {node: '>=6.9.0'} @@ -1130,18 +1062,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-self@7.25.9': - resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.25.9': - resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx@7.25.9': resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} engines: {node: '>=6.9.0'} @@ -1172,12 +1092,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-runtime@7.25.9': - resolution: {integrity: sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-shorthand-properties@7.25.9': resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} engines: {node: '>=6.9.0'} @@ -1208,12 +1122,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typescript@7.25.9': - resolution: {integrity: sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.25.9': resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} engines: {node: '>=6.9.0'} @@ -1244,12 +1152,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-flow@7.25.9': - resolution: {integrity: sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/preset-modules@0.1.6-no-external-plugins': resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} peerDependencies: @@ -1261,18 +1163,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-typescript@7.26.0': - resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/register@7.25.9': - resolution: {integrity: sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/runtime@7.0.0': resolution: {integrity: sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==} @@ -1307,6 +1197,10 @@ packages: '@coinbase/wallet-sdk@3.9.3': resolution: {integrity: sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@debank/common@0.3.60': resolution: {integrity: sha512-SaFTXvnn2aYQTPB3B8YD/AhHYwdMRiqu7jCkYV6c/Sd3MmxzJR3v+Kd4jlQniKfEdB21+1vMb0NlzHw/gyemlw==} @@ -1314,28 +1208,15 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@dnd-kit/accessibility@3.1.0': - resolution: {integrity: sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==} - peerDependencies: - react: '>=16.8.0' - - '@dnd-kit/core@4.0.3': - resolution: {integrity: sha512-uT1uHZxKx3iEkupmLfknMIvbykMJSetoXXmra6sGGvtWy+OMKrWm3axH2c90+JC/q6qaeKs2znd3Qs8GLnCa5Q==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@dnd-kit/sortable@5.1.0': - resolution: {integrity: sha512-CPyiUHbTrSYzhddfgdeoX0ERg/dEyVKIWx9+4O6uqpoppo84SXCBHVFiFBRVpQ9wtpsXs7prtUAnAUTcvFQTZg==} - peerDependencies: - '@dnd-kit/core': ^4.0.2 - react: '>=16.8.0' - '@dnd-kit/utilities@3.2.2': resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} peerDependencies: react: '>=16.8.0' + '@electron/get@2.0.3': + resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} + engines: {node: '>=12'} + '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -1578,20 +1459,6 @@ packages: '@react-native-async-storage/async-storage': optional: true - '@firebase/auth@1.8.1': - resolution: {integrity: sha512-LX9N/Cf5Z35r5yqm2+5M3+2bRRe/+RFaa/+u4HDni7TA27C/Xm4XHLKcWcLg1BzjrS4zngSaBEOSODvp6RFOqQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - '@firebase/app': 0.x - '@react-native-async-storage/async-storage': ^1.18.1 - peerDependenciesMeta: - '@react-native-async-storage/async-storage': - optional: true - - '@firebase/component@0.6.11': - resolution: {integrity: sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==} - engines: {node: '>=18.0.0'} - '@firebase/component@0.6.9': resolution: {integrity: sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==} @@ -1649,11 +1516,6 @@ packages: peerDependencies: '@firebase/app-types': 0.x - '@firebase/installations@0.6.11': - resolution: {integrity: sha512-w8fY8mw6fxJzsZM2ufmTtomopXl1+bn/syYon+Gpn+0p0nO1cIUEVEFrFazTLaaL9q1CaVhc3HmseRTsI3igAA==} - peerDependencies: - '@firebase/app': 0.x - '@firebase/installations@0.6.9': resolution: {integrity: sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==} peerDependencies: @@ -1662,10 +1524,6 @@ packages: '@firebase/logger@0.4.2': resolution: {integrity: sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==} - '@firebase/logger@0.4.4': - resolution: {integrity: sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==} - engines: {node: '>=18.0.0'} - '@firebase/messaging-compat@0.2.12': resolution: {integrity: sha512-pKsiUVZrbmRgdImYqhBNZlkKJbqjlPkVdQRZGRbkTyX4OSGKR0F/oJeCt1a8jEg5UnBp4fdVwSWSp4DuCovvEQ==} peerDependencies: @@ -1700,11 +1558,6 @@ packages: '@firebase/remote-config-types@0.3.2': resolution: {integrity: sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==} - '@firebase/remote-config@0.4.11': - resolution: {integrity: sha512-9z0rgKuws2nj+7cdiqF+NY1QR4na6KnuOvP+jQvgilDOhGtKOcCMq5XHiu66i73A9kFhyU6QQ2pHXxcmaq1pBw==} - peerDependencies: - '@firebase/app': 0.x - '@firebase/remote-config@0.4.9': resolution: {integrity: sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==} peerDependencies: @@ -1729,10 +1582,6 @@ packages: '@firebase/util@1.10.0': resolution: {integrity: sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==} - '@firebase/util@1.10.2': - resolution: {integrity: sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==} - engines: {node: '>=18.0.0'} - '@firebase/vertexai-preview@0.0.4': resolution: {integrity: sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==} engines: {node: '>=18.0.0'} @@ -1801,10 +1650,6 @@ packages: peerDependencies: google-protobuf: ^3.14.0 - '@isaacs/ttlcache@1.4.1': - resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} - engines: {node: '>=12'} - '@istanbuljs/load-nyc-config@1.1.0': resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} @@ -1826,26 +1671,14 @@ packages: node-notifier: optional: true - '@jest/create-cache-key-function@29.7.0': - resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/environment@27.5.1': resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/fake-timers@27.5.1': resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/globals@27.5.1': resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1879,10 +1712,6 @@ packages: resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jest/types@27.5.1': resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1912,6 +1741,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@ledgerhq/cryptoassets-evm-signatures@13.5.2': resolution: {integrity: sha512-OjjzuiMMEIYEbXeueJB6mXwlvYhru28b43buAVOeggZ2XmdlT0kBvt7Cjn4bDPqff/glWR7vQdytIr7b77m2EQ==} @@ -2049,18 +1881,6 @@ packages: '@mui/core-downloads-tracker@5.16.7': resolution: {integrity: sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==} - '@mui/core@5.0.0-alpha.54': - resolution: {integrity: sha512-8TxdHqDdSb6wjhsnpE5n7qtkFKDG3PUSlVY0gR3VcdsHXscUY13l3VbMQW1brI4D/R9zx5VYmxIHWaHFgw4RtA==} - engines: {node: '>=12.0.0'} - deprecated: You can now upgrade to @mui/base. See https://github.com/mui/material-ui/releases/tag/v5.1.1 - peerDependencies: - '@types/react': ^16.8.6 || ^17.0.0 - react: ^17.0.2 - react-dom: ^17.0.2 - peerDependenciesMeta: - '@types/react': - optional: true - '@mui/icons-material@5.16.7': resolution: {integrity: sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==} engines: {node: '>=12.0.0'} @@ -2206,6 +2026,10 @@ packages: resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.6.1': + resolution: {integrity: sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==} + engines: {node: ^14.21.3 || >=16} + '@noble/secp256k1@1.7.1': resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -2251,9 +2075,6 @@ packages: '@onflow/transport-http@1.10.2': resolution: {integrity: sha512-dXi4pe1K29kJ4AbHH4eBIZ3JhYoo68sl5vlJzm5w1MMApHUWDIeDDDFh1opvqyvE3W8uBCe7+hVrigMZAZyHJA==} - '@onflow/transport-http@1.5.0-alpha.1': - resolution: {integrity: sha512-hHZDoWG+/Bp3fAr9i5Lmb3qhH0BEhsB6Y/3xtrg9cm/anNGzmbRKbdKdB/QuCVDMGcjLiOWIq+Z/jh05BxuMVA==} - '@onflow/typedefs@1.3.1': resolution: {integrity: sha512-rYMSt2KRr1DG5Z9CQu4PzyT1uKPNZRrjHBTAEinjvcFeqdHF/BW93Wzvx/yYK+RF4aepDLrvkshjAHPfwUkh2g==} @@ -2430,150 +2251,11 @@ packages: '@rabby-wallet/page-provider@0.3.5': resolution: {integrity: sha512-wpS56MLGZot+m4RXdArDuJ3I3hhDke9fAPAimOlPqDcjKqUSsy9NhuZhMhw6xzsTZSsuoCjwxuuw/nqv4fU9bw==} - '@react-native/assets-registry@0.76.3': - resolution: {integrity: sha512-7Fnc3lzCFFpnoyL1egua6d/qUp0KiIpeSLbfOMln4nI2g2BMzyFHdPjJnpLV2NehmS0omOOkrfRqK5u1F/MXzA==} - engines: {node: '>=18'} - - '@react-native/babel-plugin-codegen@0.76.3': - resolution: {integrity: sha512-mZ7jmIIg4bUnxCqY3yTOkoHvvzsDyrZgfnIKiTGm5QACrsIGa5eT3pMFpMm2OpxGXRDrTMsYdPXE2rCyDX52VQ==} - engines: {node: '>=18'} - - '@react-native/babel-preset@0.76.3': - resolution: {integrity: sha512-zi2nPlQf9q2fmfPyzwWEj6DU96v8ziWtEfG7CTAX2PG/Vjfsr94vn/wWrCdhBVvLRQ6Kvd/MFAuDYpxmQwIiVQ==} - engines: {node: '>=18'} - peerDependencies: - '@babel/core': '*' - - '@react-native/codegen@0.76.3': - resolution: {integrity: sha512-oJCH/jbYeGmFJql8/y76gqWCCd74pyug41yzYAjREso1Z7xL88JhDyKMvxEnfhSdMOZYVl479N80xFiXPy3ZYA==} - engines: {node: '>=18'} - peerDependencies: - '@babel/preset-env': ^7.1.6 - - '@react-native/community-cli-plugin@0.76.3': - resolution: {integrity: sha512-vgsLixHS24jR0d0QqPykBWFaC+V8x9cM3cs4oYXw3W199jgBNGP9MWcUJLazD2vzrT/lUTVBVg0rBeB+4XR6fg==} - engines: {node: '>=18'} - peerDependencies: - '@react-native-community/cli-server-api': '*' - peerDependenciesMeta: - '@react-native-community/cli-server-api': - optional: true - - '@react-native/debugger-frontend@0.76.3': - resolution: {integrity: sha512-pMHQ3NpPB28RxXciSvm2yD+uDx3pkhzfuWkc7VFgOduyzPSIr0zotUiOJzsAtrj8++bPbOsAraCeQhCqoOTWQw==} - engines: {node: '>=18'} - - '@react-native/dev-middleware@0.76.3': - resolution: {integrity: sha512-b+2IpW40z1/S5Jo5JKrWPmucYU/PzeGyGBZZ/SJvmRnBDaP3txb9yIqNZAII1EWsKNhedh8vyRO5PSuJ9Juqzw==} - engines: {node: '>=18'} - - '@react-native/gradle-plugin@0.76.3': - resolution: {integrity: sha512-t0aYZ8ND7+yc+yIm6Yp52bInneYpki6RSIFZ9/LMUzgMKvEB62ptt/7sfho9QkKHCNxE1DJSWIqLIGi/iHHkyg==} - engines: {node: '>=18'} - - '@react-native/js-polyfills@0.76.3': - resolution: {integrity: sha512-pubJFArMMrdZiytH+W95KngcSQs+LsxOBsVHkwgMnpBfRUxXPMK4fudtBwWvhnwN76Oe+WhxSq7vOS5XgoPhmw==} - engines: {node: '>=18'} - - '@react-native/metro-babel-transformer@0.76.3': - resolution: {integrity: sha512-b2zQPXmW7avw/7zewc9nzMULPIAjsTwN03hskhxHUJH5pzUf7pIklB3FrgYPZrRhJgzHiNl3tOPu7vqiKzBYPg==} - engines: {node: '>=18'} - peerDependencies: - '@babel/core': '*' - - '@react-native/normalize-colors@0.76.3': - resolution: {integrity: sha512-Yrpmrh4IDEupUUM/dqVxhAN8QW1VEUR3Qrk2lzJC1jB2s46hDe0hrMP2vs12YJqlzshteOthjwXQlY0TgIzgbg==} - - '@react-native/virtualized-lists@0.76.3': - resolution: {integrity: sha512-wTGv9pVh3vAOWb29xFm+J9VRe9dUcUcb9FyaMLT/Hxa88W4wqa5ZMe1V9UvrrBiA1G5DKjv8/1ZcDsJhyugVKA==} - engines: {node: '>=18'} - peerDependencies: - '@types/react': ^18.2.6 - react: '*' - react-native: '*' - peerDependenciesMeta: - '@types/react': - optional: true - - '@react-spring/animated@9.7.5': - resolution: {integrity: sha512-Tqrwz7pIlsSDITzxoLS3n/v/YCUHQdOIKtOJf4yL6kYVSDTSmVK1LI1Q3M/uu2Sx4X3pIWF3xLUhlsA6SPNTNg==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - - '@react-spring/core@9.7.5': - resolution: {integrity: sha512-rmEqcxRcu7dWh7MnCcMXLvrf6/SDlSokLaLTxiPlAYi11nN3B5oiCUAblO72o+9z/87j2uzxa2Inm8UbLjXA+w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - - '@react-spring/konva@9.7.5': - resolution: {integrity: sha512-BelrmyY6w0FGoNSEfSJltjQDUoW0Prxf+FzGjyLuLs+V9M9OM/aHnYqOlvQEfQsZx6C/ZiDOn5BZl8iH8SDf+Q==} - peerDependencies: - konva: '>=2.6' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-konva: ^16.8.0 || ^16.8.7-0 || ^16.9.0-0 || ^16.10.1-0 || ^16.12.0-0 || ^16.13.0-0 || ^17.0.0-0 || ^17.0.1-0 || ^17.0.2-0 || ^18.0.0-0 - - '@react-spring/native@9.7.5': - resolution: {integrity: sha512-C1S500BNP1I05MftElyLv2nIqaWQ0MAByOAK/p4vuXcUK3XcjFaAJ385gVLgV2rgKfvkqRoz97PSwbh+ZCETEg==} - peerDependencies: - react: 16.8.0 || >=17.0.0 || >=18.0.0 - react-native: '>=0.58' - - '@react-spring/rafz@9.7.5': - resolution: {integrity: sha512-5ZenDQMC48wjUzPAm1EtwQ5Ot3bLIAwwqP2w2owG5KoNdNHpEJV263nGhCeKKmuA3vG2zLLOdu3or6kuDjA6Aw==} - - '@react-spring/shared@9.7.5': - resolution: {integrity: sha512-wdtoJrhUeeyD/PP/zo+np2s1Z820Ohr/BbuVYv+3dVLW7WctoiN7std8rISoYoHpUXtbkpesSKuPIw/6U1w1Pw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - - '@react-spring/three@9.7.5': - resolution: {integrity: sha512-RxIsCoQfUqOS3POmhVHa1wdWS0wyHAUway73uRLp3GAL5U2iYVNdnzQsep6M2NZ994BlW8TcKuMtQHUqOsy6WA==} - peerDependencies: - '@react-three/fiber': '>=6.0' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - three: '>=0.126' - - '@react-spring/types@9.7.5': - resolution: {integrity: sha512-HVj7LrZ4ReHWBimBvu2SKND3cDVUPWKLqRTmWe/fNY6o1owGOX0cAHbdPDTMelgBlVbrTKrre6lFkhqGZErK/g==} - - '@react-spring/web@9.7.5': - resolution: {integrity: sha512-lmvqGwpe+CSttsWNZVr+Dg62adtKhauGwLyGE/RRyZ8AAMLgb9x3NDMA5RMElXo+IMyTkPp7nxTB8ZQlmhb6JQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@reown/walletkit@1.1.1': + resolution: {integrity: sha512-GTPksxBO6VAsqiQ0oH2jt8C845Y7redpI4OxRy31vf7KKDPPGfldbsTYZ+FP9xSda00dCJJKuXhzewZT/xHuDg==} - '@react-spring/zdog@9.7.5': - resolution: {integrity: sha512-VV7vmb52wGHgDA1ry6hv+QgxTs78fqjKEQnj+M8hiBg+dwOsTtqqM24ADtc4cMAhPW+eZhVps8ZNKtjt8ouHFA==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-zdog: '>=1.0' - zdog: '>=1.0' - - '@react-three/fiber@8.17.10': - resolution: {integrity: sha512-S6bqa4DqUooEkInYv/W+Jklv2zjSYCXAhm6qKpAQyOXhTEt5gBXnA7W6aoJ0bjmp9pAeaSj/AZUoz1HCSof/uA==} - peerDependencies: - expo: '>=43.0' - expo-asset: '>=8.4' - expo-file-system: '>=11.0' - expo-gl: '>=11.0' - react: '>=18.0' - react-dom: '>=18.0' - react-native: '>=0.64' - three: '>=0.133' - peerDependenciesMeta: - expo: - optional: true - expo-asset: - optional: true - expo-file-system: - optional: true - expo-gl: - optional: true - react-dom: - optional: true - react-native: - optional: true + '@rrweb/types@2.0.0-alpha.17': + resolution: {integrity: sha512-AfDTVUuCyCaIG0lTSqYtrZqJX39ZEYzs4fYKnexhQ+id+kbZIpIJtaut5cto6dWZbB3SEe4fW0o90Po3LvTmfg==} '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -2587,13 +2269,16 @@ packages: '@safe-global/safe-apps-sdk@9.1.0': resolution: {integrity: sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==} - '@safe-global/safe-gateway-typescript-sdk@3.22.3': - resolution: {integrity: sha512-aDb/FpkJMZ2IvP5KULHXnCRVVYOhEEY4BAwrGfsuTXqp8g8s2oAsBoBYJfaN9rWI/QDkd5Wn3GTC0ZeOLW1NiQ==} + '@safe-global/safe-gateway-typescript-sdk@3.22.4': + resolution: {integrity: sha512-Z7Z8w3GEJdJ/paF+NK23VN4AwqWPadq0AeRYjYLjIBiPWpRB2UO/FKq7ONABEq0YFgNPklazIV4IExQU1gavXA==} engines: {node: '>=16'} '@scure/base@1.1.9': resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} + '@scure/base@1.2.1': + resolution: {integrity: sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==} + '@scure/bip32@1.3.2': resolution: {integrity: sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==} @@ -2649,6 +2334,10 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + '@sindresorhus/merge-streams@2.3.0': resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} @@ -2656,12 +2345,6 @@ packages: '@sinonjs/commons@1.8.6': resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - '@sinonjs/fake-timers@8.1.0': resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} @@ -2784,6 +2467,10 @@ packages: resolution: {integrity: sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==} engines: {node: '>=10'} + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + '@tanstack/query-core@4.36.1': resolution: {integrity: sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==} @@ -2817,42 +2504,201 @@ packages: '@trustwallet/wallet-core@4.1.19': resolution: {integrity: sha512-KTYsxIehyOf4Tq2F5j+gtk4xsGIYTxAgOEJApnkLNpOqtE1/lWptkRpOZeiIYM04ASZJIUKM88CfLpj1hjKSlg==} - '@types/accepts@1.3.7': - resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - '@types/babel__generator@7.6.8': - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@tsparticles/basic@3.7.1': + resolution: {integrity: sha512-oJMJ3qzYUROYaOEsaFXkVynxT2OTWBXbQ9MNc1bJi/bVc1VOU44VN7X/KmiZjD+w1U+Qalk6BeVvDRwpFshblw==} - '@types/bignumber.js@5.0.4': - resolution: {integrity: sha512-y/nRKmgKRakrBZ4B3/1mhZOEHrKcf6BniqxVlsVrmaG6fN6WzzUlXfsD+KX+Ii4C+093A7h1p6LkOsXktOfQnQ==} - deprecated: This is a stub types definition. bignumber.js provides its own type definitions, so you do not need this installed. + '@tsparticles/engine@3.7.1': + resolution: {integrity: sha512-GYzBgq/oOE9YJdOL1++MoawWmYg4AvVct6CIrJGx84ZRb3U2owYmLsRGabYl0qX1CWWOvUG569043RJmyp/vQA==} - '@types/bn.js@4.11.6': - resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + '@tsparticles/interaction-external-attract@3.7.1': + resolution: {integrity: sha512-cpnMsFJ7ZJNKccpQvskKvSs1ofknByHE6FGqbEb17ij7HqvbECQOCOVKHPFnYipHe14cXor/Cd+nVisRcTASoQ==} - '@types/bn.js@5.1.6': - resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} + '@tsparticles/interaction-external-bounce@3.7.1': + resolution: {integrity: sha512-npvU9Qt6WDonjezHqi+hWM44ga2Oh5yXdr8eSoJpvuHZrCP7rIdRSz5XseHouO1bMS9DbXk86sx4qwrhB5w58w==} - '@types/body-parser@1.19.5': - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@tsparticles/interaction-external-bubble@3.7.1': + resolution: {integrity: sha512-WdbYL46lMfuf2g5kfVB1hhhxRBtEXDvnwz8PJwLKurSThL/27bqsqysyXsMzXtLByXUneGhtJTj4D5I5RYdgjA==} - '@types/chrome@0.0.186': - resolution: {integrity: sha512-Ykpf95dbv0resO/PcRF/9vKETOKma5D2sSUKo8mSL1vz03IgVhyHuCrlzbDYMLrXIl9CcyGnYTMG2Zg0WAk62w==} + '@tsparticles/interaction-external-connect@3.7.1': + resolution: {integrity: sha512-hqx0ANIbjLIz/nxmk0LvqANBiNLLmVybbCA7N+xDHtEORvpKjNlKEvMz6Razocl6vRjoHZ/olSwcxIG84dh/cg==} - '@types/chrome@0.0.281': - resolution: {integrity: sha512-MH+8FFrJ1POZwKnKRBa+jZcVp+yCFxes6PYKvgFd0qLTzoQe+TdejC3dkA8gSs8UGjFKrKzu4AkZypmswv0NOg==} + '@tsparticles/interaction-external-grab@3.7.1': + resolution: {integrity: sha512-JMYpFW+7YvkpK5MYlt4Ec3Gwb5ZxS7RLVL8IRUSd5yJOw25husPTYg+FQywxrt5WhKe+tPsCAYo+uGIbTTHi9w==} - '@types/classnames@2.3.4': - resolution: {integrity: sha512-dwmfrMMQb9ujX1uYGvB5ERDlOzBNywnZAZBtOe107/hORWP05ESgU4QyaanZMWYYfd2BzrG78y13/Bju8IQcMQ==} + '@tsparticles/interaction-external-pause@3.7.1': + resolution: {integrity: sha512-Kkp+7sCe24hawH0XvS1V6UCCuHfMvpLK7oseqSam9Gt4SyGrFvaqIXxkjXhRhn9MysJyKFPBV4/dtBM1HR9p6A==} + + '@tsparticles/interaction-external-push@3.7.1': + resolution: {integrity: sha512-4VoaR5jvXgQdB7irtq4uSZYr5c+D6TBTVEnLVpBfJhUs6jhw6mgN5g7yp5izIYkK0AlcO431MHn8dvJacvRLDw==} + + '@tsparticles/interaction-external-remove@3.7.1': + resolution: {integrity: sha512-FRBW7U7zD5MkO6/b7e8iSMk/UTtRLY2XiIVFZNsKri3Re3yPpvZzzd5tl2YlYGQlg1Xc+K8SJYMQQA3PtgQ/Tg==} + + '@tsparticles/interaction-external-repulse@3.7.1': + resolution: {integrity: sha512-mwM06dVmg2FEvHMQsPOfRBQWACbjf3qnelODkqI9DSVxQ0B8DESP4BYNXyraFGYv00YiPzRv5Xy/uejHdbsQUA==} + + '@tsparticles/interaction-external-slow@3.7.1': + resolution: {integrity: sha512-CfCAs3kUQC3pLOj0dbzn5AolQyBHgjxORLdfnYBhepvFV1BXB+4ytChRfXBzjykBPI6U+rCnw5Fk/vVjAroSFA==} + + '@tsparticles/interaction-external-trail@3.7.1': + resolution: {integrity: sha512-M7lNQUWP15m8YIDP/JZcZAXaVJLqdwpBs0Uv9F6dU6jsnNXwwHFVFZ+1icrnlbgl9k/Ehhodbdo5weE7GHhQhQ==} + + '@tsparticles/interaction-particles-attract@3.7.1': + resolution: {integrity: sha512-UABbBORKaiItAT8vR0t4ye2H3VE6/Ah4zcylBlnq0Jd5yDkyP4rnkwhicaY6y4Zlfwyx+0PWdAC4f/ziFAyObg==} + + '@tsparticles/interaction-particles-collisions@3.7.1': + resolution: {integrity: sha512-0GY9++Gn2KXViyeifXWkH7a2UO5+uRwyS1rDeTN8eleyiq2j9zQf4xztZEIft8T0hTetq2rkWxQ92j2kev6NVA==} + + '@tsparticles/interaction-particles-links@3.7.1': + resolution: {integrity: sha512-BxCXAAOBNmEvlyOQzwprryW8YdtMIop2v4kgSCff5MCtDwYWoQIfzaQlWbBAkD9ey6BoF8iMjhBUaY1MnDecTA==} + + '@tsparticles/move-base@3.7.1': + resolution: {integrity: sha512-LPtMHwJHhzwfRIcSAk814fY9NcRiICwaEbapaJSYyP1DwscSXqOWoyAEWwzV9hMgAcPdsED6nGeg8RCXGm58lw==} + + '@tsparticles/move-parallax@3.7.1': + resolution: {integrity: sha512-B40azo6EJyMdI+kmIxpqWDaObPwODTYLDCikzkZ73n5tS6OhFUlkz81Scfo+g1iGTdryKFygUKhVGcG1EFuA5g==} + + '@tsparticles/plugin-absorbers@3.7.1': + resolution: {integrity: sha512-3s+fILLV1tdKOq/bXwfoxFVbzkWwXpdWTC2C0QIP6BFwDSQqV5txluiLEf7SCf8C5etQ6dstEnOgVbdzK7+eWA==} + + '@tsparticles/plugin-easing-quad@3.7.1': + resolution: {integrity: sha512-nSwKCRe6C/noCi3dyZlm1GiQGask0aXdWDuS36b82iwzwQ01cBTXeXR25mLr4fsfMLFfYAZXyBxEMMpw3rkSiw==} + + '@tsparticles/plugin-emitters-shape-circle@3.7.1': + resolution: {integrity: sha512-eBwktnGROkiyCvtrSwdPpoRbIjQgV/Odq//0dw8D+qUdnox6dNzzhJjz8L2LAA2kQZBqtdBqV2kcx3w5ZdqoEQ==} + + '@tsparticles/plugin-emitters-shape-square@3.7.1': + resolution: {integrity: sha512-nvGBsRLrkiz6Q38TJRl8Y/eu9i1ChQ9oorQydLBok+iZ6MefuOj39iYsAOkD1w9yRVrFWKHG6CR1mmJUniz/HA==} + + '@tsparticles/plugin-emitters@3.7.1': + resolution: {integrity: sha512-WV5Uwxp/Ckqv5kZynTj6mj13jYbQCArNLFv8ks+zjdlteoyT5EhQl4rg+TalaySCb1zCd6Fu2Scp35l3JJgbnw==} + + '@tsparticles/plugin-hex-color@3.7.1': + resolution: {integrity: sha512-7xu3MV8EdNNejjYyEmrq5fCDdYAcqz/9VatLpnwtwR5Q5t2qI0tD4CrcGaFfC/rTAVJacfiJe02UV/hlj03KKA==} + + '@tsparticles/plugin-hsl-color@3.7.1': + resolution: {integrity: sha512-zzAI1CuoCMBJhgeYZ5Rq42nGbPg35ZzIs11eQegjsWG5Msm5QKSj60qPzERnoUcCc4HCKtIWP7rYMz6h3xpoEg==} + + '@tsparticles/plugin-rgb-color@3.7.1': + resolution: {integrity: sha512-taEraTpCYR6jpjflqBL95tN0zFU8JrAChXTt8mxVn7gddxoNMHI/LGymEPRCweLukwV6GQyAGOkeGEdWDPtYTA==} + + '@tsparticles/react@3.0.0': + resolution: {integrity: sha512-hjGEtTT1cwv6BcjL+GcVgH++KYs52bIuQGW3PWv7z3tMa8g0bd6RI/vWSLj7p//NZ3uTjEIeilYIUPBh7Jfq/Q==} + peerDependencies: + '@tsparticles/engine': ^3.0.2 + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@tsparticles/shape-circle@3.7.1': + resolution: {integrity: sha512-kmOWaUuFwuTtcCFYjuyJbdA5qDqWdGsharLalYnIczkLu2c1I8jJo/OmGePKhWn62ocu7mqKMomfElkIcw2AsA==} + + '@tsparticles/shape-emoji@3.7.1': + resolution: {integrity: sha512-mX18c/xhYVljS/r5Xbowzclw+1YwhtWoQFOOfkmjjZppA+RjgcwSKLvH6E20PaH1yVTjBOfSF+3POKpwsULzTg==} + + '@tsparticles/shape-image@3.7.1': + resolution: {integrity: sha512-eDzfkQhqLY6fb9QH2Vo9TGfdJBFFpYnojhxQxc7IdzIwOFMD3JK4B52RVl9oowR+rNE8dNp6P2L+eMAF4yld0g==} + + '@tsparticles/shape-line@3.7.1': + resolution: {integrity: sha512-lMPYApUpg7avxmYPfHHr4dQepZSNn/g0Q1/g2+lnTi8ZtUBiCZ2WMVy9R3GOzyozbnzigLQ6AJRnOpsUZV7H4g==} + + '@tsparticles/shape-polygon@3.7.1': + resolution: {integrity: sha512-5FrRfpYC3qnvV2nXBLE4Q0v+SMNWJO8xgzh6MBFwfptvqH4EOrqc/58eS5x0jlf+evwf9LjPgeGkOTcwaHHcYQ==} + + '@tsparticles/shape-square@3.7.1': + resolution: {integrity: sha512-7VCqbRwinjBZ+Ryme27rOtl+jKrET8qDthqZLrAoj3WONBqyt+R9q6SXAJ9WodqEX68IBvcluqbFY5qDZm8iAQ==} + + '@tsparticles/shape-star@3.7.1': + resolution: {integrity: sha512-3G4oipioyWKLEQYT11Sx3k6AObu3dbv/A5LRqGGTQm5IR6UACa+INwykZYI0a+MdJJMb83E0e4Fn3hlZbi0/8w==} + + '@tsparticles/shape-text@3.7.1': + resolution: {integrity: sha512-aU1V9O8uQQBlL0jGFh9Q0b5vQ1Ji6Oo5ptyyj5yJ5uP/ZU00L0Vhk4DNyLXpaU0+H6OBoPpCqnvEsZBB9/HmCQ==} + + '@tsparticles/slim@3.7.1': + resolution: {integrity: sha512-OtJEhud2KleX7OxiG2r/VYriHNIwTpFm3sPFy4EOJzAD0EW7KZoKXGpGn5gwGI1NWeB0jso92yNTrTC2ZTW0qw==} + + '@tsparticles/updater-color@3.7.1': + resolution: {integrity: sha512-QimV3yn17dcdJx7PpTwLtw9BhkQ0q8qFF035OdcZpnynBPAO/hg0zvSMpMGoeuDVFH02wWBy4h2/BYCv6wh6Sw==} + + '@tsparticles/updater-destroy@3.7.1': + resolution: {integrity: sha512-krXNoMDKyeyE/ZjQh3LVjrLYivFefQOQ9i+B7RpMe7x4h+iRgpB6npTCqidGQ82+hZ8G6xfQ9ToduebWwK4JGg==} + + '@tsparticles/updater-life@3.7.1': + resolution: {integrity: sha512-NY5gUrgO5AsARNC0usP9PKahXf7JCxbP/H1vzTfA0SJw4veANfWTldOvhIlcm2CHVP5P1b827p0hWsBHECwz7A==} + + '@tsparticles/updater-opacity@3.7.1': + resolution: {integrity: sha512-YcyviCooTv7SAKw7sxd84CfJqZ7dYPSdYZzCpedV6TKIObRiwLqXlyLXQGJ3YltghKQSCSolmVy8woWBCDm1qA==} + + '@tsparticles/updater-out-modes@3.7.1': + resolution: {integrity: sha512-Cb5sWquRtUYLSiFpmBjjYKRdpNV52diCo9+qMtK1oVlldDBhUwqO+1TQjdlaA2yl5DURlY9ZfOHXvY+IT7CHCw==} + + '@tsparticles/updater-roll@3.7.1': + resolution: {integrity: sha512-gHLRqpTGVGPJBEAIPUiYVembIn5bcaTXXxsUJEM/IN+GIOvj2uZZGZ4r2aFTA6WugqEbJsJdblDSvMfouyz7Ug==} + + '@tsparticles/updater-rotate@3.7.1': + resolution: {integrity: sha512-toVHwl+h6SvtA8dyxSA2kMH2QdDA71vehuAa+HoRqf1y06h5kxyYiMKZFHCqDJ6lFfRPs47MjrC9dD2bDz14MQ==} + + '@tsparticles/updater-size@3.7.1': + resolution: {integrity: sha512-+Y0H0PnDJVIsJ+zHTyubYu1jtRFmVnY1dAv3VCjScIDw6bcpL/ol+HrtHTGIX0WbMyUfjCyALfAoaXi/Wm8VcQ==} + + '@tsparticles/updater-stroke-color@3.7.1': + resolution: {integrity: sha512-VHhQkCNuxjx/Hy7A+g0Yijb24T0+wQ3jNsF/yfrR9dEdZWSBiimZLvV1bilPdAeEtieAJTAZo2VNhcD1snF0iQ==} + + '@tsparticles/updater-tilt@3.7.1': + resolution: {integrity: sha512-pSOXoXPre1VPKC5nC5GW0L9jw63w1dVdsDdggEau7MP9xO7trko9L/KyayBX12Y4Ief1ca12Incxxr67hw7GGA==} + + '@tsparticles/updater-twinkle@3.7.1': + resolution: {integrity: sha512-maRTqPbeZcxBK6s1ry+ih71qSVaitfP1KTrAKR38v26GMwyO6z+zYV2bu9WTRt21FRFAoxlMLWxNu21GtQoXDA==} + + '@tsparticles/updater-wobble@3.7.1': + resolution: {integrity: sha512-YIlNg4L0w4egQJhPLpgcvcfv9+X621+cQsrdN9sSmajxhhwtEQvQUvFUzGTcvpjVi+GcBNp0t4sCKEzoP8iaYw==} + + '@types/accepts@1.3.7': + resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + + '@types/bn.js@4.11.6': + resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + + '@types/bn.js@5.1.6': + resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + + '@types/chrome@0.0.186': + resolution: {integrity: sha512-Ykpf95dbv0resO/PcRF/9vKETOKma5D2sSUKo8mSL1vz03IgVhyHuCrlzbDYMLrXIl9CcyGnYTMG2Zg0WAk62w==} + + '@types/chrome@0.0.281': + resolution: {integrity: sha512-MH+8FFrJ1POZwKnKRBa+jZcVp+yCFxes6PYKvgFd0qLTzoQe+TdejC3dkA8gSs8UGjFKrKzu4AkZypmswv0NOg==} + + '@types/classnames@2.3.4': + resolution: {integrity: sha512-dwmfrMMQb9ujX1uYGvB5ERDlOzBNywnZAZBtOe107/hORWP05ESgU4QyaanZMWYYfd2BzrG78y13/Bju8IQcMQ==} deprecated: This is a stub types definition. classnames provides its own type definitions, so you do not need this installed. '@types/connect@3.4.38': @@ -2864,6 +2710,9 @@ packages: '@types/cookies@0.9.0': resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} + '@types/css-font-loading-module@0.0.7': + resolution: {integrity: sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==} + '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} @@ -2891,17 +2740,14 @@ packages: '@types/d3-timer@3.0.2': resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} - '@types/debounce@1.2.4': - resolution: {integrity: sha512-jBqiORIzKDOToaF63Fm//haOCHuwQuLa2202RK4MozpA6lh93eCBc+/8+wZn5OzjJt3ySdc+74SXWXB55Ewtyw==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - '@types/eslint@7.29.0': - resolution: {integrity: sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==} + '@types/eslint@8.56.12': + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} '@types/eslint@9.6.1': resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} @@ -2912,8 +2758,8 @@ packages: '@types/events@3.0.3': resolution: {integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==} - '@types/express-serve-static-core@5.0.1': - resolution: {integrity: sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==} + '@types/express-serve-static-core@5.0.2': + resolution: {integrity: sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==} '@types/express@5.0.0': resolution: {integrity: sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==} @@ -2945,6 +2791,9 @@ packages: '@types/http-assert@1.5.6': resolution: {integrity: sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==} + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} @@ -2972,6 +2821,9 @@ packages: '@types/keygrip@1.0.6': resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/koa-compose@3.2.8': resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} @@ -2996,11 +2848,14 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + '@types/mixpanel-browser@2.50.2': + resolution: {integrity: sha512-Iw8cBzplUPfHoeYuasqeYwdbGTNXhN+5kFT9kU+C7zm0NtaiPpKoiuzITr2ZH9KgBsWi2MbG0FOzIg9sQepauQ==} + '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - '@types/node-forge@1.3.11': - resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + '@types/node@16.18.119': + resolution: {integrity: sha512-ia7V9a2FnhUFfetng4/sRPBMTwHZUkPFY736rb1cg9AgG7MZdR97q7/nLR9om+sq5f1la9C857E0l/nrI0RiFQ==} '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} @@ -3008,6 +2863,9 @@ packages: '@types/node@22.7.5': resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + '@types/node@22.9.3': + resolution: {integrity: sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==} + '@types/offscreencanvas@2019.7.3': resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} @@ -3032,14 +2890,8 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@17.0.25': - resolution: {integrity: sha512-urx7A7UxkZQmThYA4So0NelOVjx3V4rNFVJwp0WZlbIK5eM4rNJDiN3R/E9ix0MBh6kAEojk/9YL+Te6D9zHNA==} - - '@types/react-reconciler@0.26.7': - resolution: {integrity: sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==} - - '@types/react-reconciler@0.28.8': - resolution: {integrity: sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==} + '@types/react-dom@18.3.1': + resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} '@types/react-router-dom@5.3.3': resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} @@ -3050,11 +2902,11 @@ packages: '@types/react-transition-group@4.4.11': resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==} - '@types/react@17.0.83': - resolution: {integrity: sha512-l0m4ArKJvmFtR4e8UmKrj1pB4tUgOhJITf+mADyF/p69Ts1YAR/E+G9XEM0mHXKVRa1dQNHseyyDNzeuAXfXQw==} + '@types/react@18.3.12': + resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} - '@types/scheduler@0.16.8': - resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} '@types/secp256k1@4.0.6': resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} @@ -3080,9 +2932,6 @@ packages: '@types/w3c-web-hid@1.0.6': resolution: {integrity: sha512-IWyssXmRDo6K7s31dxf+U+x/XUWuVsl9qUIYbJmpUHPcTv/COfBCKw/F0smI45+gPV34brjyP30BFcIsHgYWLA==} - '@types/webxr@0.5.20': - resolution: {integrity: sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==} - '@types/ws@8.5.3': resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} @@ -3095,6 +2944,9 @@ packages: '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@typescript-eslint/eslint-plugin@8.15.0': resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3182,19 +3034,6 @@ packages: resolution: {integrity: sha512-ubJLn+vGb8sTdBFX6xAh4kjR5idrtS3RBngQWaJJJpEPBQmxMb8pM2q0FIRs8Is4K6jKy+uEhusMV+7ZBmTzjw==} engines: {node: '>=16'} - '@walletconnect/browser-utils@1.8.0': - resolution: {integrity: sha512-Wcqqx+wjxIo9fv6eBUFHPsW1y/bGWWRboni5dfD8PtOmrihrEpOCmvRJe4rfl7xgJW8Ea9UqKEaq0bIRLHlK4A==} - - '@walletconnect/client@1.8.0': - resolution: {integrity: sha512-svyBQ14NHx6Cs2j4TpkQaBI/2AF4+LXz64FojTjMtV4VMMhl81jSO1vNeg+yYhQzvjcGH/GpSwixjyCW0xFBOQ==} - deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' - - '@walletconnect/core@1.8.0': - resolution: {integrity: sha512-aFTHvEEbXcZ8XdWBw6rpQDte41Rxwnuk3SgTD8/iKGSRTni50gI9S3YEzMj05jozSiOBxQci4pJDMVhIUMtarw==} - - '@walletconnect/core@2.10.3': - resolution: {integrity: sha512-zvV7Rr48Mftm1+eWr+eTyriV3BFhhY703hGmi2+dA1qMe/5FuIQZs24anBWQapfJuL+CgdGczb/BI9/x3NX7jA==} - '@walletconnect/core@2.11.0': resolution: {integrity: sha512-2Tjp5BCevI7dbmqo/OrCjX4tqgMqwJNQLlQAlphqPfvwlF9+tIu6pGcVbSN3U9zyXzWIZCeleqEaWUeSeET4Ew==} @@ -3227,9 +3066,6 @@ packages: '@walletconnect/heartbeat@1.2.2': resolution: {integrity: sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==} - '@walletconnect/iso-crypto@1.8.0': - resolution: {integrity: sha512-pWy19KCyitpfXb70hA73r9FcvklS+FvO9QUIttp3c2mfW8frxgYeRXfxLRCIQTkaYueRKvdqPjbyhPLam508XQ==} - '@walletconnect/jsonrpc-http-connection@1.0.8': resolution: {integrity: sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==} @@ -3248,9 +3084,6 @@ packages: '@walletconnect/jsonrpc-utils@1.0.8': resolution: {integrity: sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==} - '@walletconnect/jsonrpc-ws-connection@1.0.13': - resolution: {integrity: sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg==} - '@walletconnect/jsonrpc-ws-connection@1.0.14': resolution: {integrity: sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA==} @@ -3307,9 +3140,6 @@ packages: '@walletconnect/relay-auth@1.0.4': resolution: {integrity: sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==} - '@walletconnect/safe-json@1.0.0': - resolution: {integrity: sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg==} - '@walletconnect/safe-json@1.0.2': resolution: {integrity: sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==} @@ -3323,19 +3153,9 @@ packages: '@walletconnect/sign-client@2.17.2': resolution: {integrity: sha512-/wigdCIQjlBXSWY43Id0IPvZ5biq4HiiQZti8Ljvx408UYjmqcxcBitbj2UJXMYkid7704JWAB2mw32I1HgshQ==} - '@walletconnect/socket-transport@1.8.0': - resolution: {integrity: sha512-5DyIyWrzHXTcVp0Vd93zJ5XMW61iDM6bcWT4p8DTRfFsOtW46JquruMhxOLeCOieM4D73kcr3U7WtyR4JUsGuQ==} - '@walletconnect/time@1.0.2': resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} - '@walletconnect/types@1.8.0': - resolution: {integrity: sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg==} - deprecated: 'WalletConnect''s v1 SDKs are now deprecated. Please upgrade to a v2 SDK. For details see: https://docs.walletconnect.com/' - - '@walletconnect/types@2.10.3': - resolution: {integrity: sha512-HcLR4JKTQyVoconQ8CqxtPrIVYHMQwZtvBq5RD0InuhxChabu2GsxtSfmz+M7ShzKWItohZx1EQJKYZKYw9ekA==} - '@walletconnect/types@2.11.0': resolution: {integrity: sha512-AB5b1lrEbCGHxqS2vqfCkIoODieH+ZAUp9rA1O2ftrhnqDJiJK983Df87JhYhECsQUBHHfALphA8ydER0q+9sw==} @@ -3348,12 +3168,6 @@ packages: '@walletconnect/universal-provider@2.11.0': resolution: {integrity: sha512-zgJv8jDvIMP4Qse/D9oIRXGdfoNqonsrjPZanQ/CHNe7oXGOBiQND2IIeX+tS0H7uNA0TPvctljCLiIN9nw4eA==} - '@walletconnect/utils@1.8.0': - resolution: {integrity: sha512-zExzp8Mj1YiAIBfKNm5u622oNw44WOESzo6hj+Q3apSMIb0Jph9X3GDIdbZmvVZsNPxWDL7uodKgZcCInZv2vA==} - - '@walletconnect/utils@2.10.3': - resolution: {integrity: sha512-9FTujY4t+SrENgvyT84TFsO1iFvix2dWH5C9PmJ3/LMrkYytjszJVMPY5bDG73RBwph9wbeYzPgkGvid2RP63A==} - '@walletconnect/utils@2.11.0': resolution: {integrity: sha512-hxkHPlTlDQILHfIKXlmzgNJau/YcSBC3XHUSuZuKZbNEw3duFT6h6pm3HT/1+j1a22IG05WDsNBuTCRkwss+BQ==} @@ -3366,15 +3180,9 @@ packages: '@walletconnect/web3wallet@1.16.1': resolution: {integrity: sha512-l6jVoLEh/UtRfvYUDs52fN+LYXsBgx3F9WfErJuCSCFfpbxDKIzM2Y9sI0WI1/5dWN5sh24H1zNCXnQ4JJltZw==} - '@walletconnect/window-getters@1.0.0': - resolution: {integrity: sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA==} - '@walletconnect/window-getters@1.0.1': resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} - '@walletconnect/window-metadata@1.0.0': - resolution: {integrity: sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA==} - '@walletconnect/window-metadata@1.0.1': resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==} @@ -3451,6 +3259,9 @@ packages: '@xobotyi/scrollbar-width@1.9.5': resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} + '@xstate/fsm@1.6.5': + resolution: {integrity: sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -3577,8 +3388,8 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - anser@1.4.10: - resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} + ansi-align@2.0.0: + resolution: {integrity: sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==} ansi-colors@3.2.4: resolution: {integrity: sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==} @@ -3648,16 +3459,15 @@ packages: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - arr-diff@4.0.0: resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} engines: {node: '>=0.10.0'} @@ -3735,13 +3545,6 @@ packages: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} - arrify@2.0.1: - resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} - engines: {node: '>=8'} - - asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - asn1.js@4.10.1: resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} @@ -3755,13 +3558,6 @@ packages: resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} engines: {node: '>=0.10.0'} - ast-types-flow@0.0.8: - resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - - ast-types@0.15.2: - resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==} - engines: {node: '>=4'} - async-each@1.0.6: resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} @@ -3800,10 +3596,6 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.10.2: - resolution: {integrity: sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==} - engines: {node: '>=4'} - axios-rate-limit@1.4.0: resolution: {integrity: sha512-uM5PbmSUdSle1I+59Av/wpLuNRobfatIR+FyylSoHcVHT20ohjflNnLMEHZQr7N2QVG/Wlt8jekIPhWwoKtpXQ==} peerDependencies: @@ -3819,34 +3611,12 @@ packages: axios@1.7.7: resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - - babel-core@7.0.0-bridge.0: - resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - babel-eslint@10.1.0: - resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==} - engines: {node: '>=6'} - deprecated: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. - peerDependencies: - eslint: '>= 4.12.1' - babel-jest@27.5.1: resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: '@babel/core': ^7.8.0 - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} @@ -3855,10 +3625,6 @@ packages: resolution: {integrity: sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -3878,15 +3644,6 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-syntax-hermes-parser@0.23.1: - resolution: {integrity: sha512-uNLD0tk2tLUjGFdmCk+u/3FEw2o+BAwW4g+z2QVlxJrzZYOOPADroEcNtTPt5lNiScctaUmnsTkVEnOwZUOLhA==} - - babel-plugin-syntax-hermes-parser@0.25.1: - resolution: {integrity: sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==} - - babel-plugin-transform-flow-enums@0.0.2: - resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} - babel-preset-current-node-syntax@1.1.0: resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} peerDependencies: @@ -3898,12 +3655,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -3913,6 +3664,10 @@ packages: base-x@3.0.10: resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} + base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -3961,9 +3716,6 @@ packages: bn.js@4.11.6: resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - bn.js@4.11.8: - resolution: {integrity: sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==} - bn.js@4.12.1: resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} @@ -3980,10 +3732,18 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + boolean@3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + borc@2.1.2: resolution: {integrity: sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==} engines: {node: '>=4'} + boxen@1.3.0: + resolution: {integrity: sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==} + engines: {node: '>=4'} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -4035,10 +3795,6 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - bs58@2.0.1: resolution: {integrity: sha512-77ld2g7Hn1GyIUpuUVfbZdhO1q9R9gv/GYam4HAeAW/tzhQDrbJ2ZttN1tIe4hmKrWFE+oUtAhBNx/EA5SVdTg==} @@ -4051,6 +3807,9 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -4081,22 +3840,18 @@ packages: resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} engines: {node: '>=0.10.0'} + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} - caller-callsite@2.0.0: - resolution: {integrity: sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==} - engines: {node: '>=4'} - - caller-path@2.0.0: - resolution: {integrity: sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==} - engines: {node: '>=4'} - - callsites@2.0.0: - resolution: {integrity: sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==} - engines: {node: '>=4'} - callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -4120,8 +3875,12 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001683: - resolution: {integrity: sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==} + caniuse-lite@1.0.30001684: + resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==} + + capture-stack-trace@1.0.2: + resolution: {integrity: sha512-X/WM2UQs6VMHUtjUDnZTRI+i1crWteJySFzr9UpGoQa4WQffXVTTXuekjl7TjZRlcF2XfjgITT0HxZ9RnxeT0w==} + engines: {node: '>=0.10.0'} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -4159,20 +3918,12 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chrome-launcher@0.15.2: - resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==} - engines: {node: '>=12.13.0'} - hasBin: true - chrome-trace-event@1.0.4: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - chromium-edge-launcher@0.2.0: - resolution: {integrity: sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==} - - ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + ci-info@1.6.0: + resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==} ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} @@ -4199,6 +3950,10 @@ packages: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} + cli-boxes@1.0.0: + resolution: {integrity: sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg==} + engines: {node: '>=0.10.0'} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -4231,6 +3986,9 @@ packages: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} @@ -4303,9 +4061,6 @@ packages: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - compare-versions@4.1.4: resolution: {integrity: sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==} @@ -4326,17 +4081,14 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - confusing-browser-globals@1.0.11: - resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + configstore@3.1.5: + resolution: {integrity: sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==} + engines: {node: '>=4'} connect-history-api-fallback@1.6.0: resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} engines: {node: '>=0.8'} - connect@3.7.0: - resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} - engines: {node: '>= 0.10.0'} - consola@3.2.3: resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} engines: {node: ^14.18.0 || >=16.10.0} @@ -4387,10 +4139,6 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cosmiconfig@5.2.1: - resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} - engines: {node: '>=4'} - cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -4403,18 +4151,28 @@ packages: create-ecdh@4.0.4: resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + create-error-class@3.0.2: + resolution: {integrity: sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==} + engines: {node: '>=0.10.0'} + create-hash@1.2.0: resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} create-hmac@1.1.7: resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-fetch@3.1.8: resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} cross-fetch@4.0.0: resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + cross-spawn@6.0.6: resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} engines: {node: '>=4.8'} @@ -4433,6 +4191,10 @@ packages: crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + crypto-random-string@1.0.0: + resolution: {integrity: sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==} + engines: {node: '>=4'} + css-in-js-utils@3.1.0: resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} @@ -4540,9 +4302,6 @@ packages: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} - damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - data-urls@2.0.0: resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} engines: {node: '>=10'} @@ -4619,6 +4378,10 @@ packages: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} engines: {node: '>=0.10'} + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} @@ -4630,6 +4393,10 @@ packages: resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==} engines: {node: '>= 0.4'} + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -4641,6 +4408,10 @@ packages: resolution: {integrity: sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==} engines: {node: '>=6'} + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -4678,9 +4449,6 @@ packages: delimit-stream@0.1.0: resolution: {integrity: sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==} - denodeify@1.2.1: - resolution: {integrity: sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==} - depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} @@ -4703,9 +4471,6 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - detect-browser@5.2.0: - resolution: {integrity: sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA==} - detect-browser@5.3.0: resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} @@ -4729,6 +4494,10 @@ packages: resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} engines: {node: '>=0.3.1'} + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -4792,6 +4561,10 @@ packages: dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dot-prop@4.2.1: + resolution: {integrity: sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==} + engines: {node: '>=4'} + dotenv-defaults@2.0.2: resolution: {integrity: sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==} @@ -4813,6 +4586,9 @@ packages: resolution: {integrity: sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g==} engines: {node: '>=0.10'} + duplexer3@0.1.5: + resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -4828,6 +4604,11 @@ packages: electron-to-chromium@1.5.64: resolution: {integrity: sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==} + electron@23.3.13: + resolution: {integrity: sha512-BaXtHEb+KYKLouUXlUVDa/lj9pj4F5kiE0kwFdJV84Y2EU7euIDgPthfKtchhr5MVHmjtavRMIV/zAwEiSQ9rQ==} + engines: {node: '>= 12.20.55'} + hasBin: true + elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} @@ -4853,9 +4634,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - emojis-list@3.0.0: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} @@ -4885,6 +4663,10 @@ packages: entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + envinfo@7.14.0: resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} engines: {node: '>=4'} @@ -4941,6 +4723,9 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + es6-error@4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -4975,30 +4760,6 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-config-react-app@6.0.0: - resolution: {integrity: sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^4.0.0 - '@typescript-eslint/parser': ^4.0.0 - babel-eslint: ^10.0.0 - eslint: ^7.5.0 - eslint-plugin-flowtype: ^5.2.0 - eslint-plugin-import: ^2.22.0 - eslint-plugin-jest: ^24.0.0 - eslint-plugin-jsx-a11y: ^6.3.1 - eslint-plugin-react: ^7.20.3 - eslint-plugin-react-hooks: ^4.0.8 - eslint-plugin-testing-library: ^3.9.0 - typescript: '*' - peerDependenciesMeta: - eslint-plugin-jest: - optional: true - eslint-plugin-testing-library: - optional: true - typescript: - optional: true - eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} @@ -5036,12 +4797,6 @@ packages: eslint-import-resolver-webpack: optional: true - eslint-plugin-flowtype@5.10.0: - resolution: {integrity: sha512-vcz32f+7TP+kvTUyMXZmCnNujBQZDNmcqPImw8b9PZ+16w1Qdm6ryRuYZYVaG9xRqqmAPr2Cs9FAX5gN+x/bjw==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - eslint: ^7.1.0 - eslint-plugin-import@2.31.0: resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} @@ -5058,12 +4813,6 @@ packages: peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - eslint-plugin-jsx-a11y@6.10.2: - resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-prettier@3.4.1: resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==} engines: {node: '>=6.0.0'} @@ -5087,20 +4836,6 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-plugin-unused-imports@2.0.0: - resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - - eslint-rule-composer@0.3.0: - resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} - engines: {node: '>=4.0.0'} - eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -5113,10 +4848,6 @@ packages: resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5125,12 +4856,12 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-webpack-plugin@2.7.0: - resolution: {integrity: sha512-bNaVVUvU4srexGhVcayn/F4pJAz19CWBkKoMx7aSQ4wtTbZQCnG5O9LHCE42mM+JSKOUp7n6vd5CIwzj7lOVGA==} - engines: {node: '>= 10.13.0'} + eslint-webpack-plugin@4.2.0: + resolution: {integrity: sha512-rsfpFQ01AWQbqtjgPRr2usVRxhWDuG0YDYcG8DJOteD3EFnpeuYuOwk0PQiN7PRBTqS6ElNdtPZPggj8If9WnA==} + engines: {node: '>= 14.15.0'} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - webpack: ^4.0.0 || ^5.0.0 + eslint: ^8.0.0 || ^9.0.0 + webpack: ^5.0.0 eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} @@ -5305,6 +5036,10 @@ packages: evp_bytestokey@1.0.3: resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + execa@0.7.0: + resolution: {integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==} + engines: {node: '>=4'} + execa@1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} @@ -5329,9 +5064,6 @@ packages: resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - express@4.21.1: resolution: {integrity: sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==} engines: {node: '>= 0.10.0'} @@ -5351,6 +5083,11 @@ packages: resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} engines: {node: '>=0.10.0'} + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -5401,6 +5138,12 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -5433,18 +5176,10 @@ packages: resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} engines: {node: '>=0.10.0'} - finalhandler@1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} - engines: {node: '>= 0.8'} - finalhandler@1.3.1: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} - find-cache-dir@2.1.0: - resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} - engines: {node: '>=6'} - find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} @@ -5482,17 +5217,10 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - flow-enums-runtime@0.0.6: - resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==} - flow-native-token-registry@0.1.6: resolution: {integrity: sha512-HePWKiitTx0KnQSqB8QLUJzRQDE9WRVmz5lHCRTEPWs+7EyoRPN5q0pcq4gQ0rpz6XxXPX5wm6KGiQTbbRBoWQ==} engines: {node: '>=10'} - flow-parser@0.254.1: - resolution: {integrity: sha512-dyUrQD6ZyI4PVQppj8PP5kj6BVThK8FprAcPCnJNLIZM7zcAL6/xGS1EE1haWv2HcO/dHy7GSwOAO59uaffjYw==} - engines: {node: '>=0.4.0'} - follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -5548,6 +5276,10 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -5598,10 +5330,18 @@ packages: get-port-please@3.1.2: resolution: {integrity: sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==} + get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + get-stream@4.1.0: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} engines: {node: '>=6'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -5639,6 +5379,14 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported + global-agent@3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + + global-dirs@0.1.1: + resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} + engines: {node: '>=4'} + globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -5676,6 +5424,14 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + got@6.7.1: + resolution: {integrity: sha512-Y/K3EDuiQN9rTZhBvPRWMLXIKdeD1Rj0nzunfoi0Yyn5WBEbzxXKU9Ub2X41oZBagVWOBU3MuDonFMgPWQFnwg==} + engines: {node: '>=4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -5737,9 +5493,9 @@ packages: resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} engines: {node: '>=0.10.0'} - hash-base@3.0.4: - resolution: {integrity: sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==} - engines: {node: '>=4'} + hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -5758,24 +5514,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - hermes-estree@0.23.1: - resolution: {integrity: sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==} - - hermes-estree@0.24.0: - resolution: {integrity: sha512-LyoXLB7IFzeZW0EvAbGZacbxBN7t6KKSDqFJPo3Ydow7wDlrDjXwsdiAHV6XOdvEN9MEuWXsSIFN4tzpyrXIHw==} - - hermes-estree@0.25.1: - resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} - - hermes-parser@0.23.1: - resolution: {integrity: sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==} - - hermes-parser@0.24.0: - resolution: {integrity: sha512-IJooSvvu2qNRe7oo9Rb04sUT4omtZqZqf9uq9WM25Tb6v3usmvA93UqfnnoWs5V0uYjEl9Al6MNU10MCGKLwpg==} - - hermes-parser@0.25.1: - resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hey-listen@1.0.8: resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} @@ -5830,6 +5568,9 @@ packages: htmlparser2@6.1.0: resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + http-deceiver@1.2.7: resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} @@ -5860,6 +5601,10 @@ packages: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} @@ -5883,9 +5628,14 @@ packages: hyphenate-style-name@1.1.0: resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} - i18next@20.6.1: - resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} - + i18next@24.0.0: + resolution: {integrity: sha512-ORGCwMrXxpmB/AljFbGEe0UK/9Pz6umb9aZgLZ9qJGE+kjKhlnLj423WX2mt+N0MlEJ78pQXFMBmeMzrkLxriQ==} + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + iconfont-parser@1.0.0: resolution: {integrity: sha512-3RJceYHEjaqYyeDdfSAb1vP1x1Eb7ZtC9Xwetj+axm85sBlJU7HMvdNLVpwm/3g5eghYOdkQK+epUITZGAIqKQ==} @@ -5912,22 +5662,17 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - image-size@1.1.1: - resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==} - engines: {node: '>=16.x'} - hasBin: true - immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} - import-fresh@2.0.0: - resolution: {integrity: sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==} - engines: {node: '>=4'} - import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} + import-lazy@2.1.0: + resolution: {integrity: sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==} + engines: {node: '>=4'} + import-local@2.0.0: resolution: {integrity: sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==} engines: {node: '>=6'} @@ -5956,6 +5701,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + inline-style-parser@0.1.1: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} @@ -5982,9 +5730,6 @@ packages: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} engines: {node: '>= 0.10'} - invariant@2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - ip-regex@2.1.0: resolution: {integrity: sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==} engines: {node: '>=4'} @@ -6055,6 +5800,10 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} + is-ci@1.2.1: + resolution: {integrity: sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==} + hasBin: true + is-core-module@2.15.1: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} @@ -6079,15 +5828,6 @@ packages: resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} engines: {node: '>= 0.4'} - is-directory@0.3.1: - resolution: {integrity: sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==} - engines: {node: '>=0.10.0'} - - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6105,8 +5845,9 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + is-finalizationregistry@1.1.0: + resolution: {integrity: sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==} + engines: {node: '>= 0.4'} is-fullwidth-code-point@2.0.0: resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} @@ -6152,6 +5893,10 @@ packages: engines: {node: '>=14.16'} hasBin: true + is-installed-globally@0.1.0: + resolution: {integrity: sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw==} + engines: {node: '>=4'} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -6164,6 +5909,10 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} + is-npm@1.0.0: + resolution: {integrity: sha512-9r39FIr3d+KD9SbX0sfMsHzb5PP3uimOiwr3YupUaUFG4W0l1U57Rx3utpttV7qz5U3jmrO5auUa04LU9pyHsg==} + engines: {node: '>=0.10.0'} + is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} @@ -6176,6 +5925,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + is-path-cwd@2.2.0: resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} engines: {node: '>=6'} @@ -6184,6 +5937,10 @@ packages: resolution: {integrity: sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==} engines: {node: '>=6'} + is-path-inside@1.0.1: + resolution: {integrity: sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==} + engines: {node: '>=0.10.0'} + is-path-inside@2.1.0: resolution: {integrity: sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==} engines: {node: '>=6'} @@ -6207,10 +5964,18 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-redirect@1.0.0: + resolution: {integrity: sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==} + engines: {node: '>=0.10.0'} + is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} + is-retry-allowed@1.2.0: + resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} + engines: {node: '>=0.10.0'} + is-set@2.0.3: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} @@ -6269,10 +6034,6 @@ packages: resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} engines: {node: '>=4'} - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} @@ -6347,11 +6108,6 @@ packages: resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} engines: {node: '>= 0.4'} - its-fine@1.2.5: - resolution: {integrity: sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA==} - peerDependencies: - react: '>=18.0' - jest-changed-files@27.5.1: resolution: {integrity: sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -6399,26 +6155,14 @@ packages: resolution: {integrity: sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-get-type@27.5.1: resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-haste-map@27.5.1: resolution: {integrity: sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-jasmine2@27.5.1: resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -6435,18 +6179,10 @@ packages: resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-mock@27.5.1: resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-pnp-resolver@1.2.3: resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} @@ -6460,10 +6196,6 @@ packages: resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-resolve-dependencies@27.5.1: resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -6500,10 +6232,6 @@ packages: resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-watcher@27.5.1: resolution: {integrity: sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -6547,18 +6275,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsc-android@250231.0.0: - resolution: {integrity: sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==} - - jsc-safe-url@0.2.4: - resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} - - jscodeshift@0.14.0: - resolution: {integrity: sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==} - hasBin: true - peerDependencies: - '@babel/preset-env': ^7.1.6 - jsdoc-type-pratt-parser@4.0.0: resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} engines: {node: '>=12.0.0'} @@ -6602,6 +6318,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json-text-sequence@0.1.1: resolution: {integrity: sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==} @@ -6614,6 +6333,9 @@ packages: engines: {node: '>=6'} hasBin: true + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -6697,15 +6419,9 @@ packages: koa-compose@4.1.0: resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} - konva@9.3.16: - resolution: {integrity: sha512-qa47cefGDDHzkToGRGDsy24f/Njrz7EHP56jQ8mlDcjAPO7vkfTDeoBDIfmF7PZtpfzDdooafQmEUJMDU2F7FQ==} - - language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} - - language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} + latest-version@3.1.0: + resolution: {integrity: sha512-Be1YRHWWlZaSsrz2U+VInk+tO0EwLIyV+23RhWLINJYwg/UIikxjlj3MhH37/6/EDCAusjajvMkMMUXRaMWl/w==} + engines: {node: '>=4'} leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} @@ -6715,12 +6431,15 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + libsodium-wrappers@0.7.15: + resolution: {integrity: sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==} + + libsodium@0.7.15: + resolution: {integrity: sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==} + lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} - lighthouse-logger@1.4.2: - resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} - lilconfig@3.1.2: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} @@ -6787,15 +6506,9 @@ packages: lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.throttle@4.1.1: - resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -6833,9 +6546,20 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lowercase-keys@1.0.1: + resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} + engines: {node: '>=0.10.0'} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -6843,9 +6567,9 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} + make-dir@1.3.0: + resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} + engines: {node: '>=4'} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -6876,8 +6600,9 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - marky@1.2.5: - resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} + matcher@3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} @@ -6958,64 +6683,6 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - metro-babel-transformer@0.81.0: - resolution: {integrity: sha512-Dc0QWK4wZIeHnyZ3sevWGTnnSkIDDn/SWyfrn99zbKbDOCoCYy71PAn9uCRrP/hduKLJQOy+tebd63Rr9D8tXg==} - engines: {node: '>=18.18'} - - metro-cache-key@0.81.0: - resolution: {integrity: sha512-qX/IwtknP9bQZL78OK9xeSvLM/xlGfrs6SlUGgHvrxtmGTRSsxcyqxR+c+7ch1xr05n62Gin/O44QKg5V70rNQ==} - engines: {node: '>=18.18'} - - metro-cache@0.81.0: - resolution: {integrity: sha512-DyuqySicHXkHUDZFVJmh0ygxBSx6pCKUrTcSgb884oiscV/ROt1Vhye+x+OIHcsodyA10gzZtrVtxIFV4l9I4g==} - engines: {node: '>=18.18'} - - metro-config@0.81.0: - resolution: {integrity: sha512-6CinEaBe3WLpRlKlYXXu8r1UblJhbwD6Gtnoib5U8j6Pjp7XxMG9h/DGMeNp9aGLDu1OieUqiXpFo7O0/rR5Kg==} - engines: {node: '>=18.18'} - - metro-core@0.81.0: - resolution: {integrity: sha512-CVkM5YCOAFkNMvJai6KzA0RpztzfEKRX62/PFMOJ9J7K0uq/UkOFLxcgpcncMIrfy0PbfEj811b69tjULUQe1Q==} - engines: {node: '>=18.18'} - - metro-file-map@0.81.0: - resolution: {integrity: sha512-zMDI5uYhQCyxbye/AuFx/pAbsz9K+vKL7h1ShUXdN2fz4VUPiyQYRsRqOoVG1DsiCgzd5B6LW0YW77NFpjDQeg==} - engines: {node: '>=18.18'} - - metro-minify-terser@0.81.0: - resolution: {integrity: sha512-U2ramh3W822ZR1nfXgIk+emxsf5eZSg10GbQrT0ZizImK8IZ5BmJY+BHRIkQgHzWFpExOVxC7kWbGL1bZALswA==} - engines: {node: '>=18.18'} - - metro-resolver@0.81.0: - resolution: {integrity: sha512-Uu2Q+buHhm571cEwpPek8egMbdSTqmwT/5U7ZVNpK6Z2ElQBBCxd7HmFAslKXa7wgpTO2FAn6MqGeERbAtVDUA==} - engines: {node: '>=18.18'} - - metro-runtime@0.81.0: - resolution: {integrity: sha512-6oYB5HOt37RuGz2eV4A6yhcl+PUTwJYLDlY9vhT+aVjbUWI6MdBCf69vc4f5K5Vpt+yOkjy+2LDwLS0ykWFwYw==} - engines: {node: '>=18.18'} - - metro-source-map@0.81.0: - resolution: {integrity: sha512-TzsVxhH83dyxg4A4+L1nzNO12I7ps5IHLjKGZH3Hrf549eiZivkdjYiq/S5lOB+p2HiQ+Ykcwtmcja95LIC62g==} - engines: {node: '>=18.18'} - - metro-symbolicate@0.81.0: - resolution: {integrity: sha512-C/1rWbNTPYp6yzID8IPuQPpVGzJ2rbWYBATxlvQ9dfK5lVNoxcwz77hjcY8ISLsRRR15hyd/zbjCNKPKeNgE1Q==} - engines: {node: '>=18.18'} - hasBin: true - - metro-transform-plugins@0.81.0: - resolution: {integrity: sha512-uErLAPBvttGCrmGSCa0dNHlOTk3uJFVEVWa5WDg6tQ79PRmuYRwzUgLhVzn/9/kyr75eUX3QWXN79Jvu4txt6Q==} - engines: {node: '>=18.18'} - - metro-transform-worker@0.81.0: - resolution: {integrity: sha512-HrQ0twiruhKy0yA+9nK5bIe3WQXZcC66PXTvRIos61/EASLAP2DzEmW7IxN/MGsfZegN2UzqL2CG38+mOB45vg==} - engines: {node: '>=18.18'} - - metro@0.81.0: - resolution: {integrity: sha512-kzdzmpL0gKhEthZ9aOV7sTqvg6NuTxDV8SIm9pf9sO8VVEbKrQk5DNcwupOUjgPPFAuKUc2NkT0suyT62hm2xg==} - engines: {node: '>=18.18'} - hasBin: true - micro-ftch@0.3.1: resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} @@ -7154,6 +6821,14 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -7174,19 +6849,20 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mixin-deep@1.3.2: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} engines: {node: '>=0.10.0'} + mixpanel-browser@2.56.0: + resolution: {integrity: sha512-GYeEz58pV2M9MZtK8vSPL4oJmCwGS08FDDRZvZwr5VJpWdT4Lgyg6zXhmNfCmSTEIw2coaarm7HZ4FL9dAVvnA==} + mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - mlly@1.7.3: resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} @@ -7258,9 +6934,6 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-abort-controller@3.1.1: - resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} - node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} @@ -7270,10 +6943,6 @@ packages: node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} - node-dir@0.1.17: - resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==} - engines: {node: '>= 0.10.5'} - node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} @@ -7319,6 +6988,10 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -7337,9 +7010,6 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nullthrows@1.1.1: - resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} - number-to-bn@1.7.0: resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -7347,10 +7017,6 @@ packages: nwsapi@2.2.13: resolution: {integrity: sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==} - ob1@0.81.0: - resolution: {integrity: sha512-6Cvrkxt1tqaRdWqTAMcVYEiO5i1xcF9y7t06nFdjFqkfPsEloCf8WwhXdwBpNUkVYSQlSGS7cDgVQR86miBfBQ==} - engines: {node: '>=18.18'} - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -7418,10 +7084,6 @@ packages: on-exit-leak-free@0.2.0: resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} - on-finished@2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -7445,10 +7107,6 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - open@7.4.2: - resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} - engines: {node: '>=8'} - opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -7472,6 +7130,10 @@ packages: typescript: optional: true + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -7520,6 +7182,10 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json@4.0.1: + resolution: {integrity: sha512-q/R5GrMek0vzgoomq6rm9OX+3PQve8sLwTirmK30YB3Cu0Bbt9OX9M/SIUnroN5BGJkzwGsFwDaRGD9EwBOlCA==} + engines: {node: '>=4'} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -7620,11 +7286,8 @@ packages: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} - performance-now@0.2.0: - resolution: {integrity: sha512-YHk5ez1hmMR5LOkb9iJkLKqoBlL7WD5M8ljC75ZfzXriuBIVNuecaXuU7e+hOwyqf24Wxhh7Vxgt7Hnw9288Tg==} - - performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} picocolors@0.2.1: resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==} @@ -7787,13 +7450,17 @@ packages: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} - preact@10.24.3: - resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==} + preact@10.25.0: + resolution: {integrity: sha512-6bYnzlLxXV3OSpUxLdaxBmE7PMOu0aR3pG6lryK/0jmvcDFPlcXGQAt5DpK3RITWiDrfYZRI0druyaK/S9kYLg==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prepend-http@1.0.4: + resolution: {integrity: sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==} + engines: {node: '>=0.10.0'} + prettier-linter-helpers@1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} @@ -7810,10 +7477,6 @@ packages: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -7824,8 +7487,9 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - promise@8.3.0: - resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} @@ -7854,6 +7518,9 @@ packages: prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + psl@1.13.0: resolution: {integrity: sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw==} @@ -7906,10 +7573,6 @@ packages: resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} engines: {node: '>=0.6'} - query-string@6.13.5: - resolution: {integrity: sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q==} - engines: {node: '>=6'} - query-string@6.14.1: resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} engines: {node: '>=6'} @@ -7924,9 +7587,6 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - queue@6.0.2: - resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} - quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -7934,12 +7594,13 @@ packages: resolution: {integrity: sha512-tRS7sTgyxMXtLum8L65daJnHUhfDUgboRdcWW2bR9vBfrj2+O5HSMbQOJfJJjIVSPFqbBCF37FpwWXGitDc5tA==} engines: {node: '>=4'} + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} - raf@3.4.1: - resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} - randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} @@ -7960,6 +7621,10 @@ packages: peerDependencies: webpack: ^4.0.0 || ^5.0.0 + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + react-component-transition@2.1.2: resolution: {integrity: sha512-SRdkm6MxpnDF2bV15Ils3NySDWc1l4jAtIor4crlPHb0/JjEGCziH9d4kcSxMGk7s+GK0fELjexv3Q3bumJtBw==} peerDependencies: @@ -7968,13 +7633,12 @@ packages: react: 16.8.0 - 17 react-dom: 16.8.0 - 17 - react-devtools-core@5.3.2: - resolution: {integrity: sha512-crr9HkVrDiJ0A4zot89oS0Cgv0Oa4OG1Em4jit3P3ZxZSKPMYyMjfwMqgcJna9o625g8oN87rBm8SWWrSTBZxg==} + react-devtools-core@4.28.5: + resolution: {integrity: sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==} - react-dom@17.0.2: - resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} - peerDependencies: - react: 17.0.2 + react-devtools@4.28.5: + resolution: {integrity: sha512-iVYraMxjfqpb+e1z3MrYIqdQABDgAZAR5wuSJwGMpxEYLC+XI/YJUbB3NlN1Wlq4s1ZvibfOtSckjnl2b3BL8Q==} + hasBin: true react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} @@ -7998,10 +7662,10 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-i18next@11.18.6: - resolution: {integrity: sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==} + react-i18next@15.1.1: + resolution: {integrity: sha512-R/Vg9wIli2P3FfeI8o1eNJUJue5LWpFsQePCHdQDmX0Co3zkr6kdT8gAseb/yGeWbNz1Txc4bKDQuZYsC0kQfw==} peerDependencies: - i18next: '>= 19.0.0' + i18next: '>= 23.2.3' react: '>= 16.8.0' react-dom: '*' react-native: '*' @@ -8041,35 +7705,12 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-konva@18.2.10: - resolution: {integrity: sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==} - peerDependencies: - konva: ^8.0.1 || ^7.2.5 || ^9.0.0 - react: '>=18.0.0' - react-dom: '>=18.0.0' - react-markdown@7.1.2: resolution: {integrity: sha512-ibMcc0EbfmbwApqJD8AUr0yls8BSrKzIbHaUsPidQljxToCqFh34nwtu3CXNEItcVJNzpjDHrhK8A+MAh2JW3A==} peerDependencies: '@types/react': '>=16' react: '>=16' - react-motion@0.5.2: - resolution: {integrity: sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ==} - peerDependencies: - react: ^0.14.9 || ^15.3.0 || ^16.0.0 - - react-native@0.76.3: - resolution: {integrity: sha512-0TUhgmlouRNf6yuDIIAdbQl0g1VsONgCMsLs7Et64hjj5VLMCA7np+4dMrZvGZ3wRNqzgeyT9oWJsUm49AcwSQ==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - '@types/react': ^18.2.6 - react: ^18.2.0 - peerDependenciesMeta: - '@types/react': - optional: true - react-number-format@4.9.4: resolution: {integrity: sha512-Gq20Z3ugqPLFgeaidnx5on9cNpbQZntPN3QgNAL/WJrNNlQnNznY0LCx7g8xtssmRBw0/hw+SCqw6zAcajooiA==} peerDependencies: @@ -8087,34 +7728,11 @@ packages: react: '>=16.4.1' react-dom: '>=16.4.1' - react-reconciler@0.27.0: - resolution: {integrity: sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==} - engines: {node: '>=0.10.0'} - peerDependencies: - react: ^18.0.0 - - react-reconciler@0.29.2: - resolution: {integrity: sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==} - engines: {node: '>=0.10.0'} - peerDependencies: - react: ^18.3.1 - - react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} - engines: {node: '>=0.10.0'} - react-router-dom@5.3.4: resolution: {integrity: sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==} peerDependencies: react: '>=15' - react-router-transition@2.1.0: - resolution: {integrity: sha512-vL0JczAcs4s5MjWm1DSitoap9KRqE1m7YZopIXiT4x6NVrqXs9CGH1uLBBSZ3rJFwGBQRgsfY7NFe2ygDfGQ2Q==} - peerDependencies: - react: ^16.8.0 - react-dom: ^16.8.0 - react-router-dom: ^5.0.0 - react-router@5.3.4: resolution: {integrity: sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==} peerDependencies: @@ -8132,12 +7750,6 @@ packages: react: '>= 16.8.0' react-dom: '>= 16.8.0' - react-spring@9.7.4: - resolution: {integrity: sha512-ypxdsOwmCfbDZGTBRyBo7eLjF55xNFN86e/QkflZ1Rfo8QMzVjCAWocrEEbsuFKkQAg2RRdhNkinWJ6BpCvJoQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-swipeable-views-core@0.14.0: resolution: {integrity: sha512-0W/e9uPweNEOSPjmYtuKSC/SvKKg1sfo+WtPdnxeLF3t2L82h7jjszuOHz9C23fzkvLfdgkaOmcbAxE9w2GEjA==} engines: {node: '>=6.0.0'} @@ -8152,23 +7764,12 @@ packages: peerDependencies: react: ^15.3.0 || ^16.0.0 || ^17.0.0 - react-text-transition@2.0.0: - resolution: {integrity: sha512-43LNm+KoJRVtau56oxeFXjJLnCFyEt9/rv91qDCsx8b00z+70n8aQDViDEHn/Zlem0EbRx95Dau02ER/SVTU7w==} - peerDependencies: - react: '>=18.0.0' - react-transition-group@4.4.5: resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: react: '>=16.6.0' react-dom: '>=16.6.0' - react-tsparticles@1.43.1: - resolution: {integrity: sha512-IWa33DP6CjcO+/upUqPhYpxduCFQvWXqCHV6rgvIPvmaqPqs8BkNbeBgBqcEPJRPzTluaD/+r9d7tDp2Uhd0uA==} - deprecated: '@tsparticles/react is the new version, please use that' - peerDependencies: - react: '>=16' - react-universal-interface@0.6.2: resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} peerDependencies: @@ -8188,13 +7789,6 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-zdog@1.2.2: - resolution: {integrity: sha512-Ix7ALha91aOEwiHuxumCeYbARS5XNpc/w0v145oGkM6poF/CvhKJwzLhM5sEZbtrghMA+psAhOJkCTzJoseicA==} - - react@17.0.2: - resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} - engines: {node: '>=0.10.0'} - react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -8225,17 +7819,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - readline@1.3.0: - resolution: {integrity: sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==} - real-require@0.1.0: resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} engines: {node: '>= 12.13.0'} - recast@0.21.5: - resolution: {integrity: sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==} - engines: {node: '>= 4'} - recharts-scale@0.4.5: resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} @@ -8261,8 +7848,8 @@ packages: reflect-metadata@0.1.14: resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==} - reflect.getprototypeof@1.0.6: - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + reflect.getprototypeof@1.0.7: + resolution: {integrity: sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==} engines: {node: '>= 0.4'} regenerate-unicode-properties@10.2.0: @@ -8275,9 +7862,6 @@ packages: regenerator-runtime@0.12.1: resolution: {integrity: sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==} - regenerator-runtime@0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -8296,6 +7880,13 @@ packages: resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} engines: {node: '>=4'} + registry-auth-token@3.4.0: + resolution: {integrity: sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==} + + registry-url@3.1.0: + resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} + engines: {node: '>=0.10.0'} + regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} @@ -8347,6 +7938,9 @@ packages: resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + resolve-cwd@2.0.0: resolution: {integrity: sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==} engines: {node: '>=4'} @@ -8389,6 +7983,9 @@ packages: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -8408,11 +8005,6 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rimraf@2.6.3: - resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -8438,6 +8030,19 @@ packages: resolution: {integrity: sha512-PD6U2PGk6Vq2spfgiWZdomLvRGDreBLxi5jv5M8EpRo3pU6VEm31KO+HFxE18Q3vgqfDrQ9pZA3FP95rkijNKw==} hasBin: true + roarr@2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + + rrdom@2.0.0-alpha.17: + resolution: {integrity: sha512-b6caDiNcFO96Opp7TGdcVd4OLGSXu5dJe+A0IDiAu8mk7OmhqZCSDlgQdTKmdO5wMf4zPsUTgb8H/aNvR3kDHA==} + + rrweb-snapshot@2.0.0-alpha.17: + resolution: {integrity: sha512-GBg5pV8LHOTbeVmH2VHLEFR0mc2QpQMzAvcoxEGfPNWgWHc8UvKCyq7pqN1vA+fDZ+yXXbixeO0kB2pzVvFCBw==} + + rrweb@2.0.0-alpha.13: + resolution: {integrity: sha512-a8GXOCnzWHNaVZPa7hsrLZtNZ3CGjiL+YrkpLo0TfmxGLhjNZbWY2r7pE06p+FcjFNlgUVTmFrSJbK3kO7yxvw==} + rtl-css-js@1.16.1: resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} @@ -8493,18 +8098,9 @@ packages: resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} engines: {node: '>=10'} - scheduler@0.20.2: - resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} - - scheduler@0.21.0: - resolution: {integrity: sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==} - scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - scheduler@0.24.0-canary-efb381bbf-20230505: - resolution: {integrity: sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==} - schema-utils@1.0.0: resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==} engines: {node: '>= 4'} @@ -8548,9 +8144,12 @@ packages: selfsigned@1.10.14: resolution: {integrity: sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==} - selfsigned@2.4.1: - resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} - engines: {node: '>=10'} + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + + semver-diff@2.1.0: + resolution: {integrity: sha512-gL8F8L4ORwsS0+iQ34yCYv///jsOq0ZL7WP55d1HnJ32o7tyFYEFQZQA22mrLIacZdU6xecaBBZ+uEiffGNyXw==} + engines: {node: '>=0.10.0'} semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} @@ -8569,9 +8168,9 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} - serialize-error@2.1.0: - resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} - engines: {node: '>=0.10.0'} + serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -8788,6 +8387,9 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + stable@0.1.8: resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' @@ -8808,10 +8410,6 @@ packages: stacktrace-js@2.0.2: resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} - stacktrace-parser@0.1.10: - resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} - engines: {node: '>=6'} - static-extend@0.1.2: resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} engines: {node: '>=0.10.0'} @@ -8848,9 +8446,6 @@ packages: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} - string-natural-compare@3.0.1: - resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} - string-width@2.1.1: resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} engines: {node: '>=4'} @@ -8867,10 +8462,6 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string.prototype.includes@2.0.1: - resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} - engines: {node: '>= 0.4'} - string.prototype.matchall@4.0.11: resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} @@ -8943,6 +8534,10 @@ packages: resolution: {integrity: sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==} engines: {node: '>=4'} + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -8962,6 +8557,10 @@ packages: stylis@4.3.4: resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==} + sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + superagent@3.8.3: resolution: {integrity: sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==} engines: {node: '>= 4.0'} @@ -8995,11 +8594,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - suspend-react@0.1.3: - resolution: {integrity: sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==} - peerDependencies: - react: '>=17.0' - svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -9024,9 +8618,9 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - temp@0.8.4: - resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} - engines: {node: '>=6.0.0'} + term-size@1.2.0: + resolution: {integrity: sha512-7dPUZQGy/+m3/wjVz3ZW5dobSoD/02NxJpoXUX0WIyjfVS3l0c+b/+9phIDFA7FHzkYtwtMFgeGZ/Y8jVTeqQQ==} + engines: {node: '>=4'} terminal-link@2.1.1: resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} @@ -9067,12 +8661,6 @@ packages: thread-stream@0.15.2: resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==} - three@0.170.0: - resolution: {integrity: sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==} - - throat@5.0.0: - resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} - throat@6.0.2: resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} @@ -9090,6 +8678,10 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + timed-out@4.0.1: + resolution: {integrity: sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==} + engines: {node: '>=0.10.0'} + tiny-emitter@2.1.0: resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} @@ -9147,8 +8739,8 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - ts-api-utils@1.4.0: - resolution: {integrity: sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==} + ts-api-utils@1.4.1: + resolution: {integrity: sha512-5RU2/lxTA3YUZxju61HO2U6EoZLvBLtmV2mbTvqyu4a/7s7RmJPT+1YekhMVsQhznRWk/czIwDUg+V8Q9ZuG4w==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' @@ -9164,27 +8756,6 @@ packages: ts-import-plugin@1.6.7: resolution: {integrity: sha512-6qbRME6Cj9RzhlqXGc1275lAK3IEJjmwYPmX0/jVPBwtdoDqHVbdRURYcvR195uFi8ZpBqT2WjL4E56buPQ4sg==} - ts-jest@27.1.5: - resolution: {integrity: sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@types/jest': ^27.0.0 - babel-jest: '>=27.0.0 <28' - esbuild: '*' - jest: ^27.0.0 - typescript: '>=3.8 <5.0' - peerDependenciesMeta: - '@babel/core': - optional: true - '@types/jest': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - ts-loader@9.5.1: resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} engines: {node: '>=12.0.0'} @@ -9192,6 +8763,20 @@ packages: typescript: '*' webpack: ^5.0.0 + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + ts-toolbelt@9.6.0: resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} @@ -9210,9 +8795,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsparticles@1.43.1: - resolution: {integrity: sha512-6EuHncwqzoyTlUxc11YH8LVlwVUgpYaZD0yMOeA2OvRqFZ9VQV8EjjQ6ZfXt6pfGA1ObPwU929jveFatxwTQkg==} - deprecated: tsParticles v3 is out, it contains breaking changes and it's recommended to migrate to that version with fixes and new features + tsparticles@3.6.0: + resolution: {integrity: sha512-Rn5MEgooQtFSqUOmBtwFYsStUeldv+8cJ0TTeHT5xKb4B3VnyU3ic1bw9ueTP19UNnBIIzs0jfdrC5Utfpo6JA==} tweetnacl-util@0.15.1: resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} @@ -9232,6 +8816,10 @@ packages: resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -9240,10 +8828,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -9256,12 +8840,12 @@ packages: resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + typed-array-byte-offset@1.0.3: + resolution: {integrity: sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==} engines: {node: '>= 0.4'} - typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} typedarray-to-buffer@3.1.5: @@ -9282,9 +8866,9 @@ packages: peerDependencies: typescript: '>=3.6.5' - typescript@4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} hasBin: true ufo@1.5.4: @@ -9345,6 +8929,10 @@ packages: uniqid@5.4.0: resolution: {integrity: sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==} + unique-string@1.0.0: + resolution: {integrity: sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==} + engines: {node: '>=4'} + unist-builder@3.0.1: resolution: {integrity: sha512-gnpOw7DIpCA0vpr6NqdPvTWnlPTApCTRzr+38E6hCWx3rz/cjo83SsKIlS1Z+L5ttScQ2AwutNnb8+tAvpb6qQ==} @@ -9366,6 +8954,10 @@ packages: unist-util-visit@4.1.2: resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} @@ -9437,6 +9029,10 @@ packages: resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} hasBin: true + unzip-response@2.0.1: + resolution: {integrity: sha512-N0XH6lqDtFH84JxptQoZYmloF4nzrQqqrAymNj+/gW60AO2AZgOcf4O/nUXJcYfyQkqvMo9lSupBZmmgvuVXlw==} + engines: {node: '>=4'} + upath@1.2.0: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} @@ -9447,6 +9043,10 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-notifier@2.5.0: + resolution: {integrity: sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==} + engines: {node: '>=4'} + uqr@0.1.2: resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} @@ -9470,6 +9070,10 @@ packages: file-loader: optional: true + url-parse-lax@1.0.0: + resolution: {integrity: sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==} + engines: {node: '>=0.10.0'} + url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -9536,6 +9140,9 @@ packages: engines: {node: '>=8'} hasBin: true + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-to-istanbul@8.1.1: resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} engines: {node: '>=10.12.0'} @@ -9579,17 +9186,14 @@ packages: typescript: optional: true - viem@2.21.49: - resolution: {integrity: sha512-NNItYfTv4+yGE5DDKc+S/g2S7KeJn047GwgEYG60FAJlK0FzwuP6lQKSeQ8k7Y4VasfuKPqiT+XiilcCtTRiDQ==} + viem@2.21.50: + resolution: {integrity: sha512-WHB8NmkaForODuSALb0Ai3E296aEigzYSE+pzB9Y0cTNJeiZT8rpkdxxUFYfjwFMnPkz2tivqrSpuw3hO5TH6w==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: typescript: optional: true - vlq@1.0.1: - resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} - vm-browserify@1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} @@ -9803,9 +9407,6 @@ packages: whatwg-encoding@1.0.5: resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} - whatwg-fetch@3.6.20: - resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} - whatwg-mimetype@2.3.0: resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} @@ -9819,8 +9420,8 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-builtin-type@1.1.4: - resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} + which-builtin-type@1.2.0: + resolution: {integrity: sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==} engines: {node: '>= 0.4'} which-collection@1.0.2: @@ -9843,6 +9444,10 @@ packages: engines: {node: '>= 8'} hasBin: true + widest-line@2.0.1: + resolution: {integrity: sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==} + engines: {node: '>=4'} + wildcard@2.0.1: resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} @@ -9875,10 +9480,6 @@ packages: write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ws@6.2.3: resolution: {integrity: sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==} peerDependencies: @@ -9902,18 +9503,6 @@ packages: utf-8-validate: optional: true - ws@7.5.3: - resolution: {integrity: sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.13.0: resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} engines: {node: '>=10.0.0'} @@ -9950,6 +9539,10 @@ packages: utf-8-validate: optional: true + xdg-basedir@3.0.0: + resolution: {integrity: sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==} + engines: {node: '>=4'} + xml-name-validator@3.0.0: resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} @@ -9975,6 +9568,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -10023,28 +9619,23 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zdog@1.1.3: - resolution: {integrity: sha512-raRj6r0gPzopFm5XWBJZr/NuV4EEnT4iE+U3dp5FV5pCb588Gmm3zLIp/j9yqqcMiHH8VNQlerLTgOqL7krh6w==} - zip-dir@2.0.0: resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==} zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - zustand@3.7.2: - resolution: {integrity: sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==} - engines: {node: '>=12.7.0'} - peerDependencies: - react: '>=16.8' - peerDependenciesMeta: - react: - optional: true - zustand@4.5.5: resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} engines: {node: '>=12.7.0'} @@ -10284,34 +9875,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-proposal-export-default-from@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) - - '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) - transitivePeerDependencies: - - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10336,21 +9899,6 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-export-default-from@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10534,12 +10082,6 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-flow-strip-types@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10705,16 +10247,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10749,18 +10281,6 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-runtime@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.0) - babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0) - babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10789,17 +10309,6 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-typescript@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) - transitivePeerDependencies: - - supports-color - '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10898,13 +10407,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-flow@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-validator-option': 7.25.9 - '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.26.0) - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -10924,26 +10426,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.26.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-validator-option': 7.25.9 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) - transitivePeerDependencies: - - supports-color - - '@babel/register@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - clone-deep: 4.0.1 - find-cache-dir: 2.1.0 - make-dir: 2.1.0 - pirates: 4.0.6 - source-map-support: 0.5.21 - '@babel/runtime@7.0.0': dependencies: regenerator-runtime: 0.12.1 @@ -10977,9 +10459,7 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@coinbase/cbpay-js@1.10.0(regenerator-runtime@0.13.11)': - optionalDependencies: - regenerator-runtime: 0.13.11 + '@coinbase/cbpay-js@1.10.0': {} '@coinbase/wallet-sdk@3.9.3': dependencies: @@ -10990,39 +10470,38 @@ snapshots: eth-json-rpc-filters: 6.0.1 eventemitter3: 5.0.1 keccak: 3.0.4 - preact: 10.24.3 + preact: 10.25.0 sha.js: 2.4.11 transitivePeerDependencies: - supports-color + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + optional: true + '@debank/common@0.3.60': {} '@discoveryjs/json-ext@0.5.7': {} - '@dnd-kit/accessibility@3.1.0(react@17.0.2)': - dependencies: - react: 17.0.2 - tslib: 2.8.1 - - '@dnd-kit/core@4.0.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': - dependencies: - '@dnd-kit/accessibility': 3.1.0(react@17.0.2) - '@dnd-kit/utilities': 3.2.2(react@17.0.2) - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - tslib: 2.8.1 - - '@dnd-kit/sortable@5.1.0(@dnd-kit/core@4.0.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react@17.0.2)': + '@dnd-kit/utilities@3.2.2(react@18.3.1)': dependencies: - '@dnd-kit/core': 4.0.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@dnd-kit/utilities': 3.2.2(react@17.0.2) - react: 17.0.2 + react: 18.3.1 tslib: 2.8.1 - '@dnd-kit/utilities@3.2.2(react@17.0.2)': + '@electron/get@2.0.3': dependencies: - react: 17.0.2 - tslib: 2.8.1 + debug: 4.3.7(supports-color@6.1.0) + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color '@emotion/babel-plugin@11.13.5': dependencies: @@ -11056,19 +10535,19 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2)': + '@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@emotion/babel-plugin': 11.13.5 '@emotion/cache': 11.13.5 '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@17.0.2) + '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1) '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 17.0.2 + react: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 transitivePeerDependencies: - supports-color @@ -11082,26 +10561,26 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2)': + '@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.3.1 - '@emotion/react': 11.13.5(@types/react@17.0.83)(react@17.0.2) + '@emotion/react': 11.13.5(@types/react@18.3.12)(react@18.3.1) '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@17.0.2) + '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1) '@emotion/utils': 1.4.2 - react: 17.0.2 + react: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 transitivePeerDependencies: - supports-color '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@17.0.2)': + '@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1)': dependencies: - react: 17.0.2 + react: 18.3.1 '@emotion/utils@1.4.2': {} @@ -11422,19 +10901,6 @@ snapshots: tslib: 2.8.1 undici: 6.19.7 - '@firebase/auth@1.8.1(@firebase/app@0.10.13)': - dependencies: - '@firebase/app': 0.10.13 - '@firebase/component': 0.6.11 - '@firebase/logger': 0.4.4 - '@firebase/util': 1.10.2 - tslib: 2.8.1 - - '@firebase/component@0.6.11': - dependencies: - '@firebase/util': 1.10.2 - tslib: 2.8.1 - '@firebase/component@0.6.9': dependencies: '@firebase/util': 1.10.0 @@ -11542,14 +11008,6 @@ snapshots: dependencies: '@firebase/app-types': 0.9.2 - '@firebase/installations@0.6.11(@firebase/app@0.10.13)': - dependencies: - '@firebase/app': 0.10.13 - '@firebase/component': 0.6.11 - '@firebase/util': 1.10.2 - idb: 7.1.1 - tslib: 2.8.1 - '@firebase/installations@0.6.9(@firebase/app@0.10.13)': dependencies: '@firebase/app': 0.10.13 @@ -11562,10 +11020,6 @@ snapshots: dependencies: tslib: 2.8.1 - '@firebase/logger@0.4.4': - dependencies: - tslib: 2.8.1 - '@firebase/messaging-compat@0.2.12(@firebase/app-compat@0.2.43)(@firebase/app@0.10.13)': dependencies: '@firebase/app-compat': 0.2.43 @@ -11625,15 +11079,6 @@ snapshots: '@firebase/remote-config-types@0.3.2': {} - '@firebase/remote-config@0.4.11(@firebase/app@0.10.13)': - dependencies: - '@firebase/app': 0.10.13 - '@firebase/component': 0.6.11 - '@firebase/installations': 0.6.11(@firebase/app@0.10.13) - '@firebase/logger': 0.4.4 - '@firebase/util': 1.10.2 - tslib: 2.8.1 - '@firebase/remote-config@0.4.9(@firebase/app@0.10.13)': dependencies: '@firebase/app': 0.10.13 @@ -11672,10 +11117,6 @@ snapshots: dependencies: tslib: 2.8.1 - '@firebase/util@1.10.2': - dependencies: - tslib: 2.8.1 - '@firebase/vertexai-preview@0.0.4(@firebase/app-types@0.9.2)(@firebase/app@0.10.13)': dependencies: '@firebase/app': 0.10.13 @@ -11697,18 +11138,18 @@ snapshots: '@floating-ui/core': 1.6.8 '@floating-ui/utils': 0.2.8 - '@floating-ui/react-dom@2.1.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/dom': 1.6.12 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) '@floating-ui/utils@0.2.8': {} '@grpc/grpc-js@1.9.15': dependencies: '@grpc/proto-loader': 0.7.13 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@grpc/proto-loader@0.7.13': dependencies: @@ -11745,8 +11186,6 @@ snapshots: browser-headers: 0.4.1 google-protobuf: 3.21.4 - '@isaacs/ttlcache@1.4.1': {} - '@istanbuljs/load-nyc-config@1.1.0': dependencies: camelcase: 5.3.1 @@ -11760,27 +11199,27 @@ snapshots: '@jest/console@27.5.1': dependencies: '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 jest-message-util: 27.5.1 jest-util: 27.5.1 slash: 3.0.0 - '@jest/core@27.5.1': + '@jest/core@27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2))': dependencies: '@jest/console': 27.5.1 '@jest/reporters': 27.5.1 '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 27.5.1 - jest-config: 27.5.1 + jest-config: 27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)) jest-haste-map: 27.5.1 jest-message-util: 27.5.1 jest-regex-util: 27.5.1 @@ -11803,42 +11242,22 @@ snapshots: - ts-node - utf-8-validate - '@jest/create-cache-key-function@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@jest/environment@27.5.1': dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 jest-mock: 27.5.1 - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 17.0.45 - jest-mock: 29.7.0 - '@jest/fake-timers@27.5.1': dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 17.0.45 + '@types/node': 22.9.3 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 17.0.45 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - '@jest/globals@27.5.1': dependencies: '@jest/environment': 27.5.1 @@ -11852,7 +11271,7 @@ snapshots: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -11921,31 +11340,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.26.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - '@jest/types@27.5.1': dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/yargs': 16.0.9 chalk: 4.1.2 @@ -11954,7 +11353,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -11980,6 +11379,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + optional: true + '@ledgerhq/cryptoassets-evm-signatures@13.5.2': dependencies: '@ledgerhq/live-env': 2.4.1 @@ -12140,8 +11545,8 @@ snapshots: dependencies: '@ethereumjs/tx': 4.2.0 '@metamask/superstruct': 3.1.0 - '@noble/hashes': 1.5.0 - '@scure/base': 1.1.9 + '@noble/hashes': 1.6.1 + '@scure/base': 1.2.1 '@types/debug': 4.1.12 debug: 4.3.7(supports-color@6.1.0) pony-cause: 2.1.11 @@ -12154,8 +11559,8 @@ snapshots: dependencies: '@ethereumjs/tx': 4.2.0 '@metamask/superstruct': 3.1.0 - '@noble/hashes': 1.5.0 - '@scure/base': 1.1.9 + '@noble/hashes': 1.6.1 + '@scure/base': 1.2.1 '@types/debug': 4.1.12 debug: 4.3.7(supports-color@6.1.0) pony-cause: 2.1.11 @@ -12209,123 +11614,109 @@ snapshots: '@motionone/dom': 10.18.0 tslib: 2.8.1 - '@mui/base@5.0.0-beta.40(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@mui/base@5.0.0-beta.40(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@floating-ui/react-dom': 2.1.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@mui/types': 7.2.19(@types/react@17.0.83) - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/types': 7.2.19(@types/react@18.3.12) + '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1) '@popperjs/core': 2.11.8 clsx: 2.1.1 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@mui/base@5.0.0-beta.62(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@mui/base@5.0.0-beta.62(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@floating-ui/react-dom': 2.1.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@mui/types': 7.2.19(@types/react@17.0.83) - '@mui/utils': 6.1.8(@types/react@17.0.83)(react@17.0.2) + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/types': 7.2.19(@types/react@18.3.12) + '@mui/utils': 6.1.8(@types/react@18.3.12)(react@18.3.1) '@popperjs/core': 2.11.8 clsx: 2.1.1 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 '@mui/core-downloads-tracker@5.16.7': {} - '@mui/core@5.0.0-alpha.54(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': - dependencies: - '@babel/runtime': 7.26.0 - '@emotion/is-prop-valid': 1.3.1 - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) - '@popperjs/core': 2.11.8 - clsx: 1.2.1 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-is: 17.0.2 - optionalDependencies: - '@types/react': 17.0.83 - - '@mui/icons-material@5.16.7(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(@types/react@17.0.83)(react@17.0.2)': + '@mui/icons-material@5.16.7(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@mui/material': 5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - react: 17.0.2 + '@mui/material': 5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@mui/lab@5.0.0-alpha.173(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@mui/lab@5.0.0-alpha.173(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@mui/base': 5.0.0-beta.40(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@mui/material': 5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@mui/system': 5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) - '@mui/types': 7.2.19(@types/react@17.0.83) - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) + '@mui/base': 5.0.0-beta.40(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/material': 5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/system': 5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) + '@mui/types': 7.2.19(@types/react@18.3.12) + '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1) clsx: 2.1.1 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@emotion/react': 11.13.5(@types/react@17.0.83)(react@17.0.2) - '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) - '@types/react': 17.0.83 + '@emotion/react': 11.13.5(@types/react@18.3.12)(react@18.3.1) + '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) + '@types/react': 18.3.12 - '@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@mui/material@5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@mui/core-downloads-tracker': 5.16.7 - '@mui/system': 5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) - '@mui/types': 7.2.19(@types/react@17.0.83) - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) + '@mui/system': 5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) + '@mui/types': 7.2.19(@types/react@18.3.12) + '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1) '@popperjs/core': 2.11.8 '@types/react-transition-group': 4.4.11 clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-transition-group: 4.4.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) optionalDependencies: - '@emotion/react': 11.13.5(@types/react@17.0.83)(react@17.0.2) - '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) - '@types/react': 17.0.83 + '@emotion/react': 11.13.5(@types/react@18.3.12)(react@18.3.1) + '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) + '@types/react': 18.3.12 - '@mui/private-theming@5.16.6(@types/react@17.0.83)(react@17.0.2)': + '@mui/private-theming@5.16.6(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) + '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1) prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@mui/styled-engine@5.16.6(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)': + '@mui/styled-engine@5.16.6(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@emotion/cache': 11.13.5 csstype: 3.1.3 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 optionalDependencies: - '@emotion/react': 11.13.5(@types/react@17.0.83)(react@17.0.2) - '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) + '@emotion/react': 11.13.5(@types/react@18.3.12)(react@18.3.1) + '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) - '@mui/styles@5.16.7(@types/react@17.0.83)(react@17.0.2)': + '@mui/styles@5.16.7(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@emotion/hash': 0.9.2 - '@mui/private-theming': 5.16.6(@types/react@17.0.83)(react@17.0.2) - '@mui/types': 7.2.19(@types/react@17.0.83) - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) + '@mui/private-theming': 5.16.6(@types/react@18.3.12)(react@18.3.1) + '@mui/types': 7.2.19(@types/react@18.3.12) + '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1) clsx: 2.1.1 csstype: 3.1.3 hoist-non-react-statics: 3.3.2 @@ -12338,53 +11729,53 @@ snapshots: jss-plugin-rule-value-function: 10.10.0 jss-plugin-vendor-prefixer: 10.10.0 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@mui/system@5.16.7(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2)': + '@mui/system@5.16.7(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@mui/private-theming': 5.16.6(@types/react@17.0.83)(react@17.0.2) - '@mui/styled-engine': 5.16.6(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2) - '@mui/types': 7.2.19(@types/react@17.0.83) - '@mui/utils': 5.16.6(@types/react@17.0.83)(react@17.0.2) + '@mui/private-theming': 5.16.6(@types/react@18.3.12)(react@18.3.1) + '@mui/styled-engine': 5.16.6(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1) + '@mui/types': 7.2.19(@types/react@18.3.12) + '@mui/utils': 5.16.6(@types/react@18.3.12)(react@18.3.1) clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 optionalDependencies: - '@emotion/react': 11.13.5(@types/react@17.0.83)(react@17.0.2) - '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@17.0.83)(react@17.0.2))(@types/react@17.0.83)(react@17.0.2) - '@types/react': 17.0.83 + '@emotion/react': 11.13.5(@types/react@18.3.12)(react@18.3.1) + '@emotion/styled': 11.13.5(@emotion/react@11.13.5(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) + '@types/react': 18.3.12 - '@mui/types@7.2.19(@types/react@17.0.83)': + '@mui/types@7.2.19(@types/react@18.3.12)': optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@mui/utils@5.16.6(@types/react@17.0.83)(react@17.0.2)': + '@mui/utils@5.16.6(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@mui/types': 7.2.19(@types/react@17.0.83) + '@mui/types': 7.2.19(@types/react@18.3.12) '@types/prop-types': 15.7.13 clsx: 2.1.1 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 react-is: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@mui/utils@6.1.8(@types/react@17.0.83)(react@17.0.2)': + '@mui/utils@6.1.8(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 - '@mui/types': 7.2.19(@types/react@17.0.83) + '@mui/types': 7.2.19(@types/react@18.3.12) '@types/prop-types': 15.7.13 clsx: 2.1.1 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 react-is: 18.3.1 optionalDependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 '@noble/curves@1.2.0': dependencies: @@ -12404,6 +11795,8 @@ snapshots: '@noble/hashes@1.5.0': {} + '@noble/hashes@1.6.1': {} + '@noble/secp256k1@1.7.1': {} '@nodelib/fs.scandir@2.1.5': @@ -12458,15 +11851,15 @@ snapshots: - supports-color - utf-8-validate - '@onflow/fcl-wc@5.4.0(@onflow/fcl-core@1.12.0(google-protobuf@3.21.4))(@types/react@17.0.83)(react@17.0.2)': + '@onflow/fcl-wc@5.4.0(@onflow/fcl-core@1.12.0(google-protobuf@3.21.4))(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@onflow/config': 1.5.0 '@onflow/fcl-core': 1.12.0(google-protobuf@3.21.4) '@onflow/util-invariant': 1.2.3 '@onflow/util-logger': 1.3.2 - '@walletconnect/modal': 2.7.0(@types/react@17.0.83)(react@17.0.2) - '@walletconnect/modal-core': 2.7.0(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal': 2.7.0(@types/react@18.3.12)(react@18.3.1) + '@walletconnect/modal-core': 2.7.0(@types/react@18.3.12)(react@18.3.1) '@walletconnect/sign-client': 2.17.2 '@walletconnect/types': 2.17.2 '@walletconnect/utils': 2.17.2 @@ -12491,12 +11884,12 @@ snapshots: - supports-color - utf-8-validate - '@onflow/fcl@1.12.3(@types/react@17.0.83)(google-protobuf@3.21.4)(react@17.0.2)': + '@onflow/fcl@1.12.3(@types/react@18.3.12)(google-protobuf@3.21.4)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@onflow/config': 1.5.0 '@onflow/fcl-core': 1.12.0(google-protobuf@3.21.4) - '@onflow/fcl-wc': 5.4.0(@onflow/fcl-core@1.12.0(google-protobuf@3.21.4))(@types/react@17.0.83)(react@17.0.2) + '@onflow/fcl-wc': 5.4.0(@onflow/fcl-core@1.12.0(google-protobuf@3.21.4))(@types/react@18.3.12)(react@18.3.1) '@onflow/interaction': 0.0.11 '@onflow/rlp': 1.2.2 '@onflow/sdk': 1.5.3 @@ -12585,18 +11978,6 @@ snapshots: - encoding - utf-8-validate - '@onflow/transport-http@1.5.0-alpha.1': - dependencies: - '@babel/runtime': 7.26.0 - '@onflow/util-address': 1.2.2 - '@onflow/util-invariant': 1.2.3 - '@onflow/util-logger': 1.3.2 - '@onflow/util-template': 1.2.2 - node-fetch: 2.7.0 - transitivePeerDependencies: - - '@onflow/util-config' - - encoding - '@onflow/typedefs@1.3.1': dependencies: '@babel/runtime': 7.26.0 @@ -12783,243 +12164,41 @@ snapshots: sinon-chrome: 3.0.1 webextension-polyfill: 0.7.0 - '@react-native/assets-registry@0.76.3': {} - - '@react-native/babel-plugin-codegen@0.76.3(@babel/preset-env@7.26.0(@babel/core@7.26.0))': + '@reown/walletkit@1.1.1': dependencies: - '@react-native/codegen': 0.76.3(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - transitivePeerDependencies: - - '@babel/preset-env' - - supports-color - - '@react-native/babel-preset@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))': - dependencies: - '@babel/core': 7.26.0 - '@babel/plugin-proposal-export-default-from': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-export-default-from': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-runtime': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.0) - '@babel/template': 7.25.9 - '@react-native/babel-plugin-codegen': 0.76.3(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - babel-plugin-syntax-hermes-parser: 0.25.1 - babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.26.0) - react-refresh: 0.14.2 - transitivePeerDependencies: - - '@babel/preset-env' - - supports-color - - '@react-native/codegen@0.76.3(@babel/preset-env@7.26.0(@babel/core@7.26.0))': - dependencies: - '@babel/parser': 7.26.2 - '@babel/preset-env': 7.26.0(@babel/core@7.26.0) - glob: 7.2.3 - hermes-parser: 0.23.1 - invariant: 2.2.4 - jscodeshift: 0.14.0(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - mkdirp: 0.5.6 - nullthrows: 1.1.1 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - - '@react-native/community-cli-plugin@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))': - dependencies: - '@react-native/dev-middleware': 0.76.3 - '@react-native/metro-babel-transformer': 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - chalk: 4.1.2 - execa: 5.1.1 - invariant: 2.2.4 - metro: 0.81.0 - metro-config: 0.81.0 - metro-core: 0.81.0 - node-fetch: 2.7.0 - readline: 1.3.0 - semver: 7.6.3 - transitivePeerDependencies: - - '@babel/core' - - '@babel/preset-env' - - bufferutil - - encoding - - supports-color - - utf-8-validate - - '@react-native/debugger-frontend@0.76.3': {} - - '@react-native/dev-middleware@0.76.3': - dependencies: - '@isaacs/ttlcache': 1.4.1 - '@react-native/debugger-frontend': 0.76.3 - chrome-launcher: 0.15.2 - chromium-edge-launcher: 0.2.0 - connect: 3.7.0 - debug: 2.6.9(supports-color@6.1.0) - nullthrows: 1.1.1 - open: 7.4.2 - selfsigned: 2.4.1 - serve-static: 1.16.2(supports-color@6.1.0) - ws: 6.2.3 + '@walletconnect/core': 2.17.1 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.17.1 + '@walletconnect/types': 2.17.1 + '@walletconnect/utils': 2.17.1 transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' - bufferutil - - supports-color + - ioredis - utf-8-validate - '@react-native/gradle-plugin@0.76.3': {} - - '@react-native/js-polyfills@0.76.3': {} - - '@react-native/metro-babel-transformer@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))': - dependencies: - '@babel/core': 7.26.0 - '@react-native/babel-preset': 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - hermes-parser: 0.23.1 - nullthrows: 1.1.1 - transitivePeerDependencies: - - '@babel/preset-env' - - supports-color - - '@react-native/normalize-colors@0.76.3': {} - - '@react-native/virtualized-lists@0.76.3(@types/react@17.0.83)(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)': - dependencies: - invariant: 2.2.4 - nullthrows: 1.1.1 - react: 17.0.2 - react-native: 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2) - optionalDependencies: - '@types/react': 17.0.83 - - '@react-spring/animated@9.7.5(react@17.0.2)': - dependencies: - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - react: 17.0.2 - - '@react-spring/core@9.7.5(react@17.0.2)': - dependencies: - '@react-spring/animated': 9.7.5(react@17.0.2) - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - react: 17.0.2 - - '@react-spring/konva@9.7.5(konva@9.3.16)(react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react@17.0.2)': + '@rrweb/types@2.0.0-alpha.17': dependencies: - '@react-spring/animated': 9.7.5(react@17.0.2) - '@react-spring/core': 9.7.5(react@17.0.2) - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - konva: 9.3.16 - react: 17.0.2 - react-konva: 18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - - '@react-spring/native@9.7.5(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)': - dependencies: - '@react-spring/animated': 9.7.5(react@17.0.2) - '@react-spring/core': 9.7.5(react@17.0.2) - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - react: 17.0.2 - react-native: 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2) - - '@react-spring/rafz@9.7.5': {} - - '@react-spring/shared@9.7.5(react@17.0.2)': - dependencies: - '@react-spring/rafz': 9.7.5 - '@react-spring/types': 9.7.5 - react: 17.0.2 - - '@react-spring/three@9.7.5(@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0))(react@17.0.2)(three@0.170.0)': - dependencies: - '@react-spring/animated': 9.7.5(react@17.0.2) - '@react-spring/core': 9.7.5(react@17.0.2) - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - '@react-three/fiber': 8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0) - react: 17.0.2 - three: 0.170.0 - - '@react-spring/types@9.7.5': {} - - '@react-spring/web@9.7.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': - dependencies: - '@react-spring/animated': 9.7.5(react@17.0.2) - '@react-spring/core': 9.7.5(react@17.0.2) - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - '@react-spring/zdog@9.7.5(react-dom@17.0.2(react@17.0.2))(react-zdog@1.2.2)(react@17.0.2)(zdog@1.1.3)': - dependencies: - '@react-spring/animated': 9.7.5(react@17.0.2) - '@react-spring/core': 9.7.5(react@17.0.2) - '@react-spring/shared': 9.7.5(react@17.0.2) - '@react-spring/types': 9.7.5 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-zdog: 1.2.2 - zdog: 1.1.3 - - '@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0)': - dependencies: - '@babel/runtime': 7.26.0 - '@types/debounce': 1.2.4 - '@types/react-reconciler': 0.26.7 - '@types/webxr': 0.5.20 - base64-js: 1.5.1 - buffer: 6.0.3 - debounce: 1.2.1 - its-fine: 1.2.5(react@17.0.2) - react: 17.0.2 - react-reconciler: 0.27.0(react@17.0.2) - scheduler: 0.21.0 - suspend-react: 0.1.3(react@17.0.2) - three: 0.170.0 - zustand: 3.7.2(react@17.0.2) - optionalDependencies: - react-dom: 17.0.2(react@17.0.2) - react-native: 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2) + rrweb-snapshot: 2.0.0-alpha.17 '@rtsao/scc@1.1.0': {} - '@safe-global/safe-apps-provider@0.18.4(typescript@4.9.5)(zod@3.23.8)': + '@safe-global/safe-apps-provider@0.18.4(typescript@5.7.2)(zod@3.23.8)': dependencies: - '@safe-global/safe-apps-sdk': 9.1.0(typescript@4.9.5)(zod@3.23.8) + '@safe-global/safe-apps-sdk': 9.1.0(typescript@5.7.2)(zod@3.23.8) events: 3.3.0 transitivePeerDependencies: - bufferutil @@ -13027,30 +12206,32 @@ snapshots: - utf-8-validate - zod - '@safe-global/safe-apps-sdk@8.1.0(typescript@4.9.5)(zod@3.23.8)': + '@safe-global/safe-apps-sdk@8.1.0(typescript@5.7.2)(zod@3.23.8)': dependencies: - '@safe-global/safe-gateway-typescript-sdk': 3.22.3 - viem: 1.21.4(typescript@4.9.5)(zod@3.23.8) + '@safe-global/safe-gateway-typescript-sdk': 3.22.4 + viem: 1.21.4(typescript@5.7.2)(zod@3.23.8) transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - zod - '@safe-global/safe-apps-sdk@9.1.0(typescript@4.9.5)(zod@3.23.8)': + '@safe-global/safe-apps-sdk@9.1.0(typescript@5.7.2)(zod@3.23.8)': dependencies: - '@safe-global/safe-gateway-typescript-sdk': 3.22.3 - viem: 2.21.49(typescript@4.9.5)(zod@3.23.8) + '@safe-global/safe-gateway-typescript-sdk': 3.22.4 + viem: 2.21.50(typescript@5.7.2)(zod@3.23.8) transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - zod - '@safe-global/safe-gateway-typescript-sdk@3.22.3': {} + '@safe-global/safe-gateway-typescript-sdk@3.22.4': {} '@scure/base@1.1.9': {} + '@scure/base@1.2.1': {} + '@scure/bip32@1.3.2': dependencies: '@noble/curves': 1.2.0 @@ -13111,14 +12292,14 @@ snapshots: '@sentry/types': 6.19.7 tslib: 1.14.1 - '@sentry/react@6.19.7(react@17.0.2)': + '@sentry/react@6.19.7(react@18.3.1)': dependencies: '@sentry/browser': 6.19.7 '@sentry/minimal': 6.19.7 '@sentry/types': 6.19.7 '@sentry/utils': 6.19.7 hoist-non-react-statics: 3.3.2 - react: 17.0.2 + react: 18.3.1 tslib: 1.14.1 '@sentry/tracing@6.19.7': @@ -13138,20 +12319,14 @@ snapshots: '@sinclair/typebox@0.27.8': {} + '@sindresorhus/is@4.6.0': {} + '@sindresorhus/merge-streams@2.3.0': {} '@sinonjs/commons@1.8.6': dependencies: type-detect: 4.0.8 - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 - '@sinonjs/fake-timers@8.1.0': dependencies: '@sinonjs/commons': 1.8.6 @@ -13316,6 +12491,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + '@tanstack/query-core@4.36.1': {} '@tanstack/query-persist-client-core@4.36.1': @@ -13326,19 +12505,18 @@ snapshots: dependencies: '@tanstack/query-persist-client-core': 4.36.1 - '@tanstack/react-query-persist-client@4.36.1(@tanstack/react-query@4.36.1(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2))': + '@tanstack/react-query-persist-client@4.36.1(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': dependencies: '@tanstack/query-persist-client-core': 4.36.1 - '@tanstack/react-query': 4.36.1(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2) + '@tanstack/react-query': 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tanstack/react-query@4.36.1(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)': + '@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/query-core': 4.36.1 - react: 17.0.2 - use-sync-external-store: 1.2.2(react@17.0.2) + react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) optionalDependencies: - react-dom: 17.0.2(react@17.0.2) - react-native: 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2) + react-dom: 18.3.1(react@18.3.1) '@tootallnate/once@1.1.2': {} @@ -13346,9 +12524,249 @@ snapshots: dependencies: protobufjs: 7.4.0 + '@tsconfig/node10@1.0.11': + optional: true + + '@tsconfig/node12@1.0.11': + optional: true + + '@tsconfig/node14@1.0.3': + optional: true + + '@tsconfig/node16@1.0.4': + optional: true + + '@tsparticles/basic@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + '@tsparticles/move-base': 3.7.1 + '@tsparticles/plugin-hex-color': 3.7.1 + '@tsparticles/plugin-hsl-color': 3.7.1 + '@tsparticles/plugin-rgb-color': 3.7.1 + '@tsparticles/shape-circle': 3.7.1 + '@tsparticles/updater-color': 3.7.1 + '@tsparticles/updater-opacity': 3.7.1 + '@tsparticles/updater-out-modes': 3.7.1 + '@tsparticles/updater-size': 3.7.1 + + '@tsparticles/engine@3.7.1': {} + + '@tsparticles/interaction-external-attract@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-bounce@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-bubble@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-connect@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-grab@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-pause@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-push@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-remove@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-repulse@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-slow@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-external-trail@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-particles-attract@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-particles-collisions@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/interaction-particles-links@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/move-base@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/move-parallax@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/plugin-absorbers@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/plugin-easing-quad@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/plugin-emitters-shape-circle@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + '@tsparticles/plugin-emitters': 3.7.1 + + '@tsparticles/plugin-emitters-shape-square@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + '@tsparticles/plugin-emitters': 3.7.1 + + '@tsparticles/plugin-emitters@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/plugin-hex-color@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/plugin-hsl-color@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/plugin-rgb-color@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/react@3.0.0(@tsparticles/engine@3.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@tsparticles/engine': 3.7.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@tsparticles/shape-circle@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-emoji@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-image@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-line@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-polygon@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-square@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-star@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/shape-text@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/slim@3.7.1': + dependencies: + '@tsparticles/basic': 3.7.1 + '@tsparticles/engine': 3.7.1 + '@tsparticles/interaction-external-attract': 3.7.1 + '@tsparticles/interaction-external-bounce': 3.7.1 + '@tsparticles/interaction-external-bubble': 3.7.1 + '@tsparticles/interaction-external-connect': 3.7.1 + '@tsparticles/interaction-external-grab': 3.7.1 + '@tsparticles/interaction-external-pause': 3.7.1 + '@tsparticles/interaction-external-push': 3.7.1 + '@tsparticles/interaction-external-remove': 3.7.1 + '@tsparticles/interaction-external-repulse': 3.7.1 + '@tsparticles/interaction-external-slow': 3.7.1 + '@tsparticles/interaction-particles-attract': 3.7.1 + '@tsparticles/interaction-particles-collisions': 3.7.1 + '@tsparticles/interaction-particles-links': 3.7.1 + '@tsparticles/move-parallax': 3.7.1 + '@tsparticles/plugin-easing-quad': 3.7.1 + '@tsparticles/shape-emoji': 3.7.1 + '@tsparticles/shape-image': 3.7.1 + '@tsparticles/shape-line': 3.7.1 + '@tsparticles/shape-polygon': 3.7.1 + '@tsparticles/shape-square': 3.7.1 + '@tsparticles/shape-star': 3.7.1 + '@tsparticles/updater-life': 3.7.1 + '@tsparticles/updater-rotate': 3.7.1 + '@tsparticles/updater-stroke-color': 3.7.1 + + '@tsparticles/updater-color@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-destroy@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-life@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-opacity@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-out-modes@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-roll@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-rotate@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-size@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-stroke-color@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-tilt@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-twinkle@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + + '@tsparticles/updater-wobble@3.7.1': + dependencies: + '@tsparticles/engine': 3.7.1 + '@types/accepts@1.3.7': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/babel__core@7.20.5': dependencies: @@ -13371,22 +12789,25 @@ snapshots: dependencies: '@babel/types': 7.26.0 - '@types/bignumber.js@5.0.4': - dependencies: - bignumber.js: 9.1.2 - '@types/bn.js@4.11.6': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/bn.js@5.1.6': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 17.0.45 + '@types/node': 22.9.3 + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 22.9.3 + '@types/responselike': 1.0.3 '@types/chrome@0.0.186': dependencies: @@ -13404,7 +12825,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/content-disposition@0.5.8': {} @@ -13413,7 +12834,9 @@ snapshots: '@types/connect': 3.4.38 '@types/express': 5.0.0 '@types/keygrip': 1.0.6 - '@types/node': 17.0.45 + '@types/node': 22.9.3 + + '@types/css-font-loading-module@0.0.7': {} '@types/d3-array@3.2.1': {} @@ -13439,8 +12862,6 @@ snapshots: '@types/d3-timer@3.0.2': {} - '@types/debounce@1.2.4': {} - '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -13450,7 +12871,7 @@ snapshots: '@types/eslint': 9.6.1 '@types/estree': 1.0.6 - '@types/eslint@7.29.0': + '@types/eslint@8.56.12': dependencies: '@types/estree': 1.0.6 '@types/json-schema': 7.0.15 @@ -13464,9 +12885,9 @@ snapshots: '@types/events@3.0.3': {} - '@types/express-serve-static-core@5.0.1': + '@types/express-serve-static-core@5.0.2': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/qs': 6.9.17 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -13474,7 +12895,7 @@ snapshots: '@types/express@5.0.0': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 5.0.1 + '@types/express-serve-static-core': 5.0.2 '@types/qs': 6.9.17 '@types/serve-static': 1.15.7 @@ -13487,11 +12908,11 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/har-format@1.2.16': {} @@ -13505,6 +12926,8 @@ snapshots: '@types/http-assert@1.5.6': {} + '@types/http-cache-semantics@4.0.4': {} + '@types/http-errors@2.0.4': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -13530,6 +12953,10 @@ snapshots: '@types/keygrip@1.0.6': {} + '@types/keyv@3.1.4': + dependencies: + '@types/node': 22.9.3 + '@types/koa-compose@3.2.8': dependencies: '@types/koa': 2.15.0 @@ -13543,7 +12970,7 @@ snapshots: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/lodash@4.17.13': {} @@ -13559,11 +12986,11 @@ snapshots: '@types/minimatch@5.1.2': {} + '@types/mixpanel-browser@2.50.2': {} + '@types/ms@0.7.34': {} - '@types/node-forge@1.3.11': - dependencies: - '@types/node': 17.0.45 + '@types/node@16.18.119': {} '@types/node@17.0.45': {} @@ -13571,13 +12998,17 @@ snapshots: dependencies: undici-types: 6.19.8 + '@types/node@22.9.3': + dependencies: + undici-types: 6.19.8 + '@types/offscreencanvas@2019.7.3': {} '@types/parse-json@4.0.2': {} '@types/pbkdf2@3.1.2': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/prettier@2.7.3': {} @@ -13589,54 +13020,47 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/react-dom@17.0.25': - dependencies: - '@types/react': 17.0.83 - - '@types/react-reconciler@0.26.7': + '@types/react-dom@18.3.1': dependencies: - '@types/react': 17.0.83 - - '@types/react-reconciler@0.28.8': - dependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 - '@types/react': 17.0.83 + '@types/react': 18.3.12 '@types/react-router': 5.1.20 '@types/react-router@5.1.20': dependencies: '@types/history': 4.7.11 - '@types/react': 17.0.83 + '@types/react': 18.3.12 '@types/react-transition-group@4.4.11': dependencies: - '@types/react': 17.0.83 + '@types/react': 18.3.12 - '@types/react@17.0.83': + '@types/react@18.3.12': dependencies: '@types/prop-types': 15.7.13 - '@types/scheduler': 0.16.8 csstype: 3.1.3 - '@types/scheduler@0.16.8': {} + '@types/responselike@1.0.3': + dependencies: + '@types/node': 22.9.3 '@types/secp256k1@4.0.6': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/send': 0.17.4 '@types/stack-utils@2.0.3': {} @@ -13649,11 +13073,9 @@ snapshots: '@types/w3c-web-hid@1.0.6': {} - '@types/webxr@0.5.20': {} - '@types/ws@8.5.3': dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 '@types/yargs-parser@21.0.3': {} @@ -13665,34 +13087,39 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5)': + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.9.3 + optional: true + + '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) '@typescript-eslint/scope-manager': 8.15.0 - '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) - '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.15.0 eslint: 9.15.0(jiti@2.4.0) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.4.0(typescript@4.9.5) + ts-api-utils: 1.4.1(typescript@5.7.2) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5)': + '@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2)': dependencies: '@typescript-eslint/scope-manager': 8.15.0 '@typescript-eslint/types': 8.15.0 - '@typescript-eslint/typescript-estree': 8.15.0(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7(supports-color@6.1.0) eslint: 9.15.0(jiti@2.4.0) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - supports-color @@ -13701,21 +13128,21 @@ snapshots: '@typescript-eslint/types': 8.15.0 '@typescript-eslint/visitor-keys': 8.15.0 - '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5)': + '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.15.0(typescript@4.9.5) - '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) debug: 4.3.7(supports-color@6.1.0) eslint: 9.15.0(jiti@2.4.0) - ts-api-utils: 1.4.0(typescript@4.9.5) + ts-api-utils: 1.4.1(typescript@5.7.2) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - supports-color '@typescript-eslint/types@8.15.0': {} - '@typescript-eslint/typescript-estree@8.15.0(typescript@4.9.5)': + '@typescript-eslint/typescript-estree@8.15.0(typescript@5.7.2)': dependencies: '@typescript-eslint/types': 8.15.0 '@typescript-eslint/visitor-keys': 8.15.0 @@ -13724,21 +13151,21 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.4.0(typescript@4.9.5) + ts-api-utils: 1.4.1(typescript@5.7.2) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5)': + '@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@2.4.0)) '@typescript-eslint/scope-manager': 8.15.0 '@typescript-eslint/types': 8.15.0 - '@typescript-eslint/typescript-estree': 8.15.0(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2) eslint: 9.15.0(jiti@2.4.0) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - supports-color @@ -13749,20 +13176,20 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@wagmi/connectors@3.1.11(@types/react@17.0.83)(react@17.0.2)(typescript@4.9.5)(viem@2.21.49(typescript@4.9.5)(zod@3.23.8))(zod@3.23.8)': + '@wagmi/connectors@3.1.11(@types/react@18.3.12)(react@18.3.1)(typescript@5.7.2)(viem@2.21.50(typescript@5.7.2)(zod@3.23.8))(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 3.9.3 - '@safe-global/safe-apps-provider': 0.18.4(typescript@4.9.5)(zod@3.23.8) - '@safe-global/safe-apps-sdk': 8.1.0(typescript@4.9.5)(zod@3.23.8) - '@walletconnect/ethereum-provider': 2.11.0(@types/react@17.0.83)(react@17.0.2) + '@safe-global/safe-apps-provider': 0.18.4(typescript@5.7.2)(zod@3.23.8) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.7.2)(zod@3.23.8) + '@walletconnect/ethereum-provider': 2.11.0(@types/react@18.3.12)(react@18.3.1) '@walletconnect/legacy-provider': 2.0.0 - '@walletconnect/modal': 2.6.2(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal': 2.6.2(@types/react@18.3.12)(react@18.3.1) '@walletconnect/utils': 2.11.0 - abitype: 0.8.7(typescript@4.9.5)(zod@3.23.8) + abitype: 0.8.7(typescript@5.7.2)(zod@3.23.8) eventemitter3: 4.0.7 - viem: 2.21.49(typescript@4.9.5)(zod@3.23.8) + viem: 2.21.50(typescript@5.7.2)(zod@3.23.8) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -13785,15 +13212,15 @@ snapshots: - utf-8-validate - zod - '@wagmi/core@1.4.13(@types/react@17.0.83)(react@17.0.2)(typescript@4.9.5)(viem@2.21.49(typescript@4.9.5)(zod@3.23.8))(zod@3.23.8)': + '@wagmi/core@1.4.13(@types/react@18.3.12)(react@18.3.1)(typescript@5.7.2)(viem@2.21.50(typescript@5.7.2)(zod@3.23.8))(zod@3.23.8)': dependencies: - '@wagmi/connectors': 3.1.11(@types/react@17.0.83)(react@17.0.2)(typescript@4.9.5)(viem@2.21.49(typescript@4.9.5)(zod@3.23.8))(zod@3.23.8) - abitype: 0.8.7(typescript@4.9.5)(zod@3.23.8) + '@wagmi/connectors': 3.1.11(@types/react@18.3.12)(react@18.3.1)(typescript@5.7.2)(viem@2.21.50(typescript@5.7.2)(zod@3.23.8))(zod@3.23.8) + abitype: 0.8.7(typescript@5.7.2)(zod@3.23.8) eventemitter3: 4.0.7 - viem: 2.21.49(typescript@4.9.5)(zod@3.23.8) - zustand: 4.5.5(@types/react@17.0.83)(react@17.0.2) + viem: 2.21.50(typescript@5.7.2)(zod@3.23.8) + zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -13823,7 +13250,7 @@ snapshots: '@ethersproject/transactions': 5.7.0 '@stablelib/random': 1.0.2 '@stablelib/sha256': 1.0.1 - '@walletconnect/core': 2.10.3 + '@walletconnect/core': 2.17.2 '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 @@ -13850,68 +13277,6 @@ snapshots: - ioredis - utf-8-validate - '@walletconnect/browser-utils@1.8.0': - dependencies: - '@walletconnect/safe-json': 1.0.0 - '@walletconnect/types': 1.8.0 - '@walletconnect/window-getters': 1.0.0 - '@walletconnect/window-metadata': 1.0.0 - detect-browser: 5.2.0 - - '@walletconnect/client@1.8.0': - dependencies: - '@walletconnect/core': 1.8.0 - '@walletconnect/iso-crypto': 1.8.0 - '@walletconnect/types': 1.8.0 - '@walletconnect/utils': 1.8.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@walletconnect/core@1.8.0': - dependencies: - '@walletconnect/socket-transport': 1.8.0 - '@walletconnect/types': 1.8.0 - '@walletconnect/utils': 1.8.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@walletconnect/core@2.10.3': - dependencies: - '@walletconnect/heartbeat': 1.2.1 - '@walletconnect/jsonrpc-provider': 1.0.13 - '@walletconnect/jsonrpc-types': 1.0.3 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.13 - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.2 - '@walletconnect/relay-api': 1.0.11 - '@walletconnect/relay-auth': 1.0.4 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.10.3 - '@walletconnect/utils': 2.10.3 - events: 3.3.0 - lodash.isequal: 4.5.0 - uint8arrays: 3.1.1 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/kv' - - bufferutil - - ioredis - - utf-8-validate - '@walletconnect/core@2.11.0': dependencies: '@walletconnect/heartbeat': 1.2.1 @@ -14040,13 +13405,13 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.11.0(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/ethereum-provider@2.11.0(@types/react@18.3.12)(react@18.3.1)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/modal': 2.7.0(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal': 2.7.0(@types/react@18.3.12)(react@18.3.1) '@walletconnect/sign-client': 2.11.0 '@walletconnect/types': 2.11.0 '@walletconnect/universal-provider': 2.11.0 @@ -14089,12 +13454,6 @@ snapshots: '@walletconnect/time': 1.0.2 events: 3.3.0 - '@walletconnect/iso-crypto@1.8.0': - dependencies: - '@walletconnect/crypto': 1.0.3 - '@walletconnect/types': 1.8.0 - '@walletconnect/utils': 1.8.0 - '@walletconnect/jsonrpc-http-connection@1.0.8': dependencies: '@walletconnect/jsonrpc-utils': 1.0.8 @@ -14132,17 +13491,6 @@ snapshots: '@walletconnect/jsonrpc-types': 1.0.4 tslib: 1.14.1 - '@walletconnect/jsonrpc-ws-connection@1.0.13': - dependencies: - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/safe-json': 1.0.2 - events: 3.3.0 - tslib: 1.14.1 - ws: 7.5.10 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - '@walletconnect/jsonrpc-ws-connection@1.0.14': dependencies: '@walletconnect/jsonrpc-utils': 1.0.8 @@ -14190,7 +13538,7 @@ snapshots: '@walletconnect/legacy-types': 2.0.0 '@walletconnect/legacy-utils': 2.0.0 copy-to-clipboard: 3.3.3 - preact: 10.24.3 + preact: 10.25.0 qrcode: 1.5.4 '@walletconnect/legacy-provider@2.0.0': @@ -14224,23 +13572,23 @@ snapshots: '@walletconnect/safe-json': 1.0.2 pino: 7.11.0 - '@walletconnect/modal-core@2.6.2(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/modal-core@2.6.2(@types/react@18.3.12)(react@18.3.1)': dependencies: - valtio: 1.11.2(@types/react@17.0.83)(react@17.0.2) + valtio: 1.11.2(@types/react@18.3.12)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - '@walletconnect/modal-core@2.7.0(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/modal-core@2.7.0(@types/react@18.3.12)(react@18.3.1)': dependencies: - valtio: 1.11.2(@types/react@17.0.83)(react@17.0.2) + valtio: 1.11.2(@types/react@18.3.12)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - '@walletconnect/modal-ui@2.6.2(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/modal-ui@2.6.2(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@walletconnect/modal-core': 2.6.2(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal-core': 2.6.2(@types/react@18.3.12)(react@18.3.1) lit: 2.8.0 motion: 10.16.2 qrcode: 1.5.3 @@ -14248,9 +13596,9 @@ snapshots: - '@types/react' - react - '@walletconnect/modal-ui@2.7.0(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/modal-ui@2.7.0(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@walletconnect/modal-core': 2.7.0(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal-core': 2.7.0(@types/react@18.3.12)(react@18.3.1) lit: 2.8.0 motion: 10.16.2 qrcode: 1.5.3 @@ -14258,18 +13606,18 @@ snapshots: - '@types/react' - react - '@walletconnect/modal@2.6.2(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/modal@2.6.2(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@walletconnect/modal-core': 2.6.2(@types/react@17.0.83)(react@17.0.2) - '@walletconnect/modal-ui': 2.6.2(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal-core': 2.6.2(@types/react@18.3.12)(react@18.3.1) + '@walletconnect/modal-ui': 2.6.2(@types/react@18.3.12)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - '@walletconnect/modal@2.7.0(@types/react@17.0.83)(react@17.0.2)': + '@walletconnect/modal@2.7.0(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@walletconnect/modal-core': 2.7.0(@types/react@17.0.83)(react@17.0.2) - '@walletconnect/modal-ui': 2.7.0(@types/react@17.0.83)(react@17.0.2) + '@walletconnect/modal-core': 2.7.0(@types/react@18.3.12)(react@18.3.1) + '@walletconnect/modal-ui': 2.7.0(@types/react@18.3.12)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react @@ -14292,9 +13640,7 @@ snapshots: '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 tslib: 1.14.1 - uint8arrays: 3.1.1 - - '@walletconnect/safe-json@1.0.0': {} + uint8arrays: 3.1.0 '@walletconnect/safe-json@1.0.2': dependencies: @@ -14366,47 +13712,7 @@ snapshots: '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 '@walletconnect/types': 2.17.2 - '@walletconnect/utils': 2.17.2 - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/kv' - - bufferutil - - ioredis - - utf-8-validate - - '@walletconnect/socket-transport@1.8.0': - dependencies: - '@walletconnect/types': 1.8.0 - '@walletconnect/utils': 1.8.0 - ws: 7.5.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@walletconnect/time@1.0.2': - dependencies: - tslib: 1.14.1 - - '@walletconnect/types@1.8.0': {} - - '@walletconnect/types@2.10.3': - dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.1 - '@walletconnect/jsonrpc-types': 1.0.3 - '@walletconnect/keyvaluestorage': 1.1.1 - '@walletconnect/logger': 2.1.2 + '@walletconnect/utils': 2.17.2 events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -14421,7 +13727,13 @@ snapshots: - '@react-native-async-storage/async-storage' - '@upstash/redis' - '@vercel/kv' + - bufferutil - ioredis + - utf-8-validate + + '@walletconnect/time@1.0.2': + dependencies: + tslib: 1.14.1 '@walletconnect/types@2.11.0': dependencies: @@ -14521,47 +13833,6 @@ snapshots: - ioredis - utf-8-validate - '@walletconnect/utils@1.8.0': - dependencies: - '@walletconnect/browser-utils': 1.8.0 - '@walletconnect/encoding': 1.0.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/types': 1.8.0 - bn.js: 4.11.8 - js-sha3: 0.8.0 - query-string: 6.13.5 - - '@walletconnect/utils@2.10.3': - dependencies: - '@stablelib/chacha20poly1305': 1.0.1 - '@stablelib/hkdf': 1.0.1 - '@stablelib/random': 1.0.2 - '@stablelib/sha256': 1.0.1 - '@stablelib/x25519': 1.0.3 - '@walletconnect/relay-api': 1.0.11 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.10.3 - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 - detect-browser: 5.3.0 - query-string: 7.1.3 - uint8arrays: 3.1.1 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/kv' - - ioredis - '@walletconnect/utils@2.11.0': dependencies: '@stablelib/chacha20poly1305': 1.0.1 @@ -14695,16 +13966,10 @@ snapshots: - ioredis - utf-8-validate - '@walletconnect/window-getters@1.0.0': {} - '@walletconnect/window-getters@1.0.1': dependencies: tslib: 1.14.1 - '@walletconnect/window-metadata@1.0.0': - dependencies: - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata@1.0.1': dependencies: '@walletconnect/window-getters': 1.0.1 @@ -14802,13 +14067,15 @@ snapshots: optionalDependencies: webpack-dev-server: 3.11.3(webpack-cli@4.10.0)(webpack@5.96.1) - '@welldone-software/why-did-you-render@6.2.3(react@17.0.2)': + '@welldone-software/why-did-you-render@6.2.3(react@18.3.1)': dependencies: lodash: 4.17.21 - react: 17.0.2 + react: 18.3.1 '@xobotyi/scrollbar-width@1.9.5': {} + '@xstate/fsm@1.6.5': {} + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -14821,26 +14088,26 @@ snapshots: abab@2.0.6: {} - abitype@0.7.1(typescript@4.9.5)(zod@3.23.8): + abitype@0.7.1(typescript@5.7.2)(zod@3.23.8): dependencies: - typescript: 4.9.5 + typescript: 5.7.2 optionalDependencies: zod: 3.23.8 - abitype@0.8.7(typescript@4.9.5)(zod@3.23.8): + abitype@0.8.7(typescript@5.7.2)(zod@3.23.8): dependencies: - typescript: 4.9.5 + typescript: 5.7.2 optionalDependencies: zod: 3.23.8 - abitype@0.9.8(typescript@4.9.5)(zod@3.23.8): + abitype@0.9.8(typescript@5.7.2)(zod@3.23.8): optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 zod: 3.23.8 - abitype@1.0.6(typescript@4.9.5)(zod@3.23.8): + abitype@1.0.6(typescript@5.7.2)(zod@3.23.8): optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 zod: 3.23.8 abort-controller@3.0.0: @@ -14912,7 +14179,9 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - anser@1.4.10: {} + ansi-align@2.0.0: + dependencies: + string-width: 2.1.1 ansi-colors@3.2.4: {} @@ -14964,14 +14233,15 @@ snapshots: are-docs-informative@0.0.2: {} + arg@4.1.3: + optional: true + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 argparse@2.0.1: {} - aria-query@5.3.2: {} - arr-diff@4.0.0: {} arr-flatten@1.1.0: {} @@ -15071,10 +14341,6 @@ snapshots: arrify@1.0.1: {} - arrify@2.0.1: {} - - asap@2.0.6: {} - asn1.js@4.10.1: dependencies: bn.js: 4.12.1 @@ -15093,12 +14359,6 @@ snapshots: assign-symbols@1.0.0: {} - ast-types-flow@0.0.8: {} - - ast-types@0.15.2: - dependencies: - tslib: 2.8.1 - async-each@1.0.6: {} async-limiter@1.0.1: {} @@ -15122,7 +14382,7 @@ snapshots: autoprefixer@10.4.20(postcss@8.4.49): dependencies: browserslist: 4.24.2 - caniuse-lite: 1.0.30001683 + caniuse-lite: 1.0.30001684 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -15133,8 +14393,6 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 - axe-core@4.10.2: {} - axios-rate-limit@1.4.0(axios@0.21.4): dependencies: axios: 0.21.4 @@ -15159,24 +14417,6 @@ snapshots: transitivePeerDependencies: - debug - axobject-query@4.1.0: {} - - babel-core@7.0.0-bridge.0(@babel/core@7.26.0): - dependencies: - '@babel/core': 7.26.0 - - babel-eslint@10.1.0(eslint@9.15.0(jiti@2.4.0)): - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - eslint: 9.15.0(jiti@2.4.0) - eslint-visitor-keys: 1.3.0 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - babel-jest@27.5.1(@babel/core@7.26.0): dependencies: '@babel/core': 7.26.0 @@ -15191,19 +14431,6 @@ snapshots: transitivePeerDependencies: - supports-color - babel-jest@29.7.0(@babel/core@7.26.0): - dependencies: - '@babel/core': 7.26.0 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.26.0) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - babel-plugin-istanbul@6.1.1: dependencies: '@babel/helper-plugin-utils': 7.25.9 @@ -15221,13 +14448,6 @@ snapshots: '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 - babel-plugin-jest-hoist@29.6.3: - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 - babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.26.0 @@ -15258,20 +14478,6 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-syntax-hermes-parser@0.23.1: - dependencies: - hermes-parser: 0.23.1 - - babel-plugin-syntax-hermes-parser@0.25.1: - dependencies: - hermes-parser: 0.25.1 - - babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.26.0): - dependencies: - '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.0) - transitivePeerDependencies: - - '@babel/core' - babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.0): dependencies: '@babel/core': 7.26.0 @@ -15297,12 +14503,6 @@ snapshots: babel-plugin-jest-hoist: 27.5.1 babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - babel-preset-jest@29.6.3(@babel/core@7.26.0): - dependencies: - '@babel/core': 7.26.0 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - bail@2.0.2: {} balanced-match@1.0.2: {} @@ -15311,6 +14511,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + base64-arraybuffer@1.0.2: {} + base64-js@1.5.1: {} base@0.11.2: @@ -15349,7 +14551,7 @@ snapshots: bip39@3.1.0: dependencies: - '@noble/hashes': 1.5.0 + '@noble/hashes': 1.6.1 bip66@1.1.5: dependencies: @@ -15361,8 +14563,6 @@ snapshots: bn.js@4.11.6: {} - bn.js@4.11.8: {} - bn.js@4.12.1: {} bn.js@5.2.1: {} @@ -15395,6 +14595,9 @@ snapshots: boolbase@1.0.0: {} + boolean@3.2.0: + optional: true + borc@2.1.2: dependencies: bignumber.js: 9.1.2 @@ -15405,6 +14608,16 @@ snapshots: json-text-sequence: 0.1.1 readable-stream: 3.6.2 + boxen@1.3.0: + dependencies: + ansi-align: 2.0.0 + camelcase: 4.1.0 + chalk: 2.4.2 + cli-boxes: 1.0.0 + string-width: 2.1.1 + term-size: 1.2.0 + widest-line: 2.0.1 + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -15478,7 +14691,7 @@ snapshots: create-hash: 1.2.0 create-hmac: 1.1.7 elliptic: 6.6.1 - hash-base: 3.0.4 + hash-base: 3.0.5 inherits: 2.0.4 parse-asn1: 5.1.7 readable-stream: 2.3.8 @@ -15488,15 +14701,11 @@ snapshots: browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001683 + caniuse-lite: 1.0.30001684 electron-to-chromium: 1.5.64 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - bs58@2.0.1: {} bs58@4.0.1: @@ -15513,6 +14722,8 @@ snapshots: dependencies: node-int64: 0.4.0 + buffer-crc32@0.2.13: {} + buffer-from@1.1.2: {} buffer-indexof@1.1.1: {} @@ -15547,6 +14758,18 @@ snapshots: union-value: 1.0.1 unset-value: 1.0.0 + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -15555,16 +14778,6 @@ snapshots: get-intrinsic: 1.2.4 set-function-length: 1.2.2 - caller-callsite@2.0.0: - dependencies: - callsites: 2.0.0 - - caller-path@2.0.0: - dependencies: - caller-callsite: 2.0.0 - - callsites@2.0.0: {} - callsites@3.1.0: {} camel-case@4.1.2: @@ -15584,7 +14797,9 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001683: {} + caniuse-lite@1.0.30001684: {} + + capture-stack-trace@1.0.2: {} ccount@2.0.1: {} @@ -15649,29 +14864,9 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chrome-launcher@0.15.2: - dependencies: - '@types/node': 17.0.45 - escape-string-regexp: 4.0.0 - is-wsl: 2.2.0 - lighthouse-logger: 1.4.2 - transitivePeerDependencies: - - supports-color - chrome-trace-event@1.0.4: {} - chromium-edge-launcher@0.2.0: - dependencies: - '@types/node': 17.0.45 - escape-string-regexp: 4.0.0 - is-wsl: 2.2.0 - lighthouse-logger: 1.4.2 - mkdirp: 1.0.4 - rimraf: 3.0.2 - transitivePeerDependencies: - - supports-color - - ci-info@2.0.0: {} + ci-info@1.6.0: {} ci-info@3.9.0: {} @@ -15699,6 +14894,8 @@ snapshots: dependencies: source-map: 0.6.1 + cli-boxes@1.0.0: {} + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -15750,6 +14947,10 @@ snapshots: kind-of: 6.0.3 shallow-clone: 3.0.1 + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + clsx@1.2.1: {} clsx@2.1.1: {} @@ -15806,8 +15007,6 @@ snapshots: comment-parser@1.4.1: {} - commondir@1.0.1: {} - compare-versions@4.1.4: {} component-emitter@1.3.1: {} @@ -15832,19 +15031,17 @@ snapshots: confbox@0.1.8: {} - confusing-browser-globals@1.0.11: {} + configstore@3.1.5: + dependencies: + dot-prop: 4.2.1 + graceful-fs: 4.2.11 + make-dir: 1.3.0 + unique-string: 1.0.0 + write-file-atomic: 2.4.3 + xdg-basedir: 3.0.0 connect-history-api-fallback@1.6.0: {} - connect@3.7.0: - dependencies: - debug: 2.6.9(supports-color@6.1.0) - finalhandler: 1.1.2 - parseurl: 1.3.3 - utils-merge: 1.0.1 - transitivePeerDependencies: - - supports-color - consola@3.2.3: {} content-disposition@0.5.4: @@ -15887,13 +15084,6 @@ snapshots: core-util-is@1.0.3: {} - cosmiconfig@5.2.1: - dependencies: - import-fresh: 2.0.0 - is-directory: 0.3.1 - js-yaml: 3.14.1 - parse-json: 4.0.0 - cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.2 @@ -15909,6 +15099,10 @@ snapshots: bn.js: 4.12.1 elliptic: 6.6.1 + create-error-class@3.0.2: + dependencies: + capture-stack-trace: 1.0.2 + create-hash@1.2.0: dependencies: cipher-base: 1.0.5 @@ -15926,6 +15120,9 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 + create-require@1.1.1: + optional: true + cross-fetch@3.1.8: dependencies: node-fetch: 2.7.0 @@ -15938,6 +15135,12 @@ snapshots: transitivePeerDependencies: - encoding + cross-spawn@5.1.0: + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + cross-spawn@6.0.6: dependencies: nice-try: 1.0.5 @@ -15964,7 +15167,7 @@ snapshots: create-hash: 1.2.0 create-hmac: 1.1.7 diffie-hellman: 5.0.3 - hash-base: 3.0.4 + hash-base: 3.0.5 inherits: 2.0.4 pbkdf2: 3.1.2 public-encrypt: 4.0.3 @@ -15973,6 +15176,8 @@ snapshots: crypto-js@4.2.0: {} + crypto-random-string@1.0.0: {} + css-in-js-utils@3.1.0: dependencies: hyphenate-style-name: 1.1.0 @@ -16085,8 +15290,6 @@ snapshots: d3-timer@3.0.1: {} - damerau-levenshtein@1.0.8: {} - data-urls@2.0.0: dependencies: abab: 2.0.6 @@ -16154,6 +15357,10 @@ snapshots: decode-uri-component@0.2.2: {} + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + dedent@0.7.0: {} deep-eql@4.1.4: @@ -16169,6 +15376,8 @@ snapshots: object-keys: 1.1.1 regexp.prototype.flags: 1.5.3 + deep-extend@0.6.0: {} + deep-is@0.1.4: {} deepmerge@4.3.1: {} @@ -16178,6 +15387,8 @@ snapshots: execa: 1.0.0 ip-regex: 2.1.0 + defer-to-connect@2.0.1: {} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 @@ -16221,8 +15432,6 @@ snapshots: delimit-stream@0.1.0: {} - denodeify@1.2.1: {} - depd@1.1.2: {} depd@2.0.0: {} @@ -16238,8 +15447,6 @@ snapshots: destroy@1.2.0: {} - detect-browser@5.2.0: {} - detect-browser@5.3.0: {} detect-libc@1.0.3: {} @@ -16252,6 +15459,9 @@ snapshots: diff@3.5.0: {} + diff@4.0.2: + optional: true + diff@5.2.0: {} diffie-hellman@5.0.3: @@ -16329,6 +15539,10 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 + dot-prop@4.2.1: + dependencies: + is-obj: 1.0.1 + dotenv-defaults@2.0.2: dependencies: dotenv: 8.6.0 @@ -16348,6 +15562,8 @@ snapshots: create-hash: 1.2.0 create-hmac: 1.1.7 + duplexer3@0.1.5: {} + duplexer@0.1.2: {} duplexify@4.1.3: @@ -16365,6 +15581,14 @@ snapshots: electron-to-chromium@1.5.64: {} + electron@23.3.13: + dependencies: + '@electron/get': 2.0.3 + '@types/node': 16.18.119 + extract-zip: 2.0.1 + transitivePeerDependencies: + - supports-color + elliptic@6.5.4: dependencies: bn.js: 4.12.1 @@ -16413,8 +15637,6 @@ snapshots: emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - emojis-list@3.0.0: {} encode-utf8@1.0.3: {} @@ -16439,6 +15661,8 @@ snapshots: entities@2.2.0: {} + env-paths@2.2.1: {} + envinfo@7.14.0: {} environment@1.1.0: {} @@ -16499,8 +15723,8 @@ snapshots: string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.2 typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 + typed-array-byte-offset: 1.0.3 + typed-array-length: 1.0.7 unbox-primitive: 1.0.2 which-typed-array: 1.1.15 @@ -16552,6 +15776,9 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + es6-error@4.1.1: + optional: true + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -16576,21 +15803,6 @@ snapshots: dependencies: eslint: 9.15.0(jiti@2.4.0) - eslint-config-react-app@6.0.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(babel-eslint@10.1.0(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-flowtype@5.10.0(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-import@2.31.0)(eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-react-hooks@5.0.0(eslint@9.15.0(jiti@2.4.0)))(eslint-plugin-react@7.37.2(eslint@9.15.0(jiti@2.4.0)))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5): - dependencies: - '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) - babel-eslint: 10.1.0(eslint@9.15.0(jiti@2.4.0)) - confusing-browser-globals: 1.0.11 - eslint: 9.15.0(jiti@2.4.0) - eslint-plugin-flowtype: 5.10.0(eslint@9.15.0(jiti@2.4.0)) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.15.0(jiti@2.4.0)) - eslint-plugin-react: 7.37.2(eslint@9.15.0(jiti@2.4.0)) - eslint-plugin-react-hooks: 5.0.0(eslint@9.15.0(jiti@2.4.0)) - optionalDependencies: - typescript: 4.9.5 - eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7(supports-color@6.1.0) @@ -16599,43 +15811,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7(supports-color@6.1.0) enhanced-resolve: 5.17.1 eslint: 9.15.0(jiti@2.4.0) - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)): dependencies: debug: 3.2.7(supports-color@6.1.0) optionalDependencies: - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) eslint: 9.15.0(jiti@2.4.0) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-plugin-import@2.31.0)(eslint@9.15.0(jiti@2.4.0)) transitivePeerDependencies: - supports-color - eslint-plugin-flowtype@5.10.0(eslint@9.15.0(jiti@2.4.0)): - dependencies: - eslint: 9.15.0(jiti@2.4.0) - lodash: 4.17.21 - string-natural-compare: 3.0.1 - - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -16646,7 +15852,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.15.0(jiti@2.4.0) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.15.0(jiti@2.4.0)) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -16658,7 +15864,7 @@ snapshots: string.prototype.trimend: 1.0.8 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -16679,25 +15885,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.15.0(jiti@2.4.0)): - dependencies: - aria-query: 5.3.2 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.8 - axe-core: 4.10.2 - axobject-query: 4.1.0 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 9.15.0(jiti@2.4.0) - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - language-tags: 1.0.9 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - safe-regex-test: 1.0.3 - string.prototype.includes: 2.0.1 - eslint-plugin-prettier@3.4.1(eslint-config-prettier@9.1.0(eslint@9.15.0(jiti@2.4.0)))(eslint@9.15.0(jiti@2.4.0))(prettier@3.3.3): dependencies: eslint: 9.15.0(jiti@2.4.0) @@ -16732,15 +15919,6 @@ snapshots: string.prototype.matchall: 4.0.11 string.prototype.repeat: 1.0.0 - eslint-plugin-unused-imports@2.0.0(@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0)): - dependencies: - eslint: 9.15.0(jiti@2.4.0) - eslint-rule-composer: 0.3.0 - optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) - - eslint-rule-composer@0.3.0: {} - eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 @@ -16756,21 +15934,18 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-visitor-keys@1.3.0: {} - eslint-visitor-keys@3.4.3: {} eslint-visitor-keys@4.2.0: {} - eslint-webpack-plugin@2.7.0(eslint@9.15.0(jiti@2.4.0))(webpack@5.96.1): + eslint-webpack-plugin@4.2.0(eslint@9.15.0(jiti@2.4.0))(webpack@5.96.1): dependencies: - '@types/eslint': 7.29.0 - arrify: 2.0.1 + '@types/eslint': 8.56.12 eslint: 9.15.0(jiti@2.4.0) - jest-worker: 27.5.1 + jest-worker: 29.7.0 micromatch: 4.0.8 normalize-path: 3.0.0 - schema-utils: 3.3.0 + schema-utils: 4.2.0 webpack: 5.96.1(webpack-cli@4.10.0) eslint@8.57.1: @@ -16899,7 +16074,7 @@ snapshots: eth-eip712-util-browser@0.0.3: dependencies: - bn.js: 4.12.1 + bn.js: 5.2.1 buffer: 6.0.3 js-sha3: 0.8.0 @@ -16944,7 +16119,7 @@ snapshots: ethereum-bloom-filters@1.2.0: dependencies: - '@noble/hashes': 1.5.0 + '@noble/hashes': 1.6.1 ethereum-checksum-address@0.0.5: dependencies: @@ -17096,6 +16271,16 @@ snapshots: md5.js: 1.3.5 safe-buffer: 5.2.1 + execa@0.7.0: + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + execa@1.0.0: dependencies: cross-spawn: 6.0.6 @@ -17151,8 +16336,6 @@ snapshots: jest-matcher-utils: 27.5.1 jest-message-util: 27.5.1 - exponential-backoff@3.1.1: {} - express@4.21.1(supports-color@6.1.0): dependencies: accepts: 1.3.8 @@ -17213,6 +16396,16 @@ snapshots: transitivePeerDependencies: - supports-color + extract-zip@2.0.1: + dependencies: + debug: 4.3.7(supports-color@6.1.0) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -17255,6 +16448,12 @@ snapshots: dependencies: bser: 2.1.1 + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fflate@0.4.8: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -17286,18 +16485,6 @@ snapshots: filter-obj@1.1.0: {} - finalhandler@1.1.2: - dependencies: - debug: 2.6.9(supports-color@6.1.0) - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.3.0 - parseurl: 1.3.3 - statuses: 1.5.0 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - finalhandler@1.3.1(supports-color@6.1.0): dependencies: debug: 2.6.9(supports-color@6.1.0) @@ -17310,12 +16497,6 @@ snapshots: transitivePeerDependencies: - supports-color - find-cache-dir@2.1.0: - dependencies: - commondir: 1.0.1 - make-dir: 2.1.0 - pkg-dir: 3.0.0 - find-root@1.1.0: {} find-up@2.1.0: @@ -17384,16 +16565,12 @@ snapshots: flatted@3.3.2: {} - flow-enums-runtime@0.0.6: {} - flow-native-token-registry@0.1.6: dependencies: cross-fetch: 3.1.8 transitivePeerDependencies: - encoding - flow-parser@0.254.1: {} - follow-redirects@1.15.9(debug@4.3.7(supports-color@6.1.0)): optionalDependencies: debug: 4.3.7(supports-color@6.1.0) @@ -17447,6 +16624,12 @@ snapshots: jsonfile: 6.1.0 universalify: 2.0.1 + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + fs.realpath@1.0.0: {} fsevents@1.2.13: @@ -17489,10 +16672,16 @@ snapshots: get-port-please@3.1.2: {} + get-stream@3.0.0: {} + get-stream@4.1.0: dependencies: pump: 3.0.2 + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + get-stream@6.0.1: {} get-stream@8.0.1: {} @@ -17533,6 +16722,20 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + global-agent@3.0.0: + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.6.3 + serialize-error: 7.0.1 + optional: true + + global-dirs@0.1.1: + dependencies: + ini: 1.3.8 + globals@11.12.0: {} globals@13.24.0: @@ -17575,6 +16778,36 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + got@6.7.1: + dependencies: + '@types/keyv': 3.1.4 + '@types/responselike': 1.0.3 + create-error-class: 3.0.2 + duplexer3: 0.1.5 + get-stream: 3.0.0 + is-redirect: 1.0.0 + is-retry-allowed: 1.2.0 + is-stream: 1.1.0 + lowercase-keys: 1.0.1 + safe-buffer: 5.2.1 + timed-out: 4.0.1 + unzip-response: 2.0.1 + url-parse-lax: 1.0.0 + graceful-fs@4.2.11: {} graphemer@1.4.0: {} @@ -17654,7 +16887,7 @@ snapshots: is-number: 3.0.0 kind-of: 4.0.0 - hash-base@3.0.4: + hash-base@3.0.5: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 @@ -17678,24 +16911,6 @@ snapshots: he@1.2.0: {} - hermes-estree@0.23.1: {} - - hermes-estree@0.24.0: {} - - hermes-estree@0.25.1: {} - - hermes-parser@0.23.1: - dependencies: - hermes-estree: 0.23.1 - - hermes-parser@0.24.0: - dependencies: - hermes-estree: 0.24.0 - - hermes-parser@0.25.1: - dependencies: - hermes-estree: 0.25.1 - hey-listen@1.0.8: {} highlight.js@10.7.3: {} @@ -17767,6 +16982,8 @@ snapshots: domutils: 2.8.0 entities: 2.2.0 + http-cache-semantics@4.1.1: {} + http-deceiver@1.2.7: {} http-errors@1.6.3: @@ -17814,6 +17031,11 @@ snapshots: http-shutdown@1.2.2: {} + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + https-browserify@1.0.0: {} https-proxy-agent@5.0.1: @@ -17831,9 +17053,11 @@ snapshots: hyphenate-style-name@1.1.0: {} - i18next@20.6.1: + i18next@24.0.0(typescript@5.7.2): dependencies: '@babel/runtime': 7.26.0 + optionalDependencies: + typescript: 5.7.2 iconfont-parser@1.0.0: dependencies: @@ -17860,22 +17084,15 @@ snapshots: ignore@5.3.2: {} - image-size@1.1.1: - dependencies: - queue: 6.0.2 - immediate@3.0.6: {} - import-fresh@2.0.0: - dependencies: - caller-path: 2.0.0 - resolve-from: 3.0.0 - import-fresh@3.3.0: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 + import-lazy@2.1.0: {} + import-local@2.0.0: dependencies: pkg-dir: 3.0.0 @@ -17899,6 +17116,8 @@ snapshots: inherits@2.0.4: {} + ini@1.3.8: {} + inline-style-parser@0.1.1: {} inline-style-prefixer@7.0.1: @@ -17922,10 +17141,6 @@ snapshots: interpret@2.2.0: {} - invariant@2.2.4: - dependencies: - loose-envify: 1.4.0 - ip-regex@2.1.0: {} ip@1.1.9: {} @@ -17987,6 +17202,10 @@ snapshots: is-callable@1.2.7: {} + is-ci@1.2.1: + dependencies: + ci-info: 1.6.0 + is-core-module@2.15.1: dependencies: hasown: 2.0.2 @@ -18013,10 +17232,6 @@ snapshots: is-accessor-descriptor: 1.0.1 is-data-descriptor: 1.0.1 - is-directory@0.3.1: {} - - is-docker@2.2.1: {} - is-docker@3.0.0: {} is-extendable@0.1.1: {} @@ -18027,7 +17242,7 @@ snapshots: is-extglob@2.1.1: {} - is-finalizationregistry@1.0.2: + is-finalizationregistry@1.1.0: dependencies: call-bind: 1.0.7 @@ -18063,6 +17278,11 @@ snapshots: dependencies: is-docker: 3.0.0 + is-installed-globally@0.1.0: + dependencies: + global-dirs: 0.1.1 + is-path-inside: 1.0.1 + is-map@2.0.3: {} is-nan@1.3.2: @@ -18072,6 +17292,8 @@ snapshots: is-negative-zero@2.0.3: {} + is-npm@1.0.0: {} + is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.2 @@ -18082,12 +17304,18 @@ snapshots: is-number@7.0.0: {} + is-obj@1.0.1: {} + is-path-cwd@2.2.0: {} is-path-in-cwd@2.1.0: dependencies: is-path-inside: 2.1.0 + is-path-inside@1.0.1: + dependencies: + path-is-inside: 1.0.2 + is-path-inside@2.1.0: dependencies: path-is-inside: 1.0.2 @@ -18104,11 +17332,15 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-redirect@1.0.0: {} + is-regex@1.1.4: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 + is-retry-allowed@1.2.0: {} + is-set@2.0.3: {} is-shared-array-buffer@1.0.3: @@ -18152,10 +17384,6 @@ snapshots: is-wsl@1.1.0: {} - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - is-wsl@3.1.0: dependencies: is-inside-container: 1.0.0 @@ -18235,14 +17463,9 @@ snapshots: define-properties: 1.2.1 get-intrinsic: 1.2.4 has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.6 + reflect.getprototypeof: 1.0.7 set-function-name: 2.0.2 - its-fine@1.2.5(react@17.0.2): - dependencies: - '@types/react-reconciler': 0.28.8 - react: 17.0.2 - jest-changed-files@27.5.1: dependencies: '@jest/types': 27.5.1 @@ -18254,7 +17477,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -18273,16 +17496,16 @@ snapshots: transitivePeerDependencies: - supports-color - jest-cli@27.5.1: + jest-cli@27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)): dependencies: - '@jest/core': 27.5.1 + '@jest/core': 27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)) '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 import-local: 3.2.0 - jest-config: 27.5.1 + jest-config: 27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)) jest-util: 27.5.1 jest-validate: 27.5.1 prompts: 2.4.2 @@ -18294,7 +17517,7 @@ snapshots: - ts-node - utf-8-validate - jest-config@27.5.1: + jest-config@27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)): dependencies: '@babel/core': 7.26.0 '@jest/test-sequencer': 27.5.1 @@ -18320,6 +17543,8 @@ snapshots: pretty-format: 27.5.1 slash: 3.0.0 strip-json-comments: 3.1.1 + optionalDependencies: + ts-node: 10.9.2(@types/node@22.9.3)(typescript@5.7.2) transitivePeerDependencies: - bufferutil - canvas @@ -18350,7 +17575,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0 @@ -18365,28 +17590,17 @@ snapshots: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 jest-mock: 27.5.1 jest-util: 27.5.1 - jest-environment-node@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 17.0.45 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jest-get-type@27.5.1: {} - jest-get-type@29.6.3: {} - jest-haste-map@27.5.1: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.9 - '@types/node': 17.0.45 + '@types/node': 22.9.3 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -18399,29 +17613,13 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - jest-haste-map@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 17.0.45 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - jest-jasmine2@27.5.1: dependencies: '@jest/environment': 27.5.1 '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 co: 4.6.0 expect: 27.5.1 @@ -18461,28 +17659,10 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 - jest-message-util@29.7.0: - dependencies: - '@babel/code-frame': 7.26.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - jest-mock@27.5.1: dependencies: '@jest/types': 27.5.1 - '@types/node': 17.0.45 - - jest-mock@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 17.0.45 - jest-util: 29.7.0 + '@types/node': 22.9.3 jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): optionalDependencies: @@ -18490,8 +17670,6 @@ snapshots: jest-regex-util@27.5.1: {} - jest-regex-util@29.6.3: {} - jest-resolve-dependencies@27.5.1: dependencies: '@jest/types': 27.5.1 @@ -18520,7 +17698,7 @@ snapshots: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.11 @@ -18571,7 +17749,7 @@ snapshots: jest-serializer@27.5.1: dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 graceful-fs: 4.2.11 jest-snapshot@27.5.1: @@ -18604,7 +17782,7 @@ snapshots: jest-util@27.5.1: dependencies: '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -18613,7 +17791,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 17.0.45 + '@types/node': 22.9.3 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -18628,20 +17806,11 @@ snapshots: leven: 3.1.0 pretty-format: 27.5.1 - jest-validate@29.7.0: - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - jest-watcher@27.5.1: dependencies: '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 17.0.45 + '@types/node': 22.9.3 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.5.1 @@ -18649,22 +17818,22 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 17.0.45 + '@types/node': 22.9.3 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@27.5.1: + jest@27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)): dependencies: - '@jest/core': 27.5.1 + '@jest/core': 27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)) import-local: 3.2.0 - jest-cli: 27.5.1 + jest-cli: 27.5.1(ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2)) transitivePeerDependencies: - bufferutil - canvas @@ -18689,35 +17858,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsc-android@250231.0.0: {} - - jsc-safe-url@0.2.4: {} - - jscodeshift@0.14.0(@babel/preset-env@7.26.0(@babel/core@7.26.0)): - dependencies: - '@babel/core': 7.26.0 - '@babel/parser': 7.26.2 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.26.0) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.26.0) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.26.0) - '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) - '@babel/preset-env': 7.26.0(@babel/core@7.26.0) - '@babel/preset-flow': 7.25.9(@babel/core@7.26.0) - '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) - '@babel/register': 7.25.9(@babel/core@7.26.0) - babel-core: 7.0.0-bridge.0(@babel/core@7.26.0) - chalk: 4.1.2 - flow-parser: 0.254.1 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - neo-async: 2.6.2 - node-dir: 0.1.17 - recast: 0.21.5 - temp: 0.8.4 - write-file-atomic: 2.4.3 - transitivePeerDependencies: - - supports-color - jsdoc-type-pratt-parser@4.0.0: {} jsdom@16.7.0: @@ -18775,6 +17915,9 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json-stringify-safe@5.0.1: + optional: true + json-text-sequence@0.1.1: dependencies: delimit-stream: 0.1.0 @@ -18785,6 +17928,10 @@ snapshots: json5@2.2.3: {} + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + jsonfile@6.1.0: dependencies: universalify: 2.0.1 @@ -18893,13 +18040,9 @@ snapshots: koa-compose@4.1.0: {} - konva@9.3.16: {} - - language-subtag-registry@0.3.23: {} - - language-tags@1.0.9: + latest-version@3.1.0: dependencies: - language-subtag-registry: 0.3.23 + package-json: 4.0.1 leven@3.1.0: {} @@ -18908,16 +18051,15 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lie@3.3.0: + libsodium-wrappers@0.7.15: dependencies: - immediate: 3.0.6 + libsodium: 0.7.15 - lighthouse-logger@1.4.2: + libsodium@0.7.15: {} + + lie@3.3.0: dependencies: - debug: 2.6.9(supports-color@6.1.0) - marky: 1.2.5 - transitivePeerDependencies: - - supports-color + immediate: 3.0.6 lilconfig@3.1.2: {} @@ -19023,12 +18165,8 @@ snapshots: lodash.isequal@4.5.0: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} - lodash.throttle@4.1.1: {} - lodash@4.17.21: {} log-update@6.1.0: @@ -19068,8 +18206,17 @@ snapshots: dependencies: tslib: 2.8.1 + lowercase-keys@1.0.1: {} + + lowercase-keys@2.0.0: {} + lru-cache@10.4.3: {} + lru-cache@4.1.5: + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -19078,16 +18225,16 @@ snapshots: dependencies: yallist: 4.0.0 - make-dir@2.1.0: + make-dir@1.3.0: dependencies: - pify: 4.0.1 - semver: 5.7.2 + pify: 3.0.0 make-dir@4.0.0: dependencies: semver: 7.6.3 - make-error@1.3.6: {} + make-error@1.3.6: + optional: true makeerror@1.0.12: dependencies: @@ -19105,11 +18252,14 @@ snapshots: markdown-table@3.0.4: {} - marky@1.2.5: {} + matcher@3.0.0: + dependencies: + escape-string-regexp: 4.0.0 + optional: true md5.js@1.3.5: dependencies: - hash-base: 3.0.4 + hash-base: 3.0.5 inherits: 2.0.4 safe-buffer: 5.2.1 @@ -19254,185 +18404,6 @@ snapshots: methods@1.1.2: {} - metro-babel-transformer@0.81.0: - dependencies: - '@babel/core': 7.26.0 - flow-enums-runtime: 0.0.6 - hermes-parser: 0.24.0 - nullthrows: 1.1.1 - transitivePeerDependencies: - - supports-color - - metro-cache-key@0.81.0: - dependencies: - flow-enums-runtime: 0.0.6 - - metro-cache@0.81.0: - dependencies: - exponential-backoff: 3.1.1 - flow-enums-runtime: 0.0.6 - metro-core: 0.81.0 - - metro-config@0.81.0: - dependencies: - connect: 3.7.0 - cosmiconfig: 5.2.1 - flow-enums-runtime: 0.0.6 - jest-validate: 29.7.0 - metro: 0.81.0 - metro-cache: 0.81.0 - metro-core: 0.81.0 - metro-runtime: 0.81.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - metro-core@0.81.0: - dependencies: - flow-enums-runtime: 0.0.6 - lodash.throttle: 4.1.1 - metro-resolver: 0.81.0 - - metro-file-map@0.81.0: - dependencies: - anymatch: 3.1.3 - debug: 2.6.9(supports-color@6.1.0) - fb-watchman: 2.0.2 - flow-enums-runtime: 0.0.6 - graceful-fs: 4.2.11 - invariant: 2.2.4 - jest-worker: 29.7.0 - micromatch: 4.0.8 - node-abort-controller: 3.1.1 - nullthrows: 1.1.1 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - transitivePeerDependencies: - - supports-color - - metro-minify-terser@0.81.0: - dependencies: - flow-enums-runtime: 0.0.6 - terser: 5.36.0 - - metro-resolver@0.81.0: - dependencies: - flow-enums-runtime: 0.0.6 - - metro-runtime@0.81.0: - dependencies: - '@babel/runtime': 7.26.0 - flow-enums-runtime: 0.0.6 - - metro-source-map@0.81.0: - dependencies: - '@babel/traverse': 7.25.9 - '@babel/traverse--for-generate-function-map': '@babel/traverse@7.25.9' - '@babel/types': 7.26.0 - flow-enums-runtime: 0.0.6 - invariant: 2.2.4 - metro-symbolicate: 0.81.0 - nullthrows: 1.1.1 - ob1: 0.81.0 - source-map: 0.5.7 - vlq: 1.0.1 - transitivePeerDependencies: - - supports-color - - metro-symbolicate@0.81.0: - dependencies: - flow-enums-runtime: 0.0.6 - invariant: 2.2.4 - metro-source-map: 0.81.0 - nullthrows: 1.1.1 - source-map: 0.5.7 - through2: 2.0.5 - vlq: 1.0.1 - transitivePeerDependencies: - - supports-color - - metro-transform-plugins@0.81.0: - dependencies: - '@babel/core': 7.26.0 - '@babel/generator': 7.26.2 - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - flow-enums-runtime: 0.0.6 - nullthrows: 1.1.1 - transitivePeerDependencies: - - supports-color - - metro-transform-worker@0.81.0: - dependencies: - '@babel/core': 7.26.0 - '@babel/generator': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - flow-enums-runtime: 0.0.6 - metro: 0.81.0 - metro-babel-transformer: 0.81.0 - metro-cache: 0.81.0 - metro-cache-key: 0.81.0 - metro-minify-terser: 0.81.0 - metro-source-map: 0.81.0 - metro-transform-plugins: 0.81.0 - nullthrows: 1.1.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - metro@0.81.0: - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/core': 7.26.0 - '@babel/generator': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - accepts: 1.3.8 - chalk: 4.1.2 - ci-info: 2.0.0 - connect: 3.7.0 - debug: 2.6.9(supports-color@6.1.0) - denodeify: 1.2.1 - error-stack-parser: 2.1.4 - flow-enums-runtime: 0.0.6 - graceful-fs: 4.2.11 - hermes-parser: 0.24.0 - image-size: 1.1.1 - invariant: 2.2.4 - jest-worker: 29.7.0 - jsc-safe-url: 0.2.4 - lodash.throttle: 4.1.1 - metro-babel-transformer: 0.81.0 - metro-cache: 0.81.0 - metro-cache-key: 0.81.0 - metro-config: 0.81.0 - metro-core: 0.81.0 - metro-file-map: 0.81.0 - metro-resolver: 0.81.0 - metro-runtime: 0.81.0 - metro-source-map: 0.81.0 - metro-symbolicate: 0.81.0 - metro-transform-plugins: 0.81.0 - metro-transform-worker: 0.81.0 - mime-types: 2.1.35 - nullthrows: 1.1.1 - serialize-error: 2.1.0 - source-map: 0.5.7 - strip-ansi: 6.0.1 - throat: 5.0.0 - ws: 7.5.10 - yargs: 17.7.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - micro-ftch@0.3.1: {} micromark-core-commonmark@1.1.0: @@ -19674,6 +18645,10 @@ snapshots: mimic-function@5.0.1: {} + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -19693,17 +18668,21 @@ snapshots: minimist@1.2.8: {} + mitt@3.0.1: {} + mixin-deep@1.3.2: dependencies: for-in: 1.0.2 is-extendable: 1.0.1 + mixpanel-browser@2.56.0: + dependencies: + rrweb: 2.0.0-alpha.13 + mkdirp@0.5.6: dependencies: minimist: 1.2.8 - mkdirp@1.0.4: {} - mlly@1.7.3: dependencies: acorn: 8.14.0 @@ -19739,15 +18718,15 @@ snapshots: nan@2.22.0: {} - nano-css@5.6.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + nano-css@5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@jridgewell/sourcemap-codec': 1.5.0 css-tree: 1.1.3 csstype: 3.1.3 fastest-stable-stringify: 2.0.2 inline-style-prefixer: 7.0.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) rtl-css-js: 1.16.1 stacktrace-js: 2.0.2 stylis: 4.3.4 @@ -19793,18 +18772,12 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 - node-abort-controller@3.1.1: {} - node-addon-api@2.0.2: {} node-addon-api@5.1.0: {} node-addon-api@7.1.1: {} - node-dir@0.1.17: - dependencies: - minimatch: 3.1.2 - node-fetch-native@1.6.4: {} node-fetch@2.7.0: @@ -19836,6 +18809,8 @@ snapshots: normalize-range@0.1.2: {} + normalize-url@6.1.0: {} + npm-run-path@2.0.2: dependencies: path-key: 2.0.1 @@ -19856,8 +18831,6 @@ snapshots: dependencies: boolbase: 1.0.0 - nullthrows@1.1.1: {} - number-to-bn@1.7.0: dependencies: bn.js: 4.11.6 @@ -19865,10 +18838,6 @@ snapshots: nwsapi@2.2.13: {} - ob1@0.81.0: - dependencies: - flow-enums-runtime: 0.0.6 - object-assign@4.1.1: {} object-copy@0.1.0: @@ -19955,10 +18924,6 @@ snapshots: on-exit-leak-free@0.2.0: {} - on-finished@2.3.0: - dependencies: - ee-first: 1.1.1 - on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -19981,11 +18946,6 @@ snapshots: dependencies: mimic-function: 5.0.1 - open@7.4.2: - dependencies: - is-docker: 2.2.1 - is-wsl: 2.2.0 - opener@1.5.2: {} opn@5.5.0: @@ -20003,20 +18963,22 @@ snapshots: os-browserify@0.3.0: {} - ox@0.1.2(typescript@4.9.5)(zod@3.23.8): + ox@0.1.2(typescript@5.7.2)(zod@3.23.8): dependencies: '@adraffy/ens-normalize': 1.11.0 '@noble/curves': 1.6.0 '@noble/hashes': 1.5.0 '@scure/bip32': 1.5.0 '@scure/bip39': 1.4.0 - abitype: 1.0.6(typescript@4.9.5)(zod@3.23.8) + abitype: 1.0.6(typescript@5.7.2)(zod@3.23.8) eventemitter3: 5.0.1 optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - zod + p-cancelable@2.1.1: {} + p-finally@1.0.0: {} p-limit@1.3.0: @@ -20057,6 +19019,13 @@ snapshots: p-try@2.2.0: {} + package-json@4.0.1: + dependencies: + got: 6.7.1 + registry-auth-token: 3.4.0 + registry-url: 3.1.0 + semver: 5.7.2 + pako@1.0.11: {} param-case@3.0.4: @@ -20073,7 +19042,7 @@ snapshots: asn1.js: 4.10.1 browserify-aes: 1.2.0 evp_bytestokey: 1.0.3 - hash-base: 3.0.4 + hash-base: 3.0.5 pbkdf2: 3.1.2 safe-buffer: 5.2.1 @@ -20146,9 +19115,7 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 - performance-now@0.2.0: {} - - performance-now@2.1.0: {} + pend@1.2.0: {} picocolors@0.2.1: {} @@ -20302,10 +19269,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - preact@10.24.3: {} + preact@10.25.0: {} prelude-ls@1.2.1: {} + prepend-http@1.0.4: {} + prettier-linter-helpers@1.0.0: dependencies: fast-diff: 1.3.0 @@ -20323,21 +19292,13 @@ snapshots: ansi-styles: 5.2.0 react-is: 17.0.2 - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - process-nextick-args@2.0.1: {} process-warning@1.0.0: {} process@0.11.10: {} - promise@8.3.0: - dependencies: - asap: 2.0.6 + progress@2.0.3: {} prompts@2.4.2: dependencies: @@ -20364,7 +19325,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 17.0.45 + '@types/node': 22.9.3 long: 5.2.3 proxy-addr@2.0.7: @@ -20378,6 +19339,8 @@ snapshots: prr@1.0.1: {} + pseudomap@1.0.2: {} + psl@1.13.0: dependencies: punycode: 2.3.1 @@ -20433,12 +19396,6 @@ snapshots: dependencies: side-channel: 1.0.6 - query-string@6.13.5: - dependencies: - decode-uri-component: 0.2.2 - split-on-first: 1.1.0 - strict-uri-encode: 2.0.0 - query-string@6.14.1: dependencies: decode-uri-component: 0.2.2 @@ -20457,19 +19414,13 @@ snapshots: queue-microtask@1.2.3: {} - queue@6.0.2: - dependencies: - inherits: 2.0.4 - quick-format-unescaped@4.0.4: {} quick-lru@1.1.0: {} - radix3@1.1.2: {} + quick-lru@5.1.1: {} - raf@3.4.1: - dependencies: - performance-now: 2.1.0 + radix3@1.1.2: {} randombytes@2.1.0: dependencies: @@ -20495,19 +19446,26 @@ snapshots: schema-utils: 3.3.0 webpack: 5.96.1(webpack-cli@4.10.0) - react-component-transition@2.1.2(@types/react-dom@17.0.25)(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + react-component-transition@2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@types/classnames': 2.3.4 - '@types/react': 17.0.83 - '@types/react-dom': 17.0.25 + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 '@types/uniqid': 5.3.4 classnames: 2.5.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-intersection-observer: 8.34.0(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-intersection-observer: 8.34.0(react@18.3.1) uniqid: 5.4.0 - react-devtools-core@5.3.2: + react-devtools-core@4.28.5: dependencies: shell-quote: 1.8.1 ws: 7.5.10 @@ -20515,12 +19473,18 @@ snapshots: - bufferutil - utf-8-validate - react-dom@17.0.2(react@17.0.2): + react-devtools@4.28.5: dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react: 17.0.2 - scheduler: 0.20.2 + cross-spawn: 5.1.0 + electron: 23.3.13 + ip: 1.1.9 + minimist: 1.2.8 + react-devtools-core: 4.28.5 + update-notifier: 2.5.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate react-dom@18.3.1(react@18.3.1): dependencies: @@ -20528,34 +19492,33 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-event-listener@0.6.6(react@17.0.2): + react-event-listener@0.6.6(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 warning: 4.0.3 - react-highlight@0.14.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-highlight@0.14.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: highlight.js: 10.7.3 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-hook-form@7.53.2(react@17.0.2): + react-hook-form@7.53.2(react@18.3.1): dependencies: - react: 17.0.2 + react: 18.3.1 - react-i18next@11.18.6(i18next@20.6.1)(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2): + react-i18next@15.1.1(i18next@24.0.0(typescript@5.7.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 html-parse-stringify: 3.0.1 - i18next: 20.6.1 - react: 17.0.2 + i18next: 24.0.0(typescript@5.7.2) + react: 18.3.1 optionalDependencies: - react-dom: 17.0.2(react@17.0.2) - react-native: 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2) + react-dom: 18.3.1(react@18.3.1) - react-iconfont-cli@2.0.2(react@17.0.2): + react-iconfont-cli@2.0.2(react@18.3.1): dependencies: colors: 1.4.0 glob: 7.2.3 @@ -20563,24 +19526,24 @@ snapshots: lodash: 4.17.21 minimist: 1.2.8 mkdirp: 0.5.6 - react: 17.0.2 + react: 18.3.1 tslib: 1.14.1 transitivePeerDependencies: - supports-color - react-infinite-scroll-component@6.1.0(react@17.0.2): + react-infinite-scroll-component@6.1.0(react@18.3.1): dependencies: - react: 17.0.2 + react: 18.3.1 throttle-debounce: 2.3.0 - react-infinite-scroller@1.2.6(react@17.0.2): + react-infinite-scroller@1.2.6(react@18.3.1): dependencies: prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 - react-intersection-observer@8.34.0(react@17.0.2): + react-intersection-observer@8.34.0(react@18.3.1): dependencies: - react: 17.0.2 + react: 18.3.1 react-is@16.13.1: {} @@ -20588,26 +19551,16 @@ snapshots: react-is@18.3.1: {} - react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2): - dependencies: - '@types/react-reconciler': 0.28.8 - its-fine: 1.2.5(react@17.0.2) - konva: 9.3.16 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-reconciler: 0.29.2(react@17.0.2) - scheduler: 0.23.2 - - react-markdown@7.1.2(@types/react@17.0.83)(react@17.0.2): + react-markdown@7.1.2(@types/react@18.3.12)(react@18.3.1): dependencies: '@types/hast': 2.3.10 - '@types/react': 17.0.83 + '@types/react': 18.3.12 '@types/unist': 2.0.11 comma-separated-tokens: 2.0.3 hast-util-whitespace: 2.0.1 prop-types: 15.8.1 property-information: 6.5.0 - react: 17.0.2 + react: 18.3.1 react-is: 17.0.2 remark-parse: 10.0.2 remark-rehype: 9.1.0 @@ -20619,116 +19572,35 @@ snapshots: transitivePeerDependencies: - supports-color - react-motion@0.5.2(react@17.0.2): - dependencies: - performance-now: 0.2.0 - prop-types: 15.8.1 - raf: 3.4.1 - react: 17.0.2 - - react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2): - dependencies: - '@jest/create-cache-key-function': 29.7.0 - '@react-native/assets-registry': 0.76.3 - '@react-native/codegen': 0.76.3(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - '@react-native/community-cli-plugin': 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0)) - '@react-native/gradle-plugin': 0.76.3 - '@react-native/js-polyfills': 0.76.3 - '@react-native/normalize-colors': 0.76.3 - '@react-native/virtualized-lists': 0.76.3(@types/react@17.0.83)(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2) - abort-controller: 3.0.0 - anser: 1.4.10 - ansi-regex: 5.0.1 - babel-jest: 29.7.0(@babel/core@7.26.0) - babel-plugin-syntax-hermes-parser: 0.23.1 - base64-js: 1.5.1 - chalk: 4.1.2 - commander: 12.1.0 - event-target-shim: 5.0.1 - flow-enums-runtime: 0.0.6 - glob: 7.2.3 - invariant: 2.2.4 - jest-environment-node: 29.7.0 - jsc-android: 250231.0.0 - memoize-one: 5.2.1 - metro-runtime: 0.81.0 - metro-source-map: 0.81.0 - mkdirp: 0.5.6 - nullthrows: 1.1.1 - pretty-format: 29.7.0 - promise: 8.3.0 - react: 17.0.2 - react-devtools-core: 5.3.2 - react-refresh: 0.14.2 - regenerator-runtime: 0.13.11 - scheduler: 0.24.0-canary-efb381bbf-20230505 - semver: 7.6.3 - stacktrace-parser: 0.1.10 - whatwg-fetch: 3.6.20 - ws: 6.2.3 - yargs: 17.7.2 - optionalDependencies: - '@types/react': 17.0.83 - transitivePeerDependencies: - - '@babel/core' - - '@babel/preset-env' - - '@react-native-community/cli-server-api' - - bufferutil - - encoding - - supports-color - - utf-8-validate - - react-number-format@4.9.4(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-number-format@4.9.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-placeholder-image@0.1.8(react@17.0.2): + react-placeholder-image@0.1.8(react@18.3.1): dependencies: - react: 17.0.2 + react: 18.3.1 - react-qrcode-logo@2.10.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-qrcode-logo@2.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: lodash.isequal: 4.5.0 qrcode-generator: 1.4.4 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - react-reconciler@0.27.0(react@17.0.2): - dependencies: - loose-envify: 1.4.0 - react: 17.0.2 - scheduler: 0.21.0 - - react-reconciler@0.29.2(react@17.0.2): - dependencies: - loose-envify: 1.4.0 - react: 17.0.2 - scheduler: 0.23.2 - - react-refresh@0.14.2: {} + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-router-dom@5.3.4(react@17.0.2): + react-router-dom@5.3.4(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 history: 4.10.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 17.0.2 - react-router: 5.3.4(react@17.0.2) + react: 18.3.1 + react-router: 5.3.4(react@18.3.1) tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - react-router-transition@2.1.0(react-dom@17.0.2(react@17.0.2))(react-router-dom@5.3.4(react@17.0.2))(react@17.0.2): - dependencies: - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-motion: 0.5.2(react@17.0.2) - react-router-dom: 5.3.4(react@17.0.2) - - react-router@5.3.4(react@17.0.2): + react-router@5.3.4(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 history: 4.10.1 @@ -20736,105 +19608,66 @@ snapshots: loose-envify: 1.4.0 path-to-regexp: 1.9.0 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 react-is: 16.13.1 tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - react-smooth@4.0.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-smooth@4.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: fast-equals: 5.0.1 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-transition-group: 4.4.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-spring@8.0.27(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-spring@8.0.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - react-spring@9.7.4(@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0))(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react-zdog@1.2.2)(react@17.0.2)(three@0.170.0)(zdog@1.1.3): - dependencies: - '@react-spring/core': 9.7.5(react@17.0.2) - '@react-spring/konva': 9.7.5(konva@9.3.16)(react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react@17.0.2) - '@react-spring/native': 9.7.5(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2) - '@react-spring/three': 9.7.5(@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0))(react@17.0.2)(three@0.170.0) - '@react-spring/web': 9.7.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spring/zdog': 9.7.5(react-dom@17.0.2(react@17.0.2))(react-zdog@1.2.2)(react@17.0.2)(zdog@1.1.3) - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - transitivePeerDependencies: - - '@react-three/fiber' - - konva - - react-konva - - react-native - - react-zdog - - three - - zdog + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-swipeable-views-core@0.14.0: dependencies: '@babel/runtime': 7.0.0 warning: 4.0.3 - react-swipeable-views-utils@0.14.0(react@17.0.2): + react-swipeable-views-utils@0.14.0(react@18.3.1): dependencies: '@babel/runtime': 7.0.0 keycode: 2.2.1 prop-types: 15.8.1 - react-event-listener: 0.6.6(react@17.0.2) + react-event-listener: 0.6.6(react@18.3.1) react-swipeable-views-core: 0.14.0 shallow-equal: 1.2.1 transitivePeerDependencies: - react - react-swipeable-views@0.14.0(react@17.0.2): + react-swipeable-views@0.14.0(react@18.3.1): dependencies: '@babel/runtime': 7.0.0 prop-types: 15.8.1 - react: 17.0.2 + react: 18.3.1 react-swipeable-views-core: 0.14.0 - react-swipeable-views-utils: 0.14.0(react@17.0.2) + react-swipeable-views-utils: 0.14.0(react@18.3.1) warning: 4.0.3 - react-text-transition@2.0.0(@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0))(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react-zdog@1.2.2)(react@17.0.2)(three@0.170.0)(zdog@1.1.3): - dependencies: - react: 17.0.2 - react-spring: 9.7.4(@react-three/fiber@8.17.10(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(three@0.170.0))(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react-konva@18.2.10(konva@9.3.16)(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react-zdog@1.2.2)(react@17.0.2)(three@0.170.0)(zdog@1.1.3) - transitivePeerDependencies: - - '@react-three/fiber' - - konva - - react-dom - - react-konva - - react-native - - react-zdog - - three - - zdog - - react-transition-group@4.4.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - react-tsparticles@1.43.1(react@17.0.2): - dependencies: - fast-deep-equal: 3.1.3 - react: 17.0.2 - tsparticles: 1.43.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-universal-interface@0.6.2(react@17.0.2)(tslib@2.8.1): + react-universal-interface@0.6.2(react@18.3.1)(tslib@2.8.1): dependencies: - react: 17.0.2 + react: 18.3.1 tslib: 2.8.1 - react-use@17.5.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-use@17.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@types/js-cookie': 2.2.7 '@xobotyi/scrollbar-width': 1.9.5 @@ -20842,10 +19675,10 @@ snapshots: fast-deep-equal: 3.1.3 fast-shallow-equal: 1.0.0 js-cookie: 2.2.1 - nano-css: 5.6.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - react-universal-interface: 0.6.2(react@17.0.2)(tslib@2.8.1) + nano-css: 5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-universal-interface: 0.6.2(react@18.3.1)(tslib@2.8.1) resize-observer-polyfill: 1.5.1 screenfull: 5.2.0 set-harmonic-interval: 1.0.1 @@ -20853,23 +19686,12 @@ snapshots: ts-easing: 0.2.0 tslib: 2.8.1 - react-window@1.8.10(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + react-window@1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 memoize-one: 5.2.1 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - react-zdog@1.2.2: - dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - resize-observer-polyfill: 1.5.1 - - react@17.0.2: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 react@18.3.1: dependencies: @@ -20918,30 +19740,21 @@ snapshots: dependencies: picomatch: 2.3.1 - readline@1.3.0: {} - real-require@0.1.0: {} - recast@0.21.5: - dependencies: - ast-types: 0.15.2 - esprima: 4.0.1 - source-map: 0.6.1 - tslib: 2.8.1 - recharts-scale@0.4.5: dependencies: decimal.js-light: 2.5.1 - recharts@2.13.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2): + recharts@2.13.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: clsx: 2.1.1 eventemitter3: 4.0.7 lodash: 4.17.21 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-is: 18.3.1 - react-smooth: 4.0.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + react-smooth: 4.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) recharts-scale: 0.4.5 tiny-invariant: 1.3.3 victory-vendor: 36.9.2 @@ -20961,15 +19774,15 @@ snapshots: reflect-metadata@0.1.14: {} - reflect.getprototypeof@1.0.6: + reflect.getprototypeof@1.0.7: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.5 es-errors: 1.3.0 get-intrinsic: 1.2.4 - globalthis: 1.0.4 - which-builtin-type: 1.1.4 + gopd: 1.0.1 + which-builtin-type: 1.2.0 regenerate-unicode-properties@10.2.0: dependencies: @@ -20979,8 +19792,6 @@ snapshots: regenerator-runtime@0.12.1: {} - regenerator-runtime@0.13.11: {} - regenerator-runtime@0.14.1: {} regenerator-transform@0.15.2: @@ -21008,6 +19819,15 @@ snapshots: unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.0 + registry-auth-token@3.4.0: + dependencies: + rc: 1.2.8 + safe-buffer: 5.2.1 + + registry-url@3.1.0: + dependencies: + rc: 1.2.8 + regjsgen@0.8.0: {} regjsparser@0.12.0: @@ -21064,6 +19884,8 @@ snapshots: resize-observer-polyfill@1.5.1: {} + resolve-alpn@1.2.1: {} + resolve-cwd@2.0.0: dependencies: resolve-from: 3.0.0 @@ -21098,6 +19920,10 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -21111,10 +19937,6 @@ snapshots: rfdc@1.4.1: {} - rimraf@2.6.3: - dependencies: - glob: 7.2.3 - rimraf@2.7.1: dependencies: glob: 7.2.3 @@ -21125,7 +19947,7 @@ snapshots: ripemd160@2.0.2: dependencies: - hash-base: 3.0.4 + hash-base: 3.0.5 inherits: 2.0.4 rlp-browser@1.0.1: @@ -21138,6 +19960,35 @@ snapshots: rlp@3.0.0: {} + roarr@2.15.4: + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.4 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.3 + optional: true + + rrdom@2.0.0-alpha.17: + dependencies: + rrweb-snapshot: 2.0.0-alpha.17 + + rrweb-snapshot@2.0.0-alpha.17: + dependencies: + postcss: 8.4.49 + + rrweb@2.0.0-alpha.13: + dependencies: + '@rrweb/types': 2.0.0-alpha.17 + '@types/css-font-loading-module': 0.0.7 + '@xstate/fsm': 1.6.5 + base64-arraybuffer: 1.0.2 + fflate: 0.4.8 + mitt: 3.0.1 + rrdom: 2.0.0-alpha.17 + rrweb-snapshot: 2.0.0-alpha.17 + rtl-css-js@1.16.1: dependencies: '@babel/runtime': 7.26.0 @@ -21195,23 +20046,10 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.20.2: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - - scheduler@0.21.0: - dependencies: - loose-envify: 1.4.0 - scheduler@0.23.2: dependencies: loose-envify: 1.4.0 - scheduler@0.24.0-canary-efb381bbf-20230505: - dependencies: - loose-envify: 1.4.0 - schema-utils@1.0.0: dependencies: ajv: 6.12.6 @@ -21252,7 +20090,7 @@ snapshots: secp256k1@4.0.2: dependencies: - elliptic: 6.6.1 + elliptic: 6.5.4 node-addon-api: 2.0.2 node-gyp-build: 4.8.4 @@ -21270,10 +20108,12 @@ snapshots: dependencies: node-forge: 0.10.0 - selfsigned@2.4.1: + semver-compare@1.0.0: + optional: true + + semver-diff@2.1.0: dependencies: - '@types/node-forge': 1.3.11 - node-forge: 1.3.1 + semver: 5.7.2 semver@5.7.2: {} @@ -21299,7 +20139,10 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-error@2.1.0: {} + serialize-error@7.0.1: + dependencies: + type-fest: 0.13.1 + optional: true serialize-javascript@6.0.2: dependencies: @@ -21567,6 +20410,9 @@ snapshots: sprintf-js@1.0.3: {} + sprintf-js@1.1.3: + optional: true + stable@0.1.8: {} stack-generator@2.0.10: @@ -21590,10 +20436,6 @@ snapshots: stack-generator: 2.0.10 stacktrace-gps: 3.1.2 - stacktrace-parser@0.1.10: - dependencies: - type-fest: 0.7.1 - static-extend@0.1.2: dependencies: define-property: 0.2.5 @@ -21628,8 +20470,6 @@ snapshots: char-regex: 1.0.2 strip-ansi: 6.0.1 - string-natural-compare@3.0.1: {} - string-width@2.1.1: dependencies: is-fullwidth-code-point: 2.0.0 @@ -21653,12 +20493,6 @@ snapshots: get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 - string.prototype.includes@2.0.1: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.5 - string.prototype.matchall@4.0.11: dependencies: call-bind: 1.0.7 @@ -21742,6 +20576,8 @@ snapshots: strip-indent@2.0.0: {} + strip-json-comments@2.0.1: {} + strip-json-comments@3.1.1: {} style-loader@2.0.0(webpack@5.96.1): @@ -21758,6 +20594,12 @@ snapshots: stylis@4.3.4: {} + sumchecker@3.0.1: + dependencies: + debug: 4.3.7(supports-color@6.1.0) + transitivePeerDependencies: + - supports-color + superagent@3.8.3: dependencies: component-emitter: 1.3.1 @@ -21798,10 +20640,6 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - suspend-react@0.1.3(react@17.0.2): - dependencies: - react: 17.0.2 - svg-parser@2.0.4: {} svgo@1.3.2: @@ -21835,9 +20673,9 @@ snapshots: tapable@2.2.1: {} - temp@0.8.4: + term-size@1.2.0: dependencies: - rimraf: 2.6.3 + execa: 0.7.0 terminal-link@2.1.1: dependencies: @@ -21875,10 +20713,6 @@ snapshots: dependencies: real-require: 0.1.0 - three@0.170.0: {} - - throat@5.0.0: {} - throat@6.0.2: {} throttle-debounce@2.3.0: {} @@ -21892,6 +20726,8 @@ snapshots: thunky@1.1.0: {} + timed-out@4.0.1: {} + tiny-emitter@2.1.0: {} tiny-invariant@1.3.3: {} @@ -21943,9 +20779,9 @@ snapshots: trough@2.2.0: {} - ts-api-utils@1.4.0(typescript@4.9.5): + ts-api-utils@1.4.1(typescript@5.7.2): dependencies: - typescript: 4.9.5 + typescript: 5.7.2 ts-custom-error@2.2.2: {} @@ -21955,33 +20791,35 @@ snapshots: dependencies: tslib: 2.8.1 - ts-jest@27.1.5(@babel/core@7.26.0)(@types/jest@27.5.2)(babel-jest@27.5.1(@babel/core@7.26.0))(jest@27.5.1)(typescript@4.9.5): - dependencies: - bs-logger: 0.2.6 - fast-json-stable-stringify: 2.1.0 - jest: 27.5.1 - jest-util: 27.5.1 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 4.9.5 - yargs-parser: 20.2.9 - optionalDependencies: - '@babel/core': 7.26.0 - '@types/jest': 27.5.2 - babel-jest: 27.5.1(@babel/core@7.26.0) - - ts-loader@9.5.1(typescript@4.9.5)(webpack@5.96.1): + ts-loader@9.5.1(typescript@5.7.2)(webpack@5.96.1): dependencies: chalk: 4.1.2 enhanced-resolve: 5.17.1 micromatch: 4.0.8 semver: 7.6.3 source-map: 0.7.4 - typescript: 4.9.5 + typescript: 5.7.2 webpack: 5.96.1(webpack-cli@4.10.0) + ts-node@10.9.2(@types/node@22.9.3)(typescript@5.7.2): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.9.3 + acorn: 8.14.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.7.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + ts-toolbelt@9.6.0: {} tsconfig-paths-webpack-plugin@3.5.2: @@ -22003,7 +20841,21 @@ snapshots: tslib@2.8.1: {} - tsparticles@1.43.1: {} + tsparticles@3.6.0: + dependencies: + '@tsparticles/engine': 3.7.1 + '@tsparticles/interaction-external-trail': 3.7.1 + '@tsparticles/plugin-absorbers': 3.7.1 + '@tsparticles/plugin-emitters': 3.7.1 + '@tsparticles/plugin-emitters-shape-circle': 3.7.1 + '@tsparticles/plugin-emitters-shape-square': 3.7.1 + '@tsparticles/shape-text': 3.7.1 + '@tsparticles/slim': 3.7.1 + '@tsparticles/updater-destroy': 3.7.1 + '@tsparticles/updater-roll': 3.7.1 + '@tsparticles/updater-tilt': 3.7.1 + '@tsparticles/updater-twinkle': 3.7.1 + '@tsparticles/updater-wobble': 3.7.1 tweetnacl-util@0.15.1: {} @@ -22017,12 +20869,13 @@ snapshots: type-detect@4.1.0: {} + type-fest@0.13.1: + optional: true + type-fest@0.20.2: {} type-fest@0.21.3: {} - type-fest@0.7.1: {} - type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -22042,7 +20895,7 @@ snapshots: has-proto: 1.0.3 is-typed-array: 1.1.13 - typed-array-byte-offset@1.0.2: + typed-array-byte-offset@1.0.3: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -22050,37 +20903,38 @@ snapshots: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 + reflect.getprototypeof: 1.0.7 - typed-array-length@1.0.6: + typed-array-length@1.0.7: dependencies: call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 - has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 + reflect.getprototypeof: 1.0.7 typedarray-to-buffer@3.1.5: dependencies: is-typedarray: 1.0.0 - typescript-eslint@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5): + typescript-eslint@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5))(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) - '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@4.9.5) + '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2))(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) + '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) + '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@2.4.0))(typescript@5.7.2) eslint: 9.15.0(jiti@2.4.0) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - supports-color - typescript-transform-paths@3.5.2(typescript@4.9.5): + typescript-transform-paths@3.5.2(typescript@5.7.2): dependencies: minimatch: 9.0.5 - typescript: 4.9.5 + typescript: 5.7.2 - typescript@4.9.5: {} + typescript@5.7.2: {} ufo@1.5.4: {} @@ -22147,6 +21001,10 @@ snapshots: uniqid@5.4.0: {} + unique-string@1.0.0: + dependencies: + crypto-random-string: 1.0.0 + unist-builder@3.0.1: dependencies: '@types/unist': 2.0.11 @@ -22176,6 +21034,8 @@ snapshots: unist-util-is: 5.2.1 unist-util-visit-parents: 5.1.3 + universalify@0.1.2: {} + universalify@0.2.0: {} universalify@2.0.1: {} @@ -22212,6 +21072,8 @@ snapshots: consola: 3.2.3 pathe: 1.1.2 + unzip-response@2.0.1: {} + upath@1.2.0: {} update-browserslist-db@1.1.1(browserslist@4.24.2): @@ -22220,6 +21082,19 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-notifier@2.5.0: + dependencies: + boxen: 1.3.0 + chalk: 2.4.2 + configstore: 3.1.5 + import-lazy: 2.1.0 + is-ci: 1.2.1 + is-installed-globally: 0.1.0 + is-npm: 1.0.0 + latest-version: 3.1.0 + semver-diff: 2.1.0 + xdg-basedir: 3.0.0 + uqr@0.1.2: {} uri-js@4.4.1: @@ -22239,6 +21114,10 @@ snapshots: optionalDependencies: file-loader: 6.2.0(webpack@5.96.1) + url-parse-lax@1.0.0: + dependencies: + prepend-http: 1.0.4 + url-parse@1.5.10: dependencies: querystringify: 2.2.0 @@ -22249,13 +21128,13 @@ snapshots: punycode: 1.4.1 qs: 6.13.1 - use-sync-external-store@1.2.0(react@17.0.2): + use-sync-external-store@1.2.0(react@18.3.1): dependencies: - react: 17.0.2 + react: 18.3.1 - use-sync-external-store@1.2.2(react@17.0.2): + use-sync-external-store@1.2.2(react@18.3.1): dependencies: - react: 17.0.2 + react: 18.3.1 use@3.1.1: {} @@ -22299,6 +21178,9 @@ snapshots: kleur: 4.1.5 sade: 1.8.1 + v8-compile-cache-lib@3.0.1: + optional: true + v8-to-istanbul@8.1.1: dependencies: '@types/istanbul-lib-coverage': 2.0.6 @@ -22310,13 +21192,13 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - valtio@1.11.2(@types/react@17.0.83)(react@17.0.2): + valtio@1.11.2(@types/react@18.3.12)(react@18.3.1): dependencies: proxy-compare: 2.5.1 - use-sync-external-store: 1.2.0(react@17.0.2) + use-sync-external-store: 1.2.0(react@18.3.1) optionalDependencies: - '@types/react': 17.0.83 - react: 17.0.2 + '@types/react': 18.3.12 + react: 18.3.1 value-equal@1.0.1: {} @@ -22351,43 +21233,41 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - viem@1.21.4(typescript@4.9.5)(zod@3.23.8): + viem@1.21.4(typescript@5.7.2)(zod@3.23.8): dependencies: '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.2.0 '@noble/hashes': 1.3.2 '@scure/bip32': 1.3.2 '@scure/bip39': 1.2.1 - abitype: 0.9.8(typescript@4.9.5)(zod@3.23.8) + abitype: 0.9.8(typescript@5.7.2)(zod@3.23.8) isows: 1.0.3(ws@8.13.0) ws: 8.13.0 optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - bufferutil - utf-8-validate - zod - viem@2.21.49(typescript@4.9.5)(zod@3.23.8): + viem@2.21.50(typescript@5.7.2)(zod@3.23.8): dependencies: '@noble/curves': 1.6.0 '@noble/hashes': 1.5.0 '@scure/bip32': 1.5.0 '@scure/bip39': 1.4.0 - abitype: 1.0.6(typescript@4.9.5)(zod@3.23.8) + abitype: 1.0.6(typescript@5.7.2)(zod@3.23.8) isows: 1.0.6(ws@8.18.0) - ox: 0.1.2(typescript@4.9.5)(zod@3.23.8) + ox: 0.1.2(typescript@5.7.2)(zod@3.23.8) webauthn-p256: 0.0.10 ws: 8.18.0 optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - bufferutil - utf-8-validate - zod - vlq@1.0.1: {} - vm-browserify@1.1.2: {} void-elements@3.1.0: {} @@ -22400,18 +21280,18 @@ snapshots: dependencies: xml-name-validator: 3.0.0 - wagmi@1.4.13(@types/react@17.0.83)(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)(typescript@4.9.5)(viem@2.21.49(typescript@4.9.5)(zod@3.23.8))(zod@3.23.8): + wagmi@1.4.13(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2)(viem@2.21.50(typescript@5.7.2)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/query-sync-storage-persister': 4.36.1 - '@tanstack/react-query': 4.36.1(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2) - '@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1(react-dom@17.0.2(react@17.0.2))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@17.0.83)(react@17.0.2))(react@17.0.2)) - '@wagmi/core': 1.4.13(@types/react@17.0.83)(react@17.0.2)(typescript@4.9.5)(viem@2.21.49(typescript@4.9.5)(zod@3.23.8))(zod@3.23.8) - abitype: 0.8.7(typescript@4.9.5)(zod@3.23.8) - react: 17.0.2 - use-sync-external-store: 1.2.2(react@17.0.2) - viem: 2.21.49(typescript@4.9.5)(zod@3.23.8) + '@tanstack/react-query': 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-query-persist-client': 4.36.1(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@wagmi/core': 1.4.13(@types/react@18.3.12)(react@18.3.1)(typescript@5.7.2)(viem@2.21.50(typescript@5.7.2)(zod@3.23.8))(zod@3.23.8) + abitype: 0.8.7(typescript@5.7.2)(zod@3.23.8) + react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) + viem: 2.21.50(typescript@5.7.2)(zod@3.23.8) optionalDependencies: - typescript: 4.9.5 + typescript: 5.7.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -22474,9 +21354,9 @@ snapshots: dependencies: web3-types: 1.9.0 - web3-eth-abi@4.4.0(typescript@4.9.5)(zod@3.23.8): + web3-eth-abi@4.4.0(typescript@5.7.2)(zod@3.23.8): dependencies: - abitype: 0.7.1(typescript@4.9.5)(zod@3.23.8) + abitype: 0.7.1(typescript@5.7.2)(zod@3.23.8) web3-errors: 1.3.0 web3-types: 1.9.0 web3-utils: 4.3.2 @@ -22495,13 +21375,13 @@ snapshots: web3-utils: 4.3.2 web3-validator: 2.0.6 - web3-eth-contract@4.7.1(typescript@4.9.5)(zod@3.23.8): + web3-eth-contract@4.7.1(typescript@5.7.2)(zod@3.23.8): dependencies: '@ethereumjs/rlp': 5.0.2 web3-core: 4.7.0 web3-errors: 1.3.0 - web3-eth: 4.11.0(typescript@4.9.5)(zod@3.23.8) - web3-eth-abi: 4.4.0(typescript@4.9.5)(zod@3.23.8) + web3-eth: 4.11.0(typescript@5.7.2)(zod@3.23.8) + web3-eth-abi: 4.4.0(typescript@5.7.2)(zod@3.23.8) web3-types: 1.9.0 web3-utils: 4.3.2 web3-validator: 2.0.6 @@ -22512,13 +21392,13 @@ snapshots: - utf-8-validate - zod - web3-eth-ens@4.4.0(typescript@4.9.5)(zod@3.23.8): + web3-eth-ens@4.4.0(typescript@5.7.2)(zod@3.23.8): dependencies: '@adraffy/ens-normalize': 1.11.0 web3-core: 4.7.0 web3-errors: 1.3.0 - web3-eth: 4.11.0(typescript@4.9.5)(zod@3.23.8) - web3-eth-contract: 4.7.1(typescript@4.9.5)(zod@3.23.8) + web3-eth: 4.11.0(typescript@5.7.2)(zod@3.23.8) + web3-eth-contract: 4.7.1(typescript@5.7.2)(zod@3.23.8) web3-net: 4.1.0 web3-types: 1.9.0 web3-utils: 4.3.2 @@ -22537,10 +21417,10 @@ snapshots: web3-utils: 4.3.2 web3-validator: 2.0.6 - web3-eth-personal@4.1.0(typescript@4.9.5)(zod@3.23.8): + web3-eth-personal@4.1.0(typescript@5.7.2)(zod@3.23.8): dependencies: web3-core: 4.7.0 - web3-eth: 4.11.0(typescript@4.9.5)(zod@3.23.8) + web3-eth: 4.11.0(typescript@5.7.2)(zod@3.23.8) web3-rpc-methods: 1.3.0 web3-types: 1.9.0 web3-utils: 4.3.2 @@ -22552,12 +21432,12 @@ snapshots: - utf-8-validate - zod - web3-eth@4.11.0(typescript@4.9.5)(zod@3.23.8): + web3-eth@4.11.0(typescript@5.7.2)(zod@3.23.8): dependencies: setimmediate: 1.0.5 web3-core: 4.7.0 web3-errors: 1.3.0 - web3-eth-abi: 4.4.0(typescript@4.9.5)(zod@3.23.8) + web3-eth-abi: 4.4.0(typescript@5.7.2)(zod@3.23.8) web3-eth-accounts: 4.3.0 web3-net: 4.1.0 web3-providers-ws: 4.0.8 @@ -22663,17 +21543,17 @@ snapshots: web3-types: 1.9.0 zod: 3.23.8 - web3@4.15.0(typescript@4.9.5)(zod@3.23.8): + web3@4.15.0(typescript@5.7.2)(zod@3.23.8): dependencies: web3-core: 4.7.0 web3-errors: 1.3.0 - web3-eth: 4.11.0(typescript@4.9.5)(zod@3.23.8) - web3-eth-abi: 4.4.0(typescript@4.9.5)(zod@3.23.8) + web3-eth: 4.11.0(typescript@5.7.2)(zod@3.23.8) + web3-eth-abi: 4.4.0(typescript@5.7.2)(zod@3.23.8) web3-eth-accounts: 4.3.0 - web3-eth-contract: 4.7.1(typescript@4.9.5)(zod@3.23.8) - web3-eth-ens: 4.4.0(typescript@4.9.5)(zod@3.23.8) + web3-eth-contract: 4.7.1(typescript@5.7.2)(zod@3.23.8) + web3-eth-ens: 4.4.0(typescript@5.7.2)(zod@3.23.8) web3-eth-iban: 4.0.7 - web3-eth-personal: 4.1.0(typescript@4.9.5)(zod@3.23.8) + web3-eth-personal: 4.1.0(typescript@5.7.2)(zod@3.23.8) web3-net: 4.1.0 web3-providers-http: 4.2.0 web3-providers-ws: 4.0.8 @@ -22849,8 +21729,6 @@ snapshots: dependencies: iconv-lite: 0.4.24 - whatwg-fetch@3.6.20: {} - whatwg-mimetype@2.3.0: {} whatwg-url@5.0.0: @@ -22872,13 +21750,14 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 - which-builtin-type@1.1.4: + which-builtin-type@1.2.0: dependencies: + call-bind: 1.0.7 function.prototype.name: 1.1.6 has-tostringtag: 1.0.2 is-async-function: 2.0.0 is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 + is-finalizationregistry: 1.1.0 is-generator-function: 1.0.10 is-regex: 1.1.4 is-weakref: 1.0.2 @@ -22912,6 +21791,10 @@ snapshots: dependencies: isexe: 2.0.0 + widest-line@2.0.1: + dependencies: + string-width: 2.1.1 + wildcard@2.0.1: {} word-wrap@1.2.5: {} @@ -22955,25 +21838,20 @@ snapshots: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 - write-file-atomic@4.0.2: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - ws@6.2.3: dependencies: async-limiter: 1.0.1 ws@7.5.10: {} - ws@7.5.3: {} - ws@8.13.0: {} ws@8.17.1: {} ws@8.18.0: {} + xdg-basedir@3.0.0: {} + xml-name-validator@3.0.0: {} xml2js@0.4.23: @@ -22991,6 +21869,8 @@ snapshots: y18n@5.0.8: {} + yallist@2.1.2: {} + yallist@3.1.1: {} yallist@4.0.0: {} @@ -23064,9 +21944,15 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yocto-queue@0.1.0: {} + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yn@3.1.1: + optional: true - zdog@1.1.3: {} + yocto-queue@0.1.0: {} zip-dir@2.0.0: dependencies: @@ -23075,16 +21961,12 @@ snapshots: zod@3.23.8: {} - zustand@3.7.2(react@17.0.2): - optionalDependencies: - react: 17.0.2 - - zustand@4.5.5(@types/react@17.0.83)(react@17.0.2): + zustand@4.5.5(@types/react@18.3.12)(react@18.3.1): dependencies: - use-sync-external-store: 1.2.2(react@17.0.2) + use-sync-external-store: 1.2.2(react@18.3.1) optionalDependencies: - '@types/react': 17.0.83 - react: 17.0.2 + '@types/react': 18.3.12 + react: 18.3.1 zwitch@2.0.4: {} diff --git a/src/background/controller/base.ts b/src/background/controller/base.ts index 5834b5e6..5ebf8374 100644 --- a/src/background/controller/base.ts +++ b/src/background/controller/base.ts @@ -1,6 +1,7 @@ import cloneDeep from 'lodash/cloneDeep'; + import { preferenceService, keyringService } from 'background/service'; -import { Account } from 'background/service/preference'; +import { type Account } from 'background/service/preference'; class BaseController { getCurrentAccount = async () => { diff --git a/src/background/controller/provider/controller.ts b/src/background/controller/provider/controller.ts index 85ffa992..84b8de67 100644 --- a/src/background/controller/provider/controller.ts +++ b/src/background/controller/provider/controller.ts @@ -1,29 +1,29 @@ +import { TypedDataUtils, SignTypedDataVersion, normalize } from '@metamask/eth-sig-util'; +import * as fcl from '@onflow/fcl'; +import BigNumber from 'bignumber.js'; import { ethErrors } from 'eth-rpc-errors'; +import { isHexString, intToHex } from 'ethereumjs-util'; +import { ethers } from 'ethers'; +import RLP from 'rlp'; +import Web3 from 'web3'; +import { stringToHex } from 'web3-utils'; -// import RpcCache from 'background/utils/rpcCache'; +import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { permissionService, - preferenceService, sessionService, signTextHistoryService, keyringService, notificationService, } from 'background/service'; -import Wallet from '../wallet'; -import BaseController from '../base'; import { EVM_ENDPOINT } from 'consts'; -import { stringToHex } from 'web3-utils'; -import { normalize as normalizeAddress } from 'eth-sig-util'; -import { ethers } from 'ethers'; -import { isHexString, intToHex } from 'ethereumjs-util'; -import BigNumber from 'bignumber.js'; -import RLP from 'rlp'; -import Web3 from 'web3'; -import { signWithKey } from '@/ui/utils/modules/passkey.js'; -import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/ui/utils/address'; + import { storage } from '../../webapi'; -import { TypedDataUtils, SignTypedDataVersion } from '@metamask/eth-sig-util'; -import * as fcl from '@onflow/fcl'; +import BaseController from '../base'; +import Wallet from '../wallet'; + +// eslint-disable-next-line import/order,no-restricted-imports +import { signWithKey } from '@/ui/utils/modules/passkey.js'; interface Web3WalletPermission { // The name of the method corresponding to the permission @@ -40,26 +40,6 @@ interface COAOwnershipProof { signatures: Uint8Array[]; } -const v1SignTypedDataVlidation = ({ - data: { - params: [_, from], - }, -}) => { - const currentAddress = preferenceService.getCurrentAccount()?.address.toLowerCase(); - if (from.toLowerCase() !== currentAddress) - throw ethErrors.rpc.invalidParams('from should be same as current address'); -}; - -const signTypedDataVlidation = ({ - data: { - params: [from, _], - }, -}) => { - const currentAddress = preferenceService.getCurrentAccount()?.address.toLowerCase(); - if (from.toLowerCase() !== currentAddress) - throw ethErrors.rpc.invalidParams('from should be same as current address'); -}; - function removeHexPrefix(hexString: string): string { return hexString.startsWith('0x') ? hexString.substring(2) : hexString; } @@ -91,6 +71,7 @@ function createAndEncodeCOAOwnershipProof( return encodedData; // Convert the encoded data to a hexadecimal string for easy display or transmission } +// Should not be in controller async function signMessage(msgParams, opts = {}) { const web3 = new Web3(); const textData = msgParams.data; @@ -115,7 +96,6 @@ async function signMessage(msgParams, opts = {}) { const hashAlgo = await storage.get('hashAlgo'); const signAlgo = await storage.get('signAlgo'); const keyindex = await storage.get('keyIndex'); - console.log('keyindex ', [BigInt(keyindex)], account); // const wallet = new ethers.Wallet(privateKey); const signature = await signWithKey(signableData, signAlgo, hashAlgo, privateKey); @@ -409,6 +389,7 @@ class ProviderController extends BaseController { } }; + // Should not be in controller personalSign = async ({ data, approvalRes, session }) => { if (!data.params) return; const [string, from] = data.params; @@ -424,8 +405,7 @@ class ProviderController extends BaseController { }; private _checkAddress = async (address) => { - // eslint-disable-next-line prefer-const - return normalizeAddress(address).toLowerCase(); + return normalize(address).toLowerCase(); }; ethChainId = async ({ session }) => { diff --git a/src/background/controller/provider/index.ts b/src/background/controller/provider/index.ts index 79fd14a2..3f5eac8c 100644 --- a/src/background/controller/provider/index.ts +++ b/src/background/controller/provider/index.ts @@ -1,9 +1,10 @@ import { ethErrors } from 'eth-rpc-errors'; -import { tab } from 'background/webapi'; + import { sessionService, keyringService, userWalletService } from 'background/service'; +import { tab } from 'background/webapi'; -import rpcFlow from './rpcFlow'; import internalMethod from './internalMethod'; +import rpcFlow from './rpcFlow'; tab.on('tabRemove', (id) => { sessionService.deleteSession(id); diff --git a/src/background/controller/provider/rpcFlow.ts b/src/background/controller/provider/rpcFlow.ts index 6b594ed8..0c553e95 100644 --- a/src/background/controller/provider/rpcFlow.ts +++ b/src/background/controller/provider/rpcFlow.ts @@ -1,4 +1,7 @@ import { ethErrors } from 'eth-rpc-errors'; + +import eventBus from '@/eventBus'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { keyringService, notificationService, @@ -7,10 +10,10 @@ import { } from 'background/service'; import { PromiseFlow, underline2Camelcase } from 'background/utils'; import { EVENTS } from 'consts'; -import providerController from './controller'; -import eventBus from '@/eventBus'; + import Wallet from '../wallet'; -import { isValidEthereumAddress } from '@/ui/utils/address'; + +import providerController from './controller'; const isSignApproval = (type: string) => { const SIGN_APPROVALS = ['SignText', 'SignTypedData', 'SignTx', 'EthConfirm']; diff --git a/src/background/controller/serviceDefinition.ts b/src/background/controller/serviceDefinition.ts index eb06f095..88ff224d 100644 --- a/src/background/controller/serviceDefinition.ts +++ b/src/background/controller/serviceDefinition.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck // import { walletController } from './index'; diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index 3210671b..354d9a06 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -1,15 +1,20 @@ /* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { getAuth } from '@firebase/auth'; import * as fcl from '@onflow/fcl'; import * as t from '@onflow/types'; import BN from 'bignumber.js'; +import * as bip39 from 'bip39'; import { ethErrors } from 'eth-rpc-errors'; import * as ethUtil from 'ethereumjs-util'; import { getApp } from 'firebase/app'; +import { getAuth } from 'firebase/auth'; import web3, { TransactionError } from 'web3'; import eventBus from '@/eventBus'; +import { isValidEthereumAddress, withPrefix } from '@/shared/utils/address'; +import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; +// eslint-disable-next-line import/order,no-restricted-imports +import { findAddressWithNetwork } from '@/ui/utils/modules/findAddressWithPK'; import { keyringService, preferenceService, @@ -30,6 +35,7 @@ import { stakingService, proxyService, newsService, + mixpanelTrack, } from 'background/service'; import i18n from 'background/service/i18n'; import { type DisplayedKeryring, KEYRING_CLASS } from 'background/service/keyring'; @@ -40,14 +46,10 @@ import fetchConfig from 'background/utils/remoteConfig'; import { notification, storage } from 'background/webapi'; import { openIndexPage } from 'background/webapi/tab'; import { INTERNAL_REQUEST_ORIGIN, EVENTS, KEYRING_TYPE } from 'consts'; -import placeholder from 'ui/FRWAssets/image/placeholder.png'; -import { getHashAlgo, getSignAlgo, getStoragedAccount } from 'ui/utils'; -import { isValidEthereumAddress, withPrefix } from 'ui/utils/address'; -import { openInternalPageInTab } from 'ui/utils/webapi'; -import { pk2PubKey, seed2PubKey, formPubKey } from '../../ui/utils/modules/passkey'; import { fclTestnetConfig, fclMainnetConfig } from '../fclConfig'; -import type { CoinItem } from '../service/coinList'; +import placeholder from '../images/placeholder.png'; +import { type CoinItem } from '../service/coinList'; import DisplayKeyring from '../service/keyring/display'; import type { NFTData, NFTModel, StorageInfo, WalletResponse } from '../service/networkModel'; import type { ConnectedSite } from '../service/permission'; @@ -55,10 +57,14 @@ import type { Account } from '../service/preference'; import { StorageEvaluator } from '../service/storage-evaluator'; import type { UserInfoStore } from '../service/user'; import defaultConfig from '../utils/defaultConfig.json'; +import { getStoragedAccount } from '../utils/getStoragedAccount'; import BaseController from './base'; import provider from './provider'; +// eslint-disable-next-line import/order,no-restricted-imports +import { pk2PubKey, seed2PubKey, formPubKey } from '@/ui/utils/modules/passkey.js'; + interface Keyring { type: string; getAccounts(): Promise; @@ -88,7 +94,10 @@ export class WalletController extends BaseController { } /* wallet */ - boot = (password) => keyringService.boot(password); + boot = async (password) => { + const result = await keyringService.boot(password); + return result; + }; isBooted = () => keyringService.isBooted(); loadMemStore = () => keyringService.loadMemStore(); verifyPassword = (password: string) => keyringService.verifyPassword(password); @@ -185,9 +194,6 @@ export class WalletController extends BaseController { await passwordService.setPassword(password); sessionService.broadcastEvent('unlock'); - // if (!alianNameInited && Object.values(alianNames).length === 0) { - // this.initAlianNames(); - // } }; switchUnlock = async (password: string) => { @@ -276,7 +282,7 @@ export class WalletController extends BaseController { // lockadd here lockAdd = async () => { - const switchingTo = process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet'; + const switchingTo = 'mainnet'; const password = keyringService.getPassword(); await storage.set('tempPassword', password); @@ -284,13 +290,13 @@ export class WalletController extends BaseController { await passwordService.clear(); sessionService.broadcastEvent('accountsChanged', []); sessionService.broadcastEvent('lock'); - openInternalPageInTab('addwelcome', true); + openIndexPage('addwelcome'); await this.switchNetwork(switchingTo); }; // lockadd here resetPwd = async () => { - const switchingTo = process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet'; + const switchingTo = 'mainnet'; await storage.clear(); await keyringService.resetKeyRing(); @@ -298,13 +304,13 @@ export class WalletController extends BaseController { await passwordService.clear(); sessionService.broadcastEvent('accountsChanged', []); sessionService.broadcastEvent('lock'); - openInternalPageInTab('reset', true); + openIndexPage('reset'); await this.switchNetwork(switchingTo); }; // lockadd here restoreWallet = async () => { - const switchingTo = process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet'; + const switchingTo = 'mainnet'; const password = keyringService.getPassword(); await storage.set('tempPassword', password); @@ -313,7 +319,7 @@ export class WalletController extends BaseController { sessionService.broadcastEvent('accountsChanged', []); sessionService.broadcastEvent('lock'); - openInternalPageInTab('restore', true); + openIndexPage('restore'); await this.switchNetwork(switchingTo); }; @@ -694,7 +700,30 @@ export class WalletController extends BaseController { signTransaction = async (type: string, from: string, data: any, options?: any) => { const keyring = await keyringService.getKeyringForAccount(from, type); - return keyringService.signTransaction(keyring, data, options); + const res = await keyringService.signTransaction(keyring, data, options); + + /* + cadence_transaction_signed: { + cadence: string; // SHA256 Hashed Cadence that was signed. + tx_id: string; // String of the transaction ID. + authorizers: string[]; // Comma separated list of authorizer account address in the transaction + proposer: string; // Address of the transactions proposer. + payer: string; // Payer of the transaction. + success: boolean; // Boolean of if the transaction was sent successful or not. true/false + }; + evm_transaction_signed: { + success: boolean; // Boolean of if the transaction was sent successful or not. true/false + flow_address: string; // Address of the account that signed the transaction + evm_address: string; // EVM Address of the account that signed the transaction + tx_id: string; // transaction id + }; + mixpanelTrack.track('transaction_signed', { + address: from, + type, + ...res, + }); + */ + return res; }; requestKeyring = (type, methodName, keyringId: number | null, ...params) => { @@ -871,16 +900,16 @@ export class WalletController extends BaseController { }; checkUserChildAccount = async () => { - const cacheKey = 'checkUserChildAccount'; + const network = await this.getNetwork(); + const address = await userWalletService.getMainWallet(network); + const cacheKey = `checkUserChildAccount${address}`; const ttl = 5 * 60 * 1000; // 5 minutes in milliseconds // Try to get the cached result let meta = await storage.getExpiry(cacheKey); if (!meta) { try { - const network = await this.getNetwork(); let result = {}; - const address = await userWalletService.getMainWallet(network); result = await openapiService.checkChildAccountMeta(address); if (result) { @@ -989,86 +1018,118 @@ export class WalletController extends BaseController { }; //coinList - getCoinList = async (_expiry = 5000): Promise => { - const network = await this.getNetwork(); - const now = new Date(); - const expiry = coinListService.getExpiry(); - let childType = await userWalletService.getActiveWallet(); - childType = childType === 'evm' ? 'evm' : 'coinItem'; - // compare the expiry time of the item with the current time - if (now.getTime() > expiry) { - if (childType === 'evm') { - await this.refreshEvmList(_expiry); - } else { - await this.refreshCoinList(_expiry); + getCoinList = async (_expiry = 60000, currentEnv = ''): Promise => { + try { + const network = await this.getNetwork(); + const now = new Date(); + const expiry = coinListService.getExpiry(); + + // Determine childType: use currentEnv if not empty, otherwise fallback to active wallet type + let childType = currentEnv || (await userWalletService.getActiveWallet()); + childType = childType === 'evm' ? 'evm' : 'coinItem'; + + // Otherwise, fetch from the coinListService + const listCoins = coinListService.listCoins(network, childType); + + // Validate and ensure listCoins is of type CoinItem[] + if ( + !listCoins || + !Array.isArray(listCoins) || + listCoins.length === 0 || + now.getTime() > expiry + ) { + console.log('listCoins is empty or invalid, refreshing...'); + let refreshedList; + if (childType === 'evm') { + refreshedList = await this.refreshEvmList(_expiry); + } else { + refreshedList = await this.refreshCoinList(_expiry); + } + if (refreshedList) { + return refreshedList; + } } + + return listCoins; + } catch (error) { + console.error('Error fetching coin list:', error); + throw new Error('Failed to fetch coin list'); // Re-throw the error with a custom message } - const listCoins = coinListService.listCoins(network, childType); - return listCoins; }; - private tokenPrice = async (tokenSymbol: string, address: string, data, contractName: string) => { + private async getFlowTokenPrice(flowPrice?: string): Promise { + const cachedFlowTokenPrice = await storage.getExpiry('flowTokenPrice'); + if (cachedFlowTokenPrice) { + if (flowPrice) { + cachedFlowTokenPrice.price.last = flowPrice; + } + return cachedFlowTokenPrice; + } + const result = await openapiService.getTokenPrice('flow'); + if (flowPrice) { + result.price.last = flowPrice; + } + await storage.setExpiry('flowTokenPrice', result, 300000); // Cache for 5 minutes + return result; + } + + private async getFixedTokenPrice(symbol: string): Promise { + if (symbol === 'usdc') { + return await openapiService.getUSDCPrice(); + } else if (symbol === 'fusd') { + return Promise.resolve({ + price: { last: '1.0', change: { percentage: '0.0' } }, + }); + } + return null; + } + + private async calculateTokenPrice(token: string, price: string | null): Promise { + if (price) { + return { price: { last: price, change: { percentage: '0.0' } } }; + } else { + return { price: { last: '0.0', change: { percentage: '0.0' } } }; + } + } + + private async tokenPrice( + tokenSymbol: string, + address: string, + data: Record, + contractName: string + ) { const token = tokenSymbol.toLowerCase(); - const key = contractName.toLowerCase() + '' + address.toLowerCase(); + const key = `${contractName.toLowerCase()}${address.toLowerCase()}`; const price = await openapiService.getPricesByKey(key, data); - switch (token) { - case 'flow': { - const flowTokenPrice = await storage.getExpiry('flowTokenPrice'); - if (flowTokenPrice) { - return flowTokenPrice; - } else { - const result = await openapiService.getTokenPrice('flow'); - await storage.setExpiry('flowTokenPrice', result, 300000); // 5 minutes in milliseconds - return result; - } - } - case 'usdc': - return await openapiService.getUSDCPrice(); - case 'fusd': - return Promise.resolve({ - price: { last: '1.0', change: { percentage: '0.0' } }, - }); - default: - if (price) { - return { price: { last: price, change: { percentage: '0.0' } } }; - } else { - return null; - } + if (token === 'flow') { + const flowPrice = price || data['FLOW']; + return this.getFlowTokenPrice(flowPrice); } - }; - private evmtokenPrice = async (tokeninfo, data) => { + const fixedTokenPrice = await this.getFixedTokenPrice(token); + if (fixedTokenPrice) return fixedTokenPrice; + + return this.calculateTokenPrice(token, price); + } + + private async evmtokenPrice(tokeninfo, data) { const token = tokeninfo.symbol.toLowerCase(); const price = await openapiService.getPricesByEvmaddress(tokeninfo.address, data); - switch (token) { - case 'flow': { - const flowTokenPrice = await storage.getExpiry('flowTokenPrice'); - if (flowTokenPrice) { - return flowTokenPrice; - } else { - const result = await openapiService.getTokenPrice('flow'); - await storage.setExpiry('flowTokenPrice', result, 300000); // 5 minutes in milliseconds - return result; - } - } - case 'usdc': - return await openapiService.getUSDCPrice(); - case 'fusd': - return Promise.resolve({ - price: { last: '1.0', change: { percentage: '0.0' } }, - }); - default: - if (price) { - return { price: { last: price, change: { percentage: '0.0' } } }; - } else { - return { price: { last: 0, change: { percentage: '0.0' } } }; - } + + if (token === 'flow') { + const flowPrice = price || data['FLOW']; + return this.getFlowTokenPrice(flowPrice); } - }; + + const fixedTokenPrice = await this.getFixedTokenPrice(token); + if (fixedTokenPrice) return fixedTokenPrice; + + return this.calculateTokenPrice(token, price); + } refreshCoinList = async ( - _expiry = 5000, + _expiry = 60000, { signal } = { signal: new AbortController().signal } ) => { try { @@ -1093,7 +1154,7 @@ export class WalletController extends BaseController { console.error('Error refresh token list balance:', error); throw new Error('Failed to refresh token list balance'); } - const data = await openapiService.getTokenPrices(); + const data = await openapiService.getTokenPrices('pricesMap'); // Map over tokenList to get prices and handle errors individually const pricesPromises = tokenList.map(async (token) => { try { @@ -1144,14 +1205,7 @@ export class WalletController extends BaseController { // Add all coins at once if (signal.aborted) throw new Error('Operation aborted'); coinListService.addCoins(coins, network); - - // const allTokens = await openapiService.getAllTokenInfo(); - // const enabledSymbols = tokenList.map((token) => token.symbol); - // const disableSymbols = allTokens.map((token) => token.symbol).filter((symbol) => !enabledSymbols.includes(symbol)); - // console.log('disableSymbols are these ', disableSymbols, enabledSymbols, coins) - // disableSymbols.forEach((coin) => coinListService.removeCoin(coin, network)); - const coinListResult = coinListService.listCoins(network); - return coinListResult; + return coins; } catch (err) { if (err.message === 'Operation aborted') { console.error('refreshCoinList operation aborted.'); @@ -1195,7 +1249,7 @@ export class WalletController extends BaseController { throw new Error('Failed to fetch token list balance'); } - const data = await openapiService.getTokenPrices(); + const data = await openapiService.getTokenPrices('pricesMap'); // Map over tokenList to get prices and handle errors individually const pricesPromises = tokenList.map(async (token) => { @@ -1279,7 +1333,7 @@ export class WalletController extends BaseController { } }; - refreshEvmList = async (_expiry = 5000) => { + refreshEvmList = async (_expiry = 60000) => { const now = new Date(); const exp = _expiry + now.getTime(); coinListService.setExpiry(exp); @@ -1320,37 +1374,6 @@ export class WalletController extends BaseController { }); }; - // const customToken = (mergedList, evmCustomToken) => { - // return mergedList.map(token => { - // const balanceInfo = evmCustomToken.map(customToken => { - // if (customToken.address.toLowerCase() === token.address.toLowerCase()) { - - // return { - // ...token, - // custom: true - // } - - // } else { - // return { - - // "chainId": 747, - // "address": customToken.address, - // "symbol": customToken.unit, - // "name": customToken.coin, - // "decimals": customToken.decimals, - // "logoURI": "", - // "flowIdentifier": "", - // "tags": [], - // "balance": 0, - // custom: true - - // } - // } - // }); - // return balanceInfo; - // }); - // }; - const customToken = (coins, evmCustomToken) => { const updatedList = [...coins]; @@ -1381,9 +1404,8 @@ export class WalletController extends BaseController { const mergedList = await mergeBalances(tokenList, allBalanceMap, flowBalance); - const data = await openapiService.getTokenEvmPrices(); + const data = await openapiService.getTokenPrices('evmPrice', true); const prices = tokenList.map((token) => this.evmtokenPrice(token, data)); - const allPrice = await Promise.all(prices); const coins: CoinItem[] = mergedList.map((token, index) => { return { @@ -1405,18 +1427,8 @@ export class WalletController extends BaseController { }); const coinWithCustom = await customToken(coins, evmCustomToken); - - coinWithCustom - .sort((a, b) => { - if (b.total === a.total) { - return b.balance - a.balance; - } else { - return b.total - a.total; - } - }) - .map((coin) => coinListService.addCoin(coin, network, 'evm')); - - return coinListService.listCoins(network, 'evm'); + coinWithCustom.map((coin) => coinListService.addCoin(coin, network, 'evm')); + return coinWithCustom; }; reqeustEvmNft = async () => { @@ -1568,21 +1580,75 @@ export class WalletController extends BaseController { //user wallets refreshUserWallets = async () => { const network = await this.getNetwork(); - const active = await userWalletService.getActiveWallet(); - const v2data = await openapiService.userWalletV2(); - const filteredData = v2data.data.wallets.filter((item) => item.blockchain !== null); + const pubKey = await this.getPubKey(); + const address = await findAddressWithNetwork(pubKey, network); + const emoji = await this.getEmoji(); + if (!address) { + throw new Error("Can't find address in chain"); + } + let transformedArray: any[]; + + // Check if the addresses array is empty + if (address.length === 0) { + // Add a placeholder blockchain item + transformedArray = [ + { + id: 0, + name: 'flow', + chain_id: network, + icon: 'placeholder', + color: 'placeholder', + blockchain: [ + { + id: 0, + name: 'Flow', + chain_id: network, + address: '0x00000000', + coins: ['flow'], + icon: '', + }, + ], + }, + ]; + } else { + // Transform the address array into blockchain objects + transformedArray = address.map((item, index) => { + return { + id: 0, + name: emoji[index].name, + chain_id: network, + icon: emoji[index].emoji, + color: emoji[index].bgcolor, + blockchain: [ + { + id: index, + name: emoji[index].name, + chain_id: network, + address: item.address, + coins: ['flow'], + icon: emoji[index].emoji, + color: emoji[index].bgcolor, + }, + ], + }; + }); + } + + console.log('v2data ', transformedArray, address); + const active = await userWalletService.getActiveWallet(); if (!active) { - userInfoService.addUserId(v2data.data.id); - userWalletService.setUserWallets(filteredData, network); + // userInfoService.addUserId(v2data.data.id); + userWalletService.setUserWallets(transformedArray, network); } - return filteredData; + return transformedArray; }; getUserWallets = async (): Promise => { const network = await this.getNetwork(); const wallets = await userWalletService.getUserWallets(network); + console.log('getUserWallets ', wallets); if (!wallets[0]) { await this.refreshUserWallets(); const data = await userWalletService.getUserWallets(network); @@ -1609,11 +1675,11 @@ export class WalletController extends BaseController { return activeWallet; }; - setActiveWallet = async (wallet: any, key: any) => { + setActiveWallet = async (wallet: any, key: any, index = null) => { await userWalletService.setActiveWallet(key); const network = await this.getNetwork(); - await userWalletService.setCurrentWallet(wallet, key, network); + await userWalletService.setCurrentWallet(wallet, key, network, index); }; hasCurrentWallet = async () => { @@ -1623,6 +1689,7 @@ export class WalletController extends BaseController { getCurrentWallet = async () => { const wallet = await userWalletService.getCurrentWallet(); + console.log('getCurrentWallet ', wallet); if (!wallet.address) { const network = await this.getNetwork(); await this.refreshUserWallets(); @@ -1638,7 +1705,8 @@ export class WalletController extends BaseController { }; setEvmAddress = async (address) => { - await userWalletService.setEvmAddress(address); + const emoji = await this.getEmoji(); + await userWalletService.setEvmAddress(address, emoji); }; getEvmAddress = async () => { @@ -1650,10 +1718,10 @@ export class WalletController extends BaseController { getCurrentAddress = async () => { const address = await userWalletService.getCurrentAddress(); if (!address) { - const data = this.refreshUserWallets(); + const data = await this.refreshUserWallets(); return withPrefix(data[0].blockchain[0].address); } else if (address.length < 3) { - const data = this.refreshUserWallets(); + const data = await this.refreshUserWallets(); return withPrefix(data[0].blockchain[0].address); } return withPrefix(address); @@ -1663,10 +1731,10 @@ export class WalletController extends BaseController { const network = await this.getNetwork(); const address = await userWalletService.getMainWallet(network); if (!address) { - const data = this.refreshUserWallets(); + const data = await this.refreshUserWallets(); return withPrefix(data[0].blockchain[0].address); } else if (address.length < 3) { - const data = this.refreshUserWallets(); + const data = await this.refreshUserWallets(); return withPrefix(data[0].blockchain[0].address); } return withPrefix(address); @@ -1681,7 +1749,23 @@ export class WalletController extends BaseController { const script = await getScripts('evm', 'createCoa'); - return await userWalletService.sendTransaction(script, [fcl.arg(formattedAmount, t.UFix64)]); + const txID = await userWalletService.sendTransaction(script, [ + fcl.arg(formattedAmount, t.UFix64), + ]); + + // try to seal it + try { + const result = await fcl.tx(txID).onceSealed(); + console.log('coa creation result ', result); + // Track with success + await this.trackCoaCreation(txID); + } catch (error) { + console.error('Error sealing transaction:', error); + // Track with error + await this.trackCoaCreation(txID, error.message); + } + + return txID; }; createCoaEmpty = async (): Promise => { @@ -1689,7 +1773,29 @@ export class WalletController extends BaseController { const script = await getScripts('evm', 'createCoaEmpty'); - return await userWalletService.sendTransaction(script, []); + const txID = await userWalletService.sendTransaction(script, []); + + // try to seal it + try { + const result = await fcl.tx(txID).onceSealed(); + console.log('coa creation result ', result); + // Track with success + await this.trackCoaCreation(txID); + } catch (error) { + console.error('Error sealing transaction:', error); + // Track with error + await this.trackCoaCreation(txID, error.message); + } + + return txID; + }; + + trackCoaCreation = async (txID: string, errorMessage?: string) => { + mixpanelTrack.track('coa_creation', { + tx_id: txID, + flow_address: (await this.getCurrentAddress()) || '', + error_message: errorMessage, + }); }; transferFlowEvm = async ( @@ -1705,11 +1811,21 @@ export class WalletController extends BaseController { recipientEVMAddressHex = recipientEVMAddressHex.substring(2); } - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(recipientEVMAddressHex, t.String), fcl.arg(formattedAmount, t.UFix64), fcl.arg(gasLimit, t.UInt64), ]); + + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: recipientEVMAddressHex, + amount: parseFloat(formattedAmount), + ft_identifier: 'FLOW', + type: 'evm', + }); + + return txID; }; transferFTToEvm = async ( @@ -1731,7 +1847,7 @@ export class WalletController extends BaseController { const regularArray = Array.from(dataArray); const gasLimit = 30000000; - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(tokenContractAddress, t.Address), fcl.arg(tokenContractName, t.String), fcl.arg(formattedAmount, t.UFix64), @@ -1739,6 +1855,14 @@ export class WalletController extends BaseController { fcl.arg(regularArray, t.Array(t.UInt8)), fcl.arg(gasLimit, t.UInt64), ]); + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: tokenContractAddress, + amount: parseFloat(formattedAmount), + ft_identifier: tokenContractName, + type: 'evm', + }); + return txID; }; transferFTToEvmV2 = async ( @@ -1751,11 +1875,21 @@ export class WalletController extends BaseController { const script = await getScripts('bridge', 'bridgeTokensToEvmAddressV2'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(vaultIdentifier, t.String), fcl.arg(formattedAmount, t.UFix64), fcl.arg(recipient, t.String), ]); + + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: recipient, + amount: parseFloat(formattedAmount), + ft_identifier: vaultIdentifier, + type: 'evm', + }); + + return txID; }; transferFTFromEvm = async ( @@ -1782,11 +1916,21 @@ export class WalletController extends BaseController { console.log('integerAmountStr amount ', integerAmountStr, amount); const script = await getScripts('bridge', 'bridgeTokensFromEvmToFlowV2'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(flowidentifier, t.String), fcl.arg(integerAmountStr, t.UInt256), fcl.arg(receiver, t.Address), ]); + + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: receiver, + amount: parseFloat(integerAmountStr), + ft_identifier: flowidentifier, + type: 'evm', + }); + + return txID; }; withdrawFlowEvm = async (amount = '1.0', address: string): Promise => { @@ -1794,10 +1938,12 @@ export class WalletController extends BaseController { const formattedAmount = parseFloat(amount).toFixed(8); const script = await getScripts('evm', 'withdrawCoa'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(formattedAmount, t.UFix64), fcl.arg(address, t.Address), ]); + + return txID; }; fundFlowEvm = async (amount = '1.0'): Promise => { @@ -1842,16 +1988,26 @@ export class WalletController extends BaseController { } }; - bridgeToEvm = async (flowIndentifier, amount = '1.0'): Promise => { + bridgeToEvm = async (flowIdentifier, amount = '1.0'): Promise => { await this.getNetwork(); const formattedAmount = parseFloat(amount).toFixed(8); const script = await getScripts('bridge', 'bridgeTokensToEvmV2'); - return await userWalletService.sendTransaction(script, [ - fcl.arg(flowIndentifier, t.String), + const txID = await userWalletService.sendTransaction(script, [ + fcl.arg(flowIdentifier, t.String), fcl.arg(formattedAmount, t.UFix64), ]); + + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: await this.getEvmAddress(), + amount: parseFloat(formattedAmount), + ft_identifier: flowIdentifier, + type: 'evm', + }); + + return txID; }; bridgeToFlow = async (flowIdentifier, amount = '1.0', tokenResult): Promise => { @@ -1870,10 +2026,20 @@ export class WalletController extends BaseController { const integerAmountStr = integerAmount.integerValue(BN.ROUND_DOWN).toFixed(); const script = await getScripts('bridge', 'bridgeTokensFromEvmV2'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(flowIdentifier, t.String), fcl.arg(integerAmountStr, t.UInt256), ]); + + mixpanelTrack.track('ft_transfer', { + from_address: await this.getEvmAddress(), + to_address: (await this.getCurrentAddress()) || '', + amount: parseFloat(integerAmountStr), + ft_identifier: flowIdentifier, + type: 'flow', + }); + + return txID; }; queryEvmAddress = async (address: string): Promise => { @@ -1971,6 +2137,14 @@ export class WalletController extends BaseController { fcl.arg(gasLimit, t.UInt64), ]); + mixpanelTrack.track('ft_transfer', { + from_address: await this.getEvmAddress(), + to_address: to, + amount: parseFloat(amount), + ft_identifier: 'FLOW', + type: 'evm', + }); + return result; // const transaction = await fcl.tx(result).onceSealed(); // console.log('transaction ', transaction); @@ -2030,6 +2204,14 @@ export class WalletController extends BaseController { fcl.arg(gasLimit, t.UInt64), ]); + mixpanelTrack.track('ft_transfer', { + from_address: await this.getEvmAddress(), + to_address: to, + amount: parseFloat(amount), + ft_identifier: 'FLOW', + type: 'evm', + }); + console.log('result ', result); const res = await fcl.tx(result).onceSealed(); const transactionExecutedEvent = res.events.find((event) => @@ -2068,8 +2250,24 @@ export class WalletController extends BaseController { }; getFlowBalance = async (address) => { - const account = await fcl.send([fcl.getAccount(address!)]).then(fcl.decode); - return account.balance; + const cacheKey = `checkFlowBalance${address}`; + let balance = await storage.getExpiry(cacheKey); + const ttl = 1 * 60 * 1000; + if (!balance) { + try { + const account = await fcl.send([fcl.getAccount(address!)]).then(fcl.decode); + balance = account.balance; + if (balance) { + // Store the result in the cache with an expiry + await storage.setExpiry(cacheKey, balance, ttl); + } + } catch (error) { + console.error('Error occurred:', error); + return {}; // Return an empty object in case of an error + } + } + + return balance; }; getNonce = async (hexEncodedAddress: string): Promise => { @@ -2124,7 +2322,7 @@ export class WalletController extends BaseController { await this.getNetwork(); const script = await getScripts('ft', 'transferTokens'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contractName) .replaceAll('', token.path.balance) @@ -2133,6 +2331,16 @@ export class WalletController extends BaseController { .replaceAll('', token.address), [fcl.arg(amount, t.UFix64), fcl.arg(address, t.Address)] ); + + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: address, + amount: parseFloat(amount), + ft_identifier: token.contractName, + type: 'flow', + }); + + return txID; }; // TODO: Replace with generic token @@ -2149,7 +2357,7 @@ export class WalletController extends BaseController { } await this.getNetwork(); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contractName) .replaceAll('', token.path.balance) @@ -2158,6 +2366,16 @@ export class WalletController extends BaseController { .replaceAll('', token.address), [fcl.arg(amount, t.UFix64), fcl.arg(address, t.Address)] ); + + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: address, + amount: parseFloat(amount), + ft_identifier: token.contractName, + type: 'flow', + }); + + return txID; }; revokeKey = async (index: string): Promise => { @@ -2320,7 +2538,7 @@ export class WalletController extends BaseController { } const script = await getScripts('hybridCustody', 'transferChildFT'); - return await userWalletService.sendTransaction( + const result = await userWalletService.sendTransaction( script .replaceAll('', token.contractName) .replaceAll('', token.path.balance) @@ -2329,6 +2547,14 @@ export class WalletController extends BaseController { .replaceAll('', token.address), [fcl.arg(childAddress, t.Address), fcl.arg(path, t.String), fcl.arg(amount, t.UFix64)] ); + mixpanelTrack.track('ft_transfer', { + from_address: (await this.getCurrentAddress()) || '', + to_address: childAddress, + amount: parseFloat(amount), + ft_identifier: token.contractName, + type: 'flow', + }); + return result; }; sendFTfromChild = async ( @@ -2345,7 +2571,7 @@ export class WalletController extends BaseController { const script = await getScripts('hybridCustody', 'sendChildFT'); - return await userWalletService.sendTransaction( + const result = await userWalletService.sendTransaction( script .replaceAll('', token.contractName) .replaceAll('', token.path.balance) @@ -2359,6 +2585,14 @@ export class WalletController extends BaseController { fcl.arg(amount, t.UFix64), ] ); + mixpanelTrack.track('ft_transfer', { + from_address: childAddress, + to_address: receiver, + amount: parseFloat(amount), + ft_identifier: token.contractName, + type: 'flow', + }); + return result; }; moveNFTfromChild = async ( @@ -2371,7 +2605,7 @@ export class WalletController extends BaseController { const script = await getScripts('hybridCustody', 'transferChildNFT'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2384,6 +2618,16 @@ export class WalletController extends BaseController { fcl.arg(ids, t.UInt64), ] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: nftContractAddress, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: token.contractName, + from_type: 'flow', + to_type: 'flow', + isMove: true, + }); + return txID; }; sendNFTfromChild = async ( @@ -2395,7 +2639,7 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('hybridCustody', 'sendChildNFT'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2409,6 +2653,16 @@ export class WalletController extends BaseController { fcl.arg(ids, t.UInt64), ] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: linkedAddress, + to_address: receiverAddress, + nft_identifier: token.contractName, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; sendNFTtoChild = async ( @@ -2418,7 +2672,7 @@ export class WalletController extends BaseController { token ): Promise => { const script = await getScripts('hybridCustody', 'transferNFTToChild'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2427,6 +2681,16 @@ export class WalletController extends BaseController { .replaceAll('', token.path.public_path), [fcl.arg(linkedAddress, t.Address), fcl.arg(path, t.String), fcl.arg(ids, t.UInt64)] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: linkedAddress, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: token.contractName, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; getChildAccountAllowTypes = async (parent: string, child: string) => { @@ -2451,19 +2715,39 @@ export class WalletController extends BaseController { batchBridgeNftToEvm = async (flowIdentifier: string, ids: Array): Promise => { const script = await getScripts('bridge', 'batchBridgeNFTToEvmV2'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(flowIdentifier, t.String), fcl.arg(ids, t.Array(t.UInt64)), ]); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: flowIdentifier, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: flowIdentifier, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; batchBridgeNftFromEvm = async (flowIdentifier: string, ids: Array): Promise => { const script = await getScripts('bridge', 'batchBridgeNFTFromEvmV2'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(flowIdentifier, t.String), fcl.arg(ids, t.Array(t.UInt256)), ]); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: flowIdentifier, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: flowIdentifier, + from_type: 'flow', + to_type: 'evm', + isMove: false, + }); + return txID; }; batchTransferNFTToChild = async ( @@ -2474,7 +2758,7 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('hybridCustody', 'batchTransferNFTToChild'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2487,6 +2771,16 @@ export class WalletController extends BaseController { fcl.arg(ids, t.Array(t.UInt64)), ] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: identifier, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; batchTransferChildNft = async ( @@ -2496,7 +2790,7 @@ export class WalletController extends BaseController { token ): Promise => { const script = await getScripts('hybridCustody', 'batchTransferChildNFT'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2509,6 +2803,16 @@ export class WalletController extends BaseController { fcl.arg(ids, t.Array(t.UInt64)), ] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: identifier, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; sendChildNFTToChild = async ( @@ -2520,7 +2824,7 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('hybridCustody', 'batchSendChildNFTToChild'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2534,6 +2838,16 @@ export class WalletController extends BaseController { fcl.arg(ids, t.Array(t.UInt64)), ] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: identifier, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; batchBridgeChildNFTToEvm = async ( @@ -2544,7 +2858,7 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('hybridCustody', 'batchBridgeChildNFTToEvm'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2557,6 +2871,16 @@ export class WalletController extends BaseController { fcl.arg(ids, t.Array(t.UInt64)), ] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: identifier, + from_type: 'flow', + to_type: 'evm', + isMove: false, + }); + return txID; }; batchBridgeChildNFTFromEvm = async ( @@ -2566,11 +2890,21 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('hybridCustody', 'batchBridgeChildNFTFromEvm'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(identifier, t.String), fcl.arg(childAddr, t.Address), fcl.arg(ids, t.Array(t.UInt256)), ]); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: identifier, + from_type: 'flow', + to_type: 'evm', + isMove: false, + }); + return txID; }; bridgeChildFTToEvm = async ( @@ -2581,7 +2915,7 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('hybridCustody', 'bridgeChildFTToEvm'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2590,17 +2924,26 @@ export class WalletController extends BaseController { .replaceAll('', token.path.public_path), [fcl.arg(identifier, t.String), fcl.arg(childAddr, t.Address), fcl.arg(amount, t.UFix64)] ); + mixpanelTrack.track('ft_transfer', { + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + ft_identifier: identifier, + type: 'evm', + amount: amount, + }); + return txID; }; bridgeChildFTFromEvm = async ( childAddr: string, vaultIdentifier: string, ids: Array, - token + token, + amount: number ): Promise => { const script = await getScripts('hybridCustody', 'bridgeChildFTFromEvm'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2611,8 +2954,17 @@ export class WalletController extends BaseController { fcl.arg(vaultIdentifier, t.String), fcl.arg(childAddr, t.Address), fcl.arg(ids, t.Array(t.UInt256)), + fcl.arg(amount, t.UFix64), ] ); + mixpanelTrack.track('ft_transfer', { + from_address: childAddr, + to_address: (await this.getCurrentAddress()) || '', + ft_identifier: vaultIdentifier, + type: 'evm', + amount: amount, + }); + return txID; }; bridgeNftToEvmAddress = async ( @@ -2637,7 +2989,7 @@ export class WalletController extends BaseController { contractEVMAddress = contractEVMAddress.substring(2); } - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(nftContractAddress, t.Address), fcl.arg(nftContractName, t.String), fcl.arg(ids, t.UInt64), @@ -2645,6 +2997,16 @@ export class WalletController extends BaseController { fcl.arg(regularArray, t.Array(t.UInt8)), fcl.arg(gasLimit, t.UInt64), ]); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: nftContractAddress, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: nftContractName, + from_type: 'evm', + to_type: 'evm', + isMove: false, + }); + return txID; }; bridgeNftFromEvmToFlow = async ( @@ -2654,11 +3016,21 @@ export class WalletController extends BaseController { ): Promise => { const script = await getScripts('bridge', 'bridgeNFTFromEvmToFlowV2'); - return await userWalletService.sendTransaction(script, [ + const txID = await userWalletService.sendTransaction(script, [ fcl.arg(flowIdentifier, t.String), fcl.arg(ids, t.UInt256), fcl.arg(receiver, t.Address), ]); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: flowIdentifier, + to_address: (await this.getCurrentAddress()) || '', + nft_identifier: flowIdentifier, + from_type: 'flow', + to_type: 'evm', + isMove: false, + }); + return txID; }; getAssociatedFlowIdentifier = async (address: string): Promise => { @@ -2674,7 +3046,7 @@ export class WalletController extends BaseController { await this.getNetwork(); const script = await getScripts('collection', 'sendNFT'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2682,13 +3054,23 @@ export class WalletController extends BaseController { .replaceAll('', token.path.public_path), [fcl.arg(recipient, t.Address), fcl.arg(parseInt(id), t.UInt64)] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: (await this.getCurrentAddress()) || '', + to_address: recipient, + nft_identifier: token.contract_name, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; sendNBANFT = async (recipient: string, id: any, token: NFTModel): Promise => { await this.getNetwork(); const script = await getScripts('collection', 'sendNbaNFT'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2696,12 +3078,22 @@ export class WalletController extends BaseController { .replaceAll('', token.path.public_path), [fcl.arg(recipient, t.Address), fcl.arg(parseInt(id), t.UInt64)] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: (await this.getCurrentAddress()) || '', + to_address: recipient, + nft_identifier: token.contract_name, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; sendInboxNFT = async (recipient: string, id: any, token: any): Promise => { const script = await getScripts('domain', 'sendInboxNFT'); - return await userWalletService.sendTransaction( + const txID = await userWalletService.sendTransaction( script .replaceAll('', token.contract_name) .replaceAll('', token.address) @@ -2709,6 +3101,16 @@ export class WalletController extends BaseController { .replaceAll('', token.path.public_path), [fcl.arg(recipient, t.Address), fcl.arg(parseInt(id), t.UInt64)] ); + mixpanelTrack.track('nft_transfer', { + tx_id: txID, + from_address: (await this.getCurrentAddress()) || '', + to_address: recipient, + nft_identifier: token.contract_name, + from_type: 'flow', + to_type: 'flow', + isMove: false, + }); + return txID; }; // SwapTokensForExactTokens @@ -2929,7 +3331,6 @@ export class WalletController extends BaseController { refreshAll = async () => { await this.refreshUserWallets(); this.clearNFT(); - this.clearChildAccount(); this.refreshAddressBook(); this.refreshEvmWallets(); await this.getCadenceScripts(); @@ -2952,11 +3353,7 @@ export class WalletController extends BaseController { getEvmEnabled = async (): Promise => { const address = await this.getEvmAddress(); - if (isValidEthereumAddress(address)) { - return true; - } else { - return false; - } + return !!address && isValidEthereumAddress(address); }; refreshEvmWallets = () => { @@ -3055,6 +3452,7 @@ export class WalletController extends BaseController { } const address = (await this.getCurrentAddress()) || '0x'; const network = await this.getNetwork(); + try { chrome.storage.session.set({ transactionPending: { txId, network, date: new Date() }, @@ -3070,10 +3468,21 @@ export class WalletController extends BaseController { // This will throw an error if there is an error with the transaction await fcl.tx(txId).onceSealed(); - // Only send a notification if the transaction is successful - if (sendNotification) { - const baseURL = this.getFlowscanUrl(); - notification.create(`${baseURL}/transaction/${txId}`, title, body, icon); + // Track the transaction result + mixpanelTrack.track('transaction_result', { + tx_id: txId, + is_successful: true, + }); + + try { + // Send a notification to the user only on success + if (sendNotification) { + const baseURL = this.getFlowscanUrl(); + notification.create(`${baseURL}/transaction/${txId}`, title, body, icon); + } + } catch (err: unknown) { + // We don't want to throw an error if the notification fails + console.error('listenTransaction notification error ', err); } } catch (err: unknown) { // An error has occurred while listening to the transaction @@ -3095,12 +3504,20 @@ export class WalletController extends BaseController { const match = errorMessage.match(ERROR_CODE_REGEX); errorCode = match ? parseInt(match[1], 10) : undefined; } - console.log({ + + console.warn({ msg: 'transactionError', errorMessage, errorCode, }); + // Track the transaction error + mixpanelTrack.track('transaction_result', { + tx_id: txId, + is_successful: false, + error_message: errorMessage, + }); + // Tell the UI that there was an error chrome.runtime.sendMessage({ msg: 'transactionError', @@ -3405,9 +3822,24 @@ export class WalletController extends BaseController { }; uploadMnemonicToGoogleDrive = async (mnemonic, username, password) => { + const isValidMnemonic = bip39.validateMnemonic(mnemonic); + if (!isValidMnemonic) { + throw new Error('Invalid mnemonic'); + } const app = getApp(process.env.NODE_ENV!); const user = await getAuth(app).currentUser; - return googleDriveService.uploadMnemonicToGoogleDrive(mnemonic, username, user!.uid, password); + try { + await googleDriveService.uploadMnemonicToGoogleDrive(mnemonic, username, user!.uid, password); + mixpanelTrack.track('multi_backup_created', { + address: (await this.getCurrentAddress()) || '', + providers: ['google_drive'], + }); + } catch { + mixpanelTrack.track('multi_backup_creation_failed', { + address: (await this.getCurrentAddress()) || '', + providers: ['google_drive'], + }); + } }; loadBackupAccounts = async (): Promise => { @@ -3502,6 +3934,12 @@ export class WalletController extends BaseController { createDelegator = async (amount, node) => { const result = await stakingService.createDelegator(amount, node); + // Track delegation creation + mixpanelTrack.track('delegation_created', { + address: (await this.getCurrentAddress()) || '', + node_id: node, + amount: amount, + }); return result; }; @@ -3577,44 +4015,32 @@ export class WalletController extends BaseController { getEmoji = async () => { const currentId = await storage.get('currentId'); - let emojires = await storage.get(`${currentId}emoji`); - if (!emojires) { - const index1 = Math.floor(Math.random() * emoji.emojis.length); - let index2; + // let emojires = await storage.get(`${currentId}emoji`) + // if (!emojires) { + // const index1 = Math.floor(Math.random() * emoji.emojis.length); + // let index2; - do { - index2 = Math.floor(Math.random() * emoji.emojis.length); - } while (index1 === index2); + // do { + // index2 = Math.floor(Math.random() * emoji.emojis.length); + // } while (index1 === index2); - emojires = [emoji.emojis[index1], emoji.emojis[index2]]; - storage.set(`${currentId}emoji`, emojires); - } + // emojires = [emoji.emojis[index1], emoji.emojis[index2]]; + // storage.set(`${currentId}emoji`, emojires) + // } - return emojires; + return emoji.emojis; }; - setEmoji = async (emoji, type) => { - const currentId = await storage.get('currentId'); - let emojires = await storage.get(`${currentId}emoji`); - if (!emojires) { - const index1 = Math.floor(Math.random() * emoji.emojis.length); - let index2; - - do { - index2 = Math.floor(Math.random() * emoji.emojis.length); - } while (index1 === index2); + setEmoji = async (emoji, type, index) => { + const network = await this.getNetwork(); - emojires = [emoji.emojis[index1], emoji.emojis[index2]]; - } if (type === 'evm') { - emojires[1] = emoji; + await userWalletService.setEvmEmoji(emoji); } else { - emojires[0] = emoji; + await userWalletService.setWalletEmoji(emoji, network, index); } - await storage.set(`${currentId}emoji`, emojires); - - return emojires; + return emoji; }; // Get the news from the server @@ -3648,10 +4074,12 @@ export class WalletController extends BaseController { // Check the storage status checkStorageStatus = async ({ transferAmount, + coin, movingBetweenEVMAndFlow, }: { - transferAmount?: number; - movingBetweenEVMAndFlow?: boolean; + transferAmount?: number; // amount in coins + coin?: string; // coin name + movingBetweenEVMAndFlow?: boolean; // are we moving between EVM and Flow? } = {}): Promise<{ isStorageSufficient: boolean; isStorageSufficientAfterAction: boolean; @@ -3662,6 +4090,7 @@ export class WalletController extends BaseController { await this.storageEvaluator.evaluateStorage( address!, transferAmount, + coin, movingBetweenEVMAndFlow ); return { @@ -3670,6 +4099,14 @@ export class WalletController extends BaseController { storageInfo, }; }; + + // Tracking stuff + + trackOnRampClicked = async (source: 'moonpay' | 'coinbase') => { + mixpanelTrack.track('on_ramp_clicked', { + source: source, + }); + }; } export default new WalletController(); diff --git a/src/background/fclConfig.ts b/src/background/fclConfig.ts index 30cf791b..404d0596 100644 --- a/src/background/fclConfig.ts +++ b/src/background/fclConfig.ts @@ -1,5 +1,6 @@ import * as fcl from '@onflow/fcl'; import { send as httpSend } from '@onflow/transport-http'; + import { storage } from './webapi'; const CONTRACTS_URL = @@ -103,6 +104,7 @@ export const fclMainnetConfig = async () => { const config = fcl .config() .put('accessNode.api', 'https://rest-mainnet.onflow.org') + // note this is the default transport. We don't really need to set this .put('sdk.transport', httpSend) .put('flow.network', 'mainnet'); @@ -122,6 +124,7 @@ export const fclTestnetConfig = async () => { const config = fcl .config() .put('accessNode.api', 'https://rest-testnet.onflow.org') + // note this is the default transport. We don't really need to set this .put('sdk.transport', httpSend) .put('flow.network', 'testnet'); diff --git a/src/background/images/placeholder.png b/src/background/images/placeholder.png new file mode 100644 index 00000000..9ed0370f Binary files /dev/null and b/src/background/images/placeholder.png differ diff --git a/src/background/index.ts b/src/background/index.ts index 81b8cffb..06710139 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -1,9 +1,22 @@ import 'reflect-metadata'; import { ethErrors } from 'eth-rpc-errors'; -import { WalletController } from 'background/controller/wallet'; -import { Message } from 'utils'; +import { initializeApp } from 'firebase/app'; +import { + getAuth, + signInAnonymously, + indexedDBLocalPersistence, + setPersistence, + onAuthStateChanged, +} from 'firebase/auth'; + +import eventBus from '@/eventBus'; +import { Message } from '@/shared/utils/messaging'; +import type { WalletController } from 'background/controller/wallet'; import { EVENTS } from 'consts'; -import { storage } from './webapi'; + +import { providerController, walletController } from './controller'; +import { preAuthzServiceDefinition } from './controller/serviceDefinition'; +import { fclTestnetConfig, fclMainnetConfig } from './fclConfig'; import { permissionService, preferenceService, @@ -22,24 +35,10 @@ import { passwordService, flownsService, stakingService, + mixpanelTrack, } from './service'; -import { providerController, walletController } from './controller'; - -import eventBus from '@/eventBus'; - -import { initializeApp, getApp } from 'firebase/app'; -import { getMessaging, getToken } from 'firebase/messaging'; -import { - getAuth, - signInAnonymously, - indexedDBLocalPersistence, - setPersistence, - onAuthStateChanged, -} from '@firebase/auth'; -import { fclTestnetConfig, fclMainnetConfig } from './fclConfig'; import { getFirbaseConfig } from './utils/firebaseConfig'; -import { getRemoteConfig } from 'firebase/remote-config'; -import { preAuthzServiceDefinition } from './controller/serviceDefinition'; +import { storage } from './webapi'; const { PortMessage } = Message; const chromeWindow = await chrome.windows.getCurrent(); @@ -138,6 +137,7 @@ async function restoreAppState() { await passwordService.init(); await flownsService.init(); await stakingService.init(); + await mixpanelTrack.init(); // rpcCache.start(); appStoreLoaded = true; @@ -171,7 +171,7 @@ function deleteTimer(port) { } chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { - if (request == 'ping') { + if (request === 'ping') { sendResponse('pong'); return; } @@ -182,7 +182,6 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { chrome.runtime.onConnect.addListener((port) => { // openapiService.getConfig(); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore port._timer = setTimeout(forceReconnect, 250e3, port); port.onDisconnect.addListener(deleteTimer); @@ -281,7 +280,7 @@ const findPath = (service) => { case 'authn': return 'Connect'; case 'authz': - return 'Confimation'; + return 'Confirmation'; case 'user-signature': return 'SignMessage'; default: @@ -347,11 +346,12 @@ const extMessageHandler = (msg, sender, sendResponse) => { }) .then((tabs) => { const tabId = tabs[0].id; - tabId && + if (tabId) { chrome.tabs.sendMessage(tabId, { type: 'FCW:NETWORK', network: userWalletService.getNetwork(), }); + } }); } // Launches extension popup window @@ -380,7 +380,7 @@ const extMessageHandler = (msg, sender, sendResponse) => { params: { tabId, type: service.type }, approvalComponent: findPath(service), }, - { height: service.type == 'authz' ? 700 : 620 } + { height: service.type === 'authz' ? 700 : 620 } ) .then((res) => { if (res === 'unlocked') { @@ -389,7 +389,7 @@ const extMessageHandler = (msg, sender, sendResponse) => { params: { tabId, type: service.type }, approvalComponent: findPath(service), }, - { height: service.type == 'authz' ? 700 : 620 } + { height: service.type === 'authz' ? 700 : 620 } ); } }); @@ -415,3 +415,5 @@ chrome.runtime.onConnect.addListener((port) => { function onMessage(msg, port) { console.log('received', msg, 'from', port.sender); } + +console.log('Is fetch native?', fetch.toString().includes('[native code]')); diff --git a/src/background/service/addressBook.ts b/src/background/service/addressBook.ts index c3aeef8d..42576d3e 100644 --- a/src/background/service/addressBook.ts +++ b/src/background/service/addressBook.ts @@ -1,5 +1,6 @@ import { createPersistStore } from 'background/utils'; -import { Contact } from './networkModel'; + +import { type Contact } from './networkModel'; interface AddressBookStore { addressBook: Record; diff --git a/src/background/service/googleDrive.ts b/src/background/service/googleDrive.ts index a4f1bb2f..c8ec6481 100644 --- a/src/background/service/googleDrive.ts +++ b/src/background/service/googleDrive.ts @@ -44,7 +44,7 @@ class GoogleDriveService { hasGooglePremission = async (): Promise => { try { const token = await this.getAuthTokenWrapper(false); - return token != undefined || token != null; + return token !== undefined && token !== null; } catch (err) { return false; } diff --git a/src/background/service/googleSafeHost.ts b/src/background/service/googleSafeHost.ts index 169cdc88..36e38ca1 100644 --- a/src/background/service/googleSafeHost.ts +++ b/src/background/service/googleSafeHost.ts @@ -1,4 +1,5 @@ import axios from 'axios'; + import { createPersistStore } from 'background/utils'; interface GoogleHostModel { diff --git a/src/background/service/i18n.ts b/src/background/service/i18n.ts index 1092ac06..a05b1354 100644 --- a/src/background/service/i18n.ts +++ b/src/background/service/i18n.ts @@ -1,4 +1,5 @@ import i18n from 'i18next'; + import messages from '../../messages.json'; export const fetchLocale = async (locale) => { diff --git a/src/background/service/index.ts b/src/background/service/index.ts index 2be228d7..d4e7dd08 100644 --- a/src/background/service/index.ts +++ b/src/background/service/index.ts @@ -20,3 +20,4 @@ export { default as stakingService } from './staking'; export { default as signTextHistoryService } from './signTextHistory'; export { default as i18n } from './i18n'; export { default as newsService } from './news'; +export { mixpanelTrack } from './mixpanel'; diff --git a/src/background/service/keyring/index.ts b/src/background/service/keyring/index.ts index afb13bc9..0699bec4 100644 --- a/src/background/service/keyring/index.ts +++ b/src/background/service/keyring/index.ts @@ -1,25 +1,28 @@ /// fork from https://github.com/MetaMask/KeyringController/blob/master/index.js import { EventEmitter } from 'events'; -import log from 'loglevel'; + +import { ObservableStore } from '@metamask/obs-store'; +import HdKeyring from '@rabby-wallet/eth-hd-keyring'; +import SimpleKeyring from '@rabby-wallet/eth-simple-keyring'; +import * as bip39 from 'bip39'; import encryptor from 'browser-passworder'; import * as ethUtil from 'ethereumjs-util'; -import * as bip39 from 'bip39'; -import { ObservableStore } from '@metamask/obs-store'; +import log from 'loglevel'; + +import eventBus from '@/eventBus'; import { normalizeAddress, setPageStateCacheWhenPopupClose, hasWalletConnectPageStateCache, } from 'background/utils'; -import SimpleKeyring from '@rabby-wallet/eth-simple-keyring'; -import HdKeyring from '@rabby-wallet/eth-hd-keyring'; - -import preference from '../preference'; -import i18n from '../i18n'; import { KEYRING_TYPE } from 'consts'; -import DisplayKeyring from './display'; -import eventBus from '@/eventBus'; + import { storage } from '../../webapi'; +import i18n from '../i18n'; +import preference from '../preference'; + +import type DisplayKeyring from './display'; export const KEYRING_SDK_TYPES = { SimpleKeyring, @@ -1090,7 +1093,7 @@ class KeyringService extends EventEmitter { * Deallocates all currently managed keyrings and accounts. * Used before initializing a new vault. */ - /* eslint-disable require-await */ + async clearKeyrings(): Promise { // clear keyrings from memory this.keyrings = []; diff --git a/src/background/service/mixpanel.ts b/src/background/service/mixpanel.ts new file mode 100644 index 00000000..ed0e2c6e --- /dev/null +++ b/src/background/service/mixpanel.ts @@ -0,0 +1,60 @@ +import eventBus from '@/eventBus'; +import type { TrackingEvents } from '@/shared/types/tracking-types'; + +// TODO: Look at using a server side proxy service to send events to Mixpanel +// Note: Mixpanel is initialized in the browser side. Yes... it is possible for events to be lost if there is no listener. +// At some point, we should migrate to a more reliable event bus. +class MixpanelService { + private static instance: MixpanelService; + private initialized = false; + + private constructor() { + // Private constructor for singleton + } + + static getInstance(): MixpanelService { + if (!MixpanelService.instance) { + MixpanelService.instance = new MixpanelService(); + } + return MixpanelService.instance; + } + + init() { + if (this.initialized) return; + + this.initialized = true; + } + track(eventName: T, properties?: TrackingEvents[T]) { + chrome.runtime.sendMessage({ + msg: 'track_event', + eventName, + properties, + }); + } + + time(eventName: T) { + chrome.runtime.sendMessage({ + msg: 'track_time', + eventName, + }); + } + + identify(userId: string) { + if (!this.initialized) return; + + chrome.runtime.sendMessage({ + msg: 'track_user', + userId, + }); + } + + reset() { + if (!this.initialized) return; + + chrome.runtime.sendMessage({ + msg: 'track_reset', + }); + } +} + +export const mixpanelTrack = MixpanelService.getInstance(); diff --git a/src/background/service/networkModel.ts b/src/background/service/networkModel.ts index 988f65c3..51ed4674 100644 --- a/src/background/service/networkModel.ts +++ b/src/background/service/networkModel.ts @@ -171,6 +171,7 @@ export interface BlockchainResponse { coins: Array; id: number; icon: string; + color: string; } interface Thumbnail { diff --git a/src/background/service/nft.ts b/src/background/service/nft.ts index aa933858..bdbc78ca 100644 --- a/src/background/service/nft.ts +++ b/src/background/service/nft.ts @@ -1,6 +1,7 @@ import { createPersistStore } from 'background/utils'; import { storage } from 'background/webapi'; -import { NFTData, NFTCollectionData, NFTCollectionList } from './networkModel'; + +import { type NFTData, type NFTCollectionData, type NFTCollectionList } from './networkModel'; interface NftStore { nft: NFTNetwork; collection: NFTCollectionNetwork; diff --git a/src/background/service/notification.ts b/src/background/service/notification.ts index fd743e54..55af41c2 100644 --- a/src/background/service/notification.ts +++ b/src/background/service/notification.ts @@ -1,6 +1,8 @@ import Events from 'events'; + import { ethErrors } from 'eth-rpc-errors'; import { EthereumProviderError } from 'eth-rpc-errors/dist/classes'; + import { winMgr } from 'background/webapi'; import { IS_CHROME, IS_LINUX } from 'consts'; diff --git a/src/background/service/openapi.ts b/src/background/service/openapi.ts index b44831a6..54297c71 100644 --- a/src/background/service/openapi.ts +++ b/src/background/service/openapi.ts @@ -1,3 +1,7 @@ +import * as fcl from '@onflow/fcl'; +import type { Method } from 'axios'; +import dayjs from 'dayjs'; +import { initializeApp, getApp } from 'firebase/app'; import { getAuth, signInWithCustomToken, @@ -5,23 +9,21 @@ import { indexedDBLocalPersistence, signInAnonymously, onAuthStateChanged, -} from '@firebase/auth'; -import type { Unsubscribe } from '@firebase/util'; -import * as fcl from '@onflow/fcl'; -import type { Method } from 'axios'; -import dayjs from 'dayjs'; -import { initializeApp, getApp } from 'firebase/app'; + type Unsubscribe, +} from 'firebase/auth'; import { getInstallations, getId } from 'firebase/installations'; import type { TokenInfo } from 'flow-native-token-registry'; import log from 'loglevel'; import { storage } from '@/background/webapi'; +import { isValidFlowAddress, isValidEthereumAddress } from '@/shared/utils/address'; +import { getStringFromHashAlgo, getStringFromSignAlgo } from '@/shared/utils/algo'; +import { getPeriodFrequency } from '@/shared/utils/getPeriodFrequency'; import { createPersistStore, getScripts, findKeyAndInfo } from 'background/utils'; import { getFirbaseConfig, getFirbaseFunctionUrl } from 'background/utils/firebaseConfig'; import fetchConfig from 'background/utils/remoteConfig'; import { INITIAL_OPENAPI_URL, WEB_NEXT_URL } from 'consts'; -import { getPeriodFrequency } from '../../utils'; import { fclMainnetConfig, fclTestnetConfig } from '../fclConfig'; import { @@ -40,9 +42,6 @@ import { PriceProvider, } from './networkModel'; -// import { getRemoteConfig, fetchAndActivate, getValue } from 'firebase/remote-config'; -// import configJson from 'background/utils/firebase.config.json'; - import { userWalletService, coinListService, @@ -51,8 +50,8 @@ import { transactionService, nftService, googleSafeHostService, + mixpanelTrack, } from './index'; - // import { userInfo } from 'os'; // import userWallet from './userWallet'; // const axios = axiosOriginal.create({ adapter }) @@ -83,10 +82,9 @@ const remoteFetch = fetchConfig; const pricesMap = {}; const waitForAuthInit = async () => { - let unsubscribe: Promise; + let unsubscribe: Unsubscribe; await new Promise((resolve) => { - // @ts-expect-error firebase auth function - unsubscribe = auth.onAuthStateChanged((user) => resolve()); + unsubscribe = auth.onAuthStateChanged((_user) => resolve()); }); (await unsubscribe!)(); }; @@ -516,61 +514,42 @@ class OpenApiService { } }; - getTokenPrices = async () => { - const tokenPriceMap = await storage.getExpiry('pricesMap'); - if (tokenPriceMap) { - return tokenPriceMap; - } else { - let data: any = []; - try { - const response = await this.sendRequest('GET', '/api/prices', {}, {}, WEB_NEXT_URL); - data = response.data || []; // Ensure data is set to an empty array if response.data is undefined - } catch (error) { - console.error('Error fetching prices:', error); - data = []; // Set data to empty array in case of an error - } - - if (pricesMap && pricesMap['FLOW']) { - return pricesMap; - } - data.map((d) => { - const { rateToUSD, contractName, contractAddress } = d; - const key = contractName.toLowerCase() + '' + contractAddress.toLowerCase(); - pricesMap[key] = rateToUSD.toFixed(8); - }); - await storage.setExpiry('pricesMap', pricesMap, 300000); // 5 minutes in milliseconds - return pricesMap; + getTokenPrices = async (storageKey: string, isEvm: boolean = false) => { + const cachedPrices = await storage.getExpiry(storageKey); + if (cachedPrices) { + return cachedPrices; } - }; - getTokenEvmPrices = async () => { - const tokenPriceMap = await storage.getExpiry('evmPrice'); - if (tokenPriceMap) { - return tokenPriceMap; - } else { - let data: any = []; - try { - const response = await this.sendRequest('GET', '/api/prices', {}, {}, WEB_NEXT_URL); - data = response.data || []; // Ensure data is set to an empty array if response.data is undefined - } catch (error) { - console.error('Error fetching prices:', error); - data = []; // Set data to empty array in case of an error - } + const pricesMap: Record = {}; - data.map((d) => { - if (d.evmAddress) { - const { rateToUSD, evmAddress } = d; + try { + const response = await this.sendRequest('GET', '/api/prices', {}, {}, WEB_NEXT_URL); + const data = response?.data || []; + + data.forEach((token) => { + if (isEvm && token.evmAddress) { + // EVM price + const { rateToUSD, evmAddress } = token; const key = evmAddress.toLowerCase(); - pricesMap[key] = rateToUSD.toFixed(5); - } else { - const { rateToUSD, symbol } = d; + pricesMap[key] = Number(rateToUSD).toFixed(8); + } else if (!isEvm && token.contractName && token.contractAddress) { + // Flow chain price + const { rateToUSD, contractName, contractAddress } = token; + const key = `${contractName.toLowerCase()}${contractAddress.toLowerCase()}`; + pricesMap[key] = Number(rateToUSD).toFixed(8); + } else if (isEvm && token.symbol) { + // Handle fallback for EVM tokens + const { rateToUSD, symbol } = token; const key = symbol.toUpperCase(); - pricesMap[key] = rateToUSD.toFixed(5); + pricesMap[key] = Number(rateToUSD).toFixed(8); } }); - await storage.setExpiry('evmPrice', pricesMap, 300000); // 5 minutes in milliseconds - return pricesMap; + } catch (error) { + console.error('Error fetching prices:', error); } + + await storage.setExpiry(storageKey, pricesMap, 300000); + return pricesMap; }; getPricesBySymbol = async (symbol: string, data) => { @@ -694,6 +673,13 @@ class OpenApiService { ); await this._signWithCustom(data.data.custom_token); await storage.set('currentId', data.data.id); + + // Track the registration + mixpanelTrack.track('account_created', { + public_key: account_key.public_key, + sign_algo: getStringFromSignAlgo(account_key.sign_algo), + hash_algo: getStringFromHashAlgo(account_key.hash_algo), + }); return data; }; @@ -1161,12 +1147,13 @@ class OpenApiService { getAccountMinFlow = async (address: string) => { const script = await getScripts('basic', 'getAccountMinFlow'); - - const minFlow = await fcl.query({ - cadence: script, - args: (arg, t) => [arg(address, t.Address)], - }); - return minFlow; + if (isValidFlowAddress(address)) { + const minFlow = await fcl.query({ + cadence: script, + args: (arg, t) => [arg(address, t.Address)], + }); + return minFlow; + } }; getFlownsDomainsByAddress = async (address: string) => { @@ -1309,13 +1296,20 @@ class OpenApiService { }; getEvmTokenInfo = async (name: string, network = ''): Promise => { - // FIX ME: Get defaultTokenList from firebase remote config if (!network) { network = await userWalletService.getNetwork(); } + const tokens = await this.getEvmListFromGithub(network); - // const coins = await remoteFetch.flowCoins(); - return tokens.find((item) => item.symbol.toLowerCase() === name.toLowerCase()); + + const tokenInfo = tokens.find((item) => item.symbol.toLowerCase() === name.toLowerCase()); + + if (tokenInfo && isValidEthereumAddress(tokenInfo.address)) { + return tokenInfo; + } + + const freshTokens = await this.refreshEvmGitToken(network); + return freshTokens.find((item) => item.symbol.toLowerCase() === name.toLowerCase()); }; getTokenInfoByContract = async (contractName: string): Promise => { @@ -1557,6 +1551,8 @@ class OpenApiService { this.mergeCustomTokens(gitToken, evmCustomToken); storage.setExpiry(`GitTokenList${network}${chainType}`, gitToken, 600000); + + return gitToken; }; refreshCustomEvmGitToken = async (network) => { diff --git a/src/background/service/password.ts b/src/background/service/password.ts index 47ab8639..5fc4a55e 100644 --- a/src/background/service/password.ts +++ b/src/background/service/password.ts @@ -1,4 +1,5 @@ import { createSessionStore } from 'background/utils'; + import googleDriveService from './googleDrive'; interface PasswordStore { diff --git a/src/background/service/permission.ts b/src/background/service/permission.ts index a58bcf56..22cf674f 100644 --- a/src/background/service/permission.ts +++ b/src/background/service/permission.ts @@ -1,7 +1,8 @@ +import { max } from 'lodash'; import LRU from 'lru-cache'; + import { createPersistStore } from 'background/utils'; import { INTERNAL_REQUEST_ORIGIN } from 'consts'; -import { max } from 'lodash'; export interface ConnectedSite { origin: string; diff --git a/src/background/service/preference.ts b/src/background/service/preference.ts index 6d7353fe..a8c34b2e 100644 --- a/src/background/service/preference.ts +++ b/src/background/service/preference.ts @@ -1,11 +1,15 @@ +import compareVersions from 'compare-versions'; import cloneDeep from 'lodash/cloneDeep'; + +import { storage } from '@/background/webapi'; import eventBus from '@/eventBus'; -import compareVersions from 'compare-versions'; import { createPersistStore } from 'background/utils'; -import { keyringService, sessionService, i18n } from './index'; import { EVENTS } from 'consts'; + import { FlowNetwork } from './networkModel'; -import { storage } from '@/background/webapi'; + +import { keyringService, sessionService, i18n } from './index'; + const version = process.env.release || '0'; export interface Account { type: string; diff --git a/src/background/service/proxy.ts b/src/background/service/proxy.ts index aa20ef3e..4d380a1f 100644 --- a/src/background/service/proxy.ts +++ b/src/background/service/proxy.ts @@ -1,23 +1,13 @@ -import { createPersistStore } from 'background/utils'; -import { - WalletResponse, - BlockchainResponse, - ChildAccount, - DeviceInfoRequest, -} from './networkModel'; -import * as fcl from '@onflow/fcl'; -import * as secp from '@noble/secp256k1'; -import { keyringService, openapiService } from 'background/service'; -import wallet from 'background/controller/wallet'; -import { getApp } from 'firebase/app'; -import { signWithKey, seed2PubKey } from '@/ui/utils/modules/passkey.js'; -import { findAddressWithSeed, findAddressWithPK } from '@/ui/utils/modules/findAddressWithPK'; -import { withPrefix } from '@/ui/utils/address'; -import { getAuth, signInAnonymously } from '@firebase/auth'; -import { storage } from '../webapi'; +import { Core } from '@walletconnect/core'; import SignClient from '@walletconnect/sign-client'; + import { FCLWalletConnectMethod } from '@/ui/utils/type'; -import { Core } from '@walletconnect/core'; +import wallet from 'background/controller/wallet'; +import { keyringService, openapiService } from 'background/service'; + +import { storage } from '../webapi'; + +import { type DeviceInfoRequest } from './networkModel'; class Proxy { proxySign = async (token: string, userId: string) => { @@ -49,7 +39,6 @@ class Proxy { const topicId = await storage.get(`${currentId}Topic`); try { const signwallet = await SignClient.init({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Unreachable code error core: new Core({ projectId: process.env.WC_PROJECTID, @@ -113,7 +102,6 @@ class Proxy { const topicId = await storage.get(`${currentId}Topic`); try { const signwallet = await SignClient.init({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Unreachable code error core: new Core({ projectId: process.env.WC_PROJECTID, diff --git a/src/background/service/signTextHistory.ts b/src/background/service/signTextHistory.ts index 3c84a8cf..6c0ded0c 100644 --- a/src/background/service/signTextHistory.ts +++ b/src/background/service/signTextHistory.ts @@ -1,7 +1,9 @@ -import { createPersistStore } from 'background/utils'; -import permissionService, { ConnectedSite } from './permission'; import { sortBy } from 'lodash'; + import { CHAINS_ENUM, INTERNAL_REQUEST_ORIGIN } from '@/constant'; +import { createPersistStore } from 'background/utils'; + +import permissionService, { type ConnectedSite } from './permission'; export interface SignTextHistoryItem { site: ConnectedSite; diff --git a/src/background/service/staking.ts b/src/background/service/staking.ts index 4a31a8d4..af1e500b 100644 --- a/src/background/service/staking.ts +++ b/src/background/service/staking.ts @@ -1,14 +1,8 @@ -import { createPersistStore, getScripts } from 'background/utils'; -import * as t from '@onflow/types'; import * as fcl from '@onflow/fcl'; -import * as secp from '@noble/secp256k1'; -import { keyringService, openapiService, userWalletService } from 'background/service'; -import wallet from 'background/controller/wallet'; -import { getApp } from 'firebase/app'; -import { getAuth } from '@firebase/auth'; -import { withPrefix } from '@/ui/utils/address'; -import fetchConfig from 'background/utils/remoteConfig'; -import { storage } from '@/background/webapi'; +import * as t from '@onflow/types'; + +import { userWalletService } from 'background/service'; +import { createPersistStore, getScripts } from 'background/utils'; interface StakingStore { nodeList: Record; diff --git a/src/background/service/storage-evaluator.ts b/src/background/service/storage-evaluator.ts index 18110b73..8aa2a17d 100644 --- a/src/background/service/storage-evaluator.ts +++ b/src/background/service/storage-evaluator.ts @@ -17,6 +17,7 @@ export class StorageEvaluator { async evaluateStorage( address: string, sendAmount?: number, + coin?: string, movingBetweenEVMAndFlow?: boolean ): Promise { // Get storage info from openapi service @@ -32,7 +33,7 @@ export class StorageEvaluator { if (sendAmount !== undefined) { // This is the amount of flow that will be used by the transaction const flowUsed = - sendAmount + + (coin === 'flow' ? sendAmount : 0) + (movingBetweenEVMAndFlow ? StorageEvaluator.FIXED_MOVE_FEE : 0) + StorageEvaluator.AVERAGE_TX_FEE; diff --git a/src/background/service/transaction.ts b/src/background/service/transaction.ts index ee51b642..1e69a6db 100644 --- a/src/background/service/transaction.ts +++ b/src/background/service/transaction.ts @@ -1,4 +1,5 @@ import { createPersistStore, createSessionStore } from 'background/utils'; + import { TransactionItem } from './networkModel'; interface TransactionStore { expiry: number; diff --git a/src/background/service/user.ts b/src/background/service/user.ts index dd4d2efa..4739a452 100644 --- a/src/background/service/user.ts +++ b/src/background/service/user.ts @@ -1,5 +1,7 @@ import { createPersistStore } from 'background/utils'; +import { mixpanelTrack } from './mixpanel'; + export interface UserInfoStore { avatar: string; nickname: string; @@ -56,10 +58,17 @@ class UserInfo { this.store.avatar = url.toString(); } this.store.avatar = data['avatar']; + + // identify the user + mixpanelTrack.identify(this.store.user_id); + + // TODO: track the user info if not in private mode }; addUserId = (userId: string) => { this.store.user_id = userId; + // identify the user + mixpanelTrack.identify(this.store.user_id); }; removeUserInfo = () => { @@ -68,6 +77,8 @@ class UserInfo { updateUserInfo = (data: UserInfoStore) => { this.store = data; + // identify the user + mixpanelTrack.identify(this.store.user_id); }; setDashIndex = (data: number) => { diff --git a/src/background/service/userWallet.ts b/src/background/service/userWallet.ts index cd86cf02..031cd4ee 100644 --- a/src/background/service/userWallet.ts +++ b/src/background/service/userWallet.ts @@ -1,15 +1,18 @@ -import { getAuth, signInAnonymously } from '@firebase/auth'; import * as secp from '@noble/secp256k1'; import * as fcl from '@onflow/fcl'; import { getApp } from 'firebase/app'; +import { getAuth, signInAnonymously } from 'firebase/auth'; -import { withPrefix } from '@/ui/utils/address'; +import { withPrefix } from '@/shared/utils/address'; +import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; +// eslint-disable-next-line no-restricted-imports import { findAddressWithSeed, findAddressWithPK } from '@/ui/utils/modules/findAddressWithPK'; +// eslint-disable-next-line no-restricted-imports import { signWithKey, seed2PubKey } from '@/ui/utils/modules/passkey.js'; import wallet from 'background/controller/wallet'; -import { keyringService, openapiService } from 'background/service'; +import { keyringService, mixpanelTrack, openapiService } from 'background/service'; import { createPersistStore } from 'background/utils'; -import { getHashAlgo, getSignAlgo, getStoragedAccount } from 'ui/utils'; +import { getStoragedAccount } from 'background/utils/getStoragedAccount'; import { storage } from '../webapi'; @@ -48,22 +51,24 @@ class UserWallet { name: '', icon: '', address: '', - chain_id: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + chain_id: 'mainnet', id: 1, coins: ['flow'], + color: '', }, evmWallet: { name: '', icon: '', address: '', - chain_id: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + chain_id: 'mainnet', id: 1, coins: ['flow'], + color: '', }, activeChild: null, evmEnabled: false, monitor: 'flowscan', - network: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + network: 'mainnet', }, }); }; @@ -80,33 +85,37 @@ class UserWallet { name: '', address: '', icon: '', - chain_id: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + chain_id: 'mainnet', id: 1, coins: ['flow'], + color: '', }, evmWallet: { name: '', address: '', icon: '', - chain_id: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + chain_id: 'mainnet', id: 1, coins: ['flow'], + color: '', }, activeChild: null, evmEnabled: false, monitor: 'flowscan', - network: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + network: 'mainnet', }; }; setUserWallets = async (filteredData, network) => { - for (const wallet of filteredData) { - const chainId = wallet.chain_id; - this.store.wallets[chainId] = [wallet]; - } - + console.log('filteredData ', filteredData); + this.store.wallets[network] = filteredData; + let walletIndex = (await storage.get('currentWalletIndex')) || 0; if (this.store.wallets[network] && this.store.wallets[network].length > 0) { - const current = this.store.wallets[network][0].blockchain[0]; + if (walletIndex >= filteredData.length) { + walletIndex = 0; // Reset walletIndex to 0 if it exceeds the array length + await storage.set('currentWalletIndex', 0); + } + const current = this.store.wallets[network][walletIndex].blockchain[0]; this.store.currentWallet = current; } else { console.error(`No wallet found for network: ${network}`); @@ -125,11 +134,15 @@ class UserWallet { return this.store.activeChild; }; - setCurrentWallet = (wallet: any, key: any, network: string) => { + setCurrentWallet = async (wallet: any, key: any, network: string, index = null) => { if (key && key !== 'evm') { this.store.currentWallet = wallet; } else if (key === 'evm') { this.store.evmWallet.address = wallet.address; + } else if (index !== null) { + await storage.set('currentWalletIndex', index); + const current = this.store.wallets[network][index].blockchain[0]; + this.store.currentWallet = current; } else { const current = this.store.wallets[network][0].blockchain[0]; this.store.currentWallet = current; @@ -150,7 +163,7 @@ class UserWallet { } if (this.store.network !== network) { this.store.activeChild = null; - this.store.currentWallet = this.store.wallets[network][0].blockchain[0]; + // this.store.currentWallet = this.store.wallets[network][0].blockchain[0]; } this.store.network = network; }; @@ -172,9 +185,10 @@ class UserWallet { name: '', address: '', icon: '', - chain_id: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet', + chain_id: 'mainnet', id: 1, coins: ['flow'], + color: '', }; this.store.evmEnabled = false; }; @@ -216,21 +230,42 @@ class UserWallet { return this.store.evmWallet; }; - setEvmAddress = (address: string) => { + setEvmAddress = (address: string, emoji) => { + console.log('emoji setEvmAddress ', emoji); if (address.length > 20) { this.store.evmWallet.address = address; + this.store.evmWallet.name = emoji[9].name; + this.store.evmWallet.icon = emoji[9].emoji; + this.store.evmWallet.color = emoji[9].bgcolor; } else { this.store.evmWallet.address = ''; } }; - getMainWallet = (network: string) => { - const wallet = this.store.wallets[network][0].blockchain[0]; + setEvmEmoji = (emoji) => { + this.store.evmWallet.name = emoji.name; + this.store.evmWallet.icon = emoji.emoji; + this.store.evmWallet.color = emoji.bgcolor; + }; + + setWalletEmoji = (emoji, network, id) => { + this.store.wallets[network][id].name = emoji.name; + this.store.wallets[network][id].icon = emoji.emoji; + this.store.wallets[network][id].color = emoji.bgcolor; + this.store.wallets[network][id].blockchain[0].name = emoji.name; + this.store.wallets[network][id].blockchain[0].icon = emoji.emoji; + this.store.wallets[network][id].blockchain[0].color = emoji.bgcolor; + }; + + getMainWallet = async (network: string) => { + const walletIndex = (await storage.get('currentWalletIndex')) || 0; + const wallet = this.store.wallets[network][walletIndex].blockchain[0]; return withPrefix(wallet.address) || ''; }; - returnMainWallet = (network: string) => { - const wallet = this.store.wallets[network][0].blockchain[0]; + returnMainWallet = async (network: string) => { + const walletIndex = (await storage.get('currentWalletIndex')) || 0; + const wallet = this.store.wallets[network][walletIndex].blockchain[0]; return wallet; }; @@ -238,18 +273,39 @@ class UserWallet { return withPrefix(this.store.currentWallet.address) || ''; }; + private extractScriptName = (cadence: string): string => { + const scriptLines = cadence.split('\n'); + for (const line of scriptLines) { + if (line.includes('// Flow Wallet')) { + // ' // Flow Wallet - testnet Script sendNFT - v2.31' + const nameMatch = line.match(/\/\/ Flow Wallet -\s*(testnet|mainnet)\s*Script\s+(\w+)/); + return nameMatch ? nameMatch[2] : 'unknown_script'; + } + } + return 'unknown_script'; + }; sendTransaction = async (cadence: string, args: any[]): Promise => { + const scriptName = this.extractScriptName(cadence); //add proxy - const allowed = await wallet.allowLilicoPay(); - const txID = await fcl.mutate({ - cadence: cadence, - args: (arg, t) => args, - proposer: this.authorizationFunction, - authorizations: [this.authorizationFunction], - payer: allowed ? this.payerAuthFunction : this.authorizationFunction, - limit: 9999, - }); - return txID; + try { + const allowed = await wallet.allowLilicoPay(); + const txID = await fcl.mutate({ + cadence: cadence, + args: (arg, t) => args, + proposer: this.authorizationFunction, + authorizations: [this.authorizationFunction], + payer: allowed ? this.payerAuthFunction : this.authorizationFunction, + limit: 9999, + }); + + return txID; + } catch (error) { + mixpanelTrack.track('script_error', { + script_id: scriptName, + error: error, + }); + throw error; + } }; sign = async (signableMessage: string): Promise => { @@ -290,7 +346,12 @@ class UserWallet { if (!result[0].pubK) { console.log('No result found, creating a new result object'); // Create a new result object with extension default setting - result = await findAddressWithPK(keys.pk, ''); + const foundResult = await findAddressWithPK(keys.pk, ''); + if (!foundResult) { + throw new Error('Unable to find a address with the provided PK. Aborting login.'); + } + + result = foundResult; } const app = getApp(process.env.NODE_ENV!); const auth = getAuth(app); diff --git a/src/background/utils/getStoragedAccount.ts b/src/background/utils/getStoragedAccount.ts new file mode 100644 index 00000000..200db6b3 --- /dev/null +++ b/src/background/utils/getStoragedAccount.ts @@ -0,0 +1,30 @@ +import { storage } from '@/background/webapi'; + +export const getStoragedAccount = async () => { + const accountIndex = (await storage.get('currentAccountIndex')) || 0; + const currentId = (await storage.get('currentId')) || null; + const loggedInAccounts = (await storage.get('loggedInAccounts')) || []; + let account; + + // Check if currentId is provided and valid + if (currentId !== null) { + // Find account with the currentId + account = loggedInAccounts.find((acc) => acc.id === currentId); + + // If no account is found with currentId, default to accountIndex + if (!account) { + account = loggedInAccounts[accountIndex]; + } + } else { + // If currentId is not provided, use accountIndex + account = loggedInAccounts[accountIndex]; + } + + if (!account) { + // Handle the case when no account is found + throw new Error('Account info not found.'); + } else { + // Return account + return account; + } +}; diff --git a/src/background/utils/index.ts b/src/background/utils/index.ts index 7cb3474d..85f6ac36 100644 --- a/src/background/utils/index.ts +++ b/src/background/utils/index.ts @@ -1,9 +1,14 @@ import * as ethUtil from 'ethereumjs-util'; + +import packageJson from '@/../package.json'; +import { storage } from '@/background/webapi'; + +const { version } = packageJson; +import { mixpanelTrack } from '../service'; import pageStateCache from '../service/pageStateCache'; + export { default as createPersistStore } from './persisitStore'; export { default as createSessionStore } from './sessionStore'; -import { storage } from '@/background/webapi'; -import { version } from '@/../package.json'; // {a:{b: string}} => {1: 'a.b'} // later same [source] value will override [result] key generated before @@ -93,12 +98,22 @@ export const isSameAddress = (a: string, b: string) => { }; export const getScripts = async (folder: string, scriptName: string) => { - const { data } = await storage.get('cadenceScripts'); - const files = data[folder]; - const script = files[scriptName]; - const scriptString = Buffer.from(script, 'base64').toString('utf-8'); - const modifiedScriptString = scriptString.replaceAll('', `Extension-${version}`); - return modifiedScriptString; + try { + const { data } = await storage.get('cadenceScripts'); + const files = data[folder]; + const script = files[scriptName]; + const scriptString = Buffer.from(script, 'base64').toString('utf-8'); + const modifiedScriptString = scriptString.replaceAll('', `Extension-${version}`); + return modifiedScriptString; + } catch (error) { + if (error instanceof Error) { + mixpanelTrack.track('script_error', { + script_id: scriptName, + error: error.message, + }); + } + throw error; + } }; export const findKeyAndInfo = (keys, publicKey) => { diff --git a/src/background/utils/remoteConfig.ts b/src/background/utils/remoteConfig.ts index c888a17d..117a0560 100644 --- a/src/background/utils/remoteConfig.ts +++ b/src/background/utils/remoteConfig.ts @@ -1,23 +1,19 @@ -import defaultTokenList from './defaultTokenList.json'; -import defaultConfig from './defaultConfig.json'; -import { TokenModel, NFTModel } from '../service/networkModel'; import { storage } from '@/background/webapi'; -import configJson from './firebase.config.json'; -import testnetNftList from './defaultNftList.testnet.json'; -import mainnetNftList from './defaultNftList.mainnet.json'; -import openapi from '../service/openapi'; + import { userWalletService } from '../service'; -interface RemoteConfigResponse { - flowCoins: TokenModel[]; - nftCollection: NFTModel[]; -} +import openapi from '../service/openapi'; + +import defaultConfig from './defaultConfig.json'; +import mainnetNftList from './defaultNftList.mainnet.json'; +import testnetNftList from './defaultNftList.testnet.json'; +import defaultTokenList from './defaultTokenList.json'; interface CacheState { result: any; expireTime: number; } -const baseURL = configJson.functions[process.env.NODE_ENV!]; +const BASE_FUNCTIONS_URL = process.env.FB_FUNCTIONS; class fetchRemoteConfig { coinState: CacheState = { result: {}, expireTime: 0 }; @@ -40,10 +36,8 @@ class fetchRemoteConfig { const exp = 1000 * 60 * 60 * 1 + now.getTime(); if (expire < now.getTime()) { try { - const result = await openapi.sendRequest('GET', '/fetchFTList', {}, {}, baseURL); - // fetch(`${baseURL}/fetchFTList`); - // const result = await coins.json(); - console.log(result, 'result coins'); + const result = await openapi.sendRequest('GET', '/fetchFTList', {}, {}, BASE_FUNCTIONS_URL); + this.coinState.result = result; this.coinState.expireTime = exp; return result; @@ -62,7 +56,7 @@ class fetchRemoteConfig { const now = new Date(); const exp = 1000 * 60 * 60 * 1 + now.getTime(); let defaultNftList = testnetNftList; - if (network == 'mainnet') { + if (network === 'mainnet') { defaultNftList = mainnetNftList; } if (expire < now.getTime()) { @@ -89,7 +83,7 @@ class fetchRemoteConfig { const now = new Date(); const exp = 1000 * 60 * 60 * 1 + now.getTime(); let defaultNftList = testnetNftList; - if (network == 'mainnet') { + if (network === 'mainnet') { defaultNftList = mainnetNftList; } if (expire < now.getTime()) { @@ -115,7 +109,7 @@ class fetchRemoteConfig { const exp = 1000 * 60 * 60 * 1 + now.getTime(); if (expire < now.getTime()) { try { - const result = await openapi.sendRequest('GET', '/config', {}, {}, baseURL); + const result = await openapi.sendRequest('GET', '/config', {}, {}, BASE_FUNCTIONS_URL); // fetch(`${baseURL}/config`); // const result = await config.json(); this.configState.result = result; @@ -135,36 +129,4 @@ class fetchRemoteConfig { } } -const fetchConfig = async () // remoteConfig -: Promise => { - // if (process.env.NODE_ENV === 'production') { - // remoteConfig.settings.minimumFetchIntervalMillis = 1000 * 60 * 10; - // } else { - // remoteConfig.settings.minimumFetchIntervalMillis = 1000 * 60 * 1; - // } - - // remoteConfig.defaultConfig = { - // 'nft_collections': defaultNftList, - // 'flow_coins': defaultTokenList - // } - - // await fetchAndActivate(remoteConfig); - // const nftCollection = JSON.parse(getValue(remoteConfig, 'nft_collections').asString()); - - // const flowCoins = JSON.parse(getValue(remoteConfig, 'flow_coins').asString()); - - // return {nftCollection, flowCoins}; - const network = await userWalletService.getNetwork(); - let defaultNftList = testnetNftList; - if (network == 'mainnet') { - defaultNftList = mainnetNftList; - } - return { flowCoins: defaultTokenList, nftCollection: defaultNftList }; -}; - -// export default { -// flowCoins: fetchCoin, -// nftCollection: fetchNFT -// }; - export default new fetchRemoteConfig(); diff --git a/src/background/webapi/storage.ts b/src/background/webapi/storage.ts index 261f6e65..588ecc4b 100644 --- a/src/background/webapi/storage.ts +++ b/src/background/webapi/storage.ts @@ -5,7 +5,6 @@ const get = async (prop?) => { }; const getSession = async (prop?) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const result = await chrome.storage.session?.get(prop); @@ -27,7 +26,6 @@ const set = async (prop, value): Promise => { }; const setSession = async (prop, value): Promise => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await chrome.storage.session?.set({ [prop]: value }); }; @@ -79,7 +77,6 @@ const remove = async (prop) => { }; const removeSession = async (prop) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await chrome.storage.session?.remove(prop); }; @@ -89,7 +86,6 @@ const clear = async () => { }; const clearSession = async () => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await chrome.storage.session?.clear(); }; diff --git a/src/background/webapi/window.ts b/src/background/webapi/window.ts index 2f75ddca..3258c992 100644 --- a/src/background/webapi/window.ts +++ b/src/background/webapi/window.ts @@ -1,4 +1,5 @@ import { EventEmitter } from 'events'; + import { IS_WINDOWS } from 'consts'; const event = new EventEmitter(); diff --git a/src/components/iconfont/IconAClose.js b/src/components/iconfont/IconAClose.js index f8417798..6598026f 100644 --- a/src/components/iconfont/IconAClose.js +++ b/src/components/iconfont/IconAClose.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAClose = ({ size, color, style: _style, ...rest }) => { +const IconAClose = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconAClose = ({ size, color, style: _style, ...rest }) => { ); }; -IconAClose.defaultProps = { - size: 18, -}; - export default IconAClose; diff --git a/src/components/iconfont/IconAGroup762.js b/src/components/iconfont/IconAGroup762.js index ad5b61f9..4dbea04e 100644 --- a/src/components/iconfont/IconAGroup762.js +++ b/src/components/iconfont/IconAGroup762.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAGroup762 = ({ size, color, style: _style, ...rest }) => { +const IconAGroup762 = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconAGroup762 = ({ size, color, style: _style, ...rest }) => { ); }; -IconAGroup762.defaultProps = { - size: 18, -}; - export default IconAGroup762; diff --git a/src/components/iconfont/IconAHamburgermenu.js b/src/components/iconfont/IconAHamburgermenu.js index f61cc98e..b9952991 100644 --- a/src/components/iconfont/IconAHamburgermenu.js +++ b/src/components/iconfont/IconAHamburgermenu.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAHamburgermenu = ({ size, color, style: _style, ...rest }) => { +const IconAHamburgermenu = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconAHamburgermenu = ({ size, color, style: _style, ...rest }) => { ); }; -IconAHamburgermenu.defaultProps = { - size: 18, -}; - export default IconAHamburgermenu; diff --git a/src/components/iconfont/IconAVector11Stroke.js b/src/components/iconfont/IconAVector11Stroke.js index 096a5e03..c48312c7 100644 --- a/src/components/iconfont/IconAVector11Stroke.js +++ b/src/components/iconfont/IconAVector11Stroke.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAVector11Stroke = ({ size, color, style: _style, ...rest }) => { +const IconAVector11Stroke = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconAVector11Stroke = ({ size, color, style: _style, ...rest }) => { ); }; -IconAVector11Stroke.defaultProps = { - size: 18, -}; - export default IconAVector11Stroke; diff --git a/src/components/iconfont/IconAbout.js b/src/components/iconfont/IconAbout.js index 152b33d9..d3226c2a 100644 --- a/src/components/iconfont/IconAbout.js +++ b/src/components/iconfont/IconAbout.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAbout = ({ size, color, style: _style, ...rest }) => { +const IconAbout = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconAbout = ({ size, color, style: _style, ...rest }) => { ); }; -IconAbout.defaultProps = { - size: 18, -}; - export default IconAbout; diff --git a/src/components/iconfont/IconAccount.js b/src/components/iconfont/IconAccount.js index 5c2eaafe..1df3d390 100644 --- a/src/components/iconfont/IconAccount.js +++ b/src/components/iconfont/IconAccount.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAccount = ({ size, color, style: _style, ...rest }) => { +const IconAccount = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconAccount = ({ size, color, style: _style, ...rest }) => { ); }; -IconAccount.defaultProps = { - size: 18, -}; - export default IconAccount; diff --git a/src/components/iconfont/IconAddressbook.d.ts b/src/components/iconfont/IconAddressbook.d.ts index 47264394..13d8314f 100644 --- a/src/components/iconfont/IconAddressbook.d.ts +++ b/src/components/iconfont/IconAddressbook.d.ts @@ -7,6 +7,6 @@ interface Props extends Omit, 'color'> { color?: string | string[]; } -declare const IconAddressBook: FunctionComponent; +declare const IconAddressbook: FunctionComponent; -export default IconAddressBook; +export default IconAddressbook; diff --git a/src/components/iconfont/IconAddressbook.js b/src/components/iconfont/IconAddressbook.js index 0576f3cb..96927d0e 100644 --- a/src/components/iconfont/IconAddressbook.js +++ b/src/components/iconfont/IconAddressbook.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAddressBook = ({ size, color, style: _style, ...rest }) => { +const IconAddressbook = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconAddressBook = ({ size, color, style: _style, ...rest }) => { ); }; -IconAddressBook.defaultProps = { - size: 18, -}; - -export default IconAddressBook; +export default IconAddressbook; diff --git a/src/components/iconfont/IconAppStore.js b/src/components/iconfont/IconAppStore.js index c825588e..8ad32a92 100644 --- a/src/components/iconfont/IconAppStore.js +++ b/src/components/iconfont/IconAppStore.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconAppStore = ({ size, color, style: _style, ...rest }) => { +const IconAppStore = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconAppStore = ({ size, color, style: _style, ...rest }) => { ); }; -IconAppStore.defaultProps = { - size: 18, -}; - export default IconAppStore; diff --git a/src/components/iconfont/IconBack.js b/src/components/iconfont/IconBack.js index 93ccff4c..88d9e470 100644 --- a/src/components/iconfont/IconBack.js +++ b/src/components/iconfont/IconBack.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconBack = ({ size, color, style: _style, ...rest }) => { +const IconBack = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconBack = ({ size, color, style: _style, ...rest }) => { ); }; -IconBack.defaultProps = { - size: 18, -}; - export default IconBack; diff --git a/src/components/iconfont/IconBackButton.js b/src/components/iconfont/IconBackButton.js index eddff8f0..73f0d899 100644 --- a/src/components/iconfont/IconBackButton.js +++ b/src/components/iconfont/IconBackButton.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconBackButton = ({ size, color, style: _style, ...rest }) => { +const IconBackButton = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconBackButton = ({ size, color, style: _style, ...rest }) => { ); }; -IconBackButton.defaultProps = { - size: 18, -}; - export default IconBackButton; diff --git a/src/components/iconfont/IconBackup.js b/src/components/iconfont/IconBackup.js index 62465358..b52dfd98 100644 --- a/src/components/iconfont/IconBackup.js +++ b/src/components/iconfont/IconBackup.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconBackup = ({ size, color, style: _style, ...rest }) => { +const IconBackup = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconBackup = ({ size, color, style: _style, ...rest }) => { ); }; -IconBackup.defaultProps = { - size: 18, -}; - export default IconBackup; diff --git a/src/components/iconfont/IconBinance.js b/src/components/iconfont/IconBinance.js index 999c6cba..0cb41765 100644 --- a/src/components/iconfont/IconBinance.js +++ b/src/components/iconfont/IconBinance.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconBinance = ({ size, color, style: _style, ...rest }) => { +const IconBinance = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconBinance = ({ size, color, style: _style, ...rest }) => { ); }; -IconBinance.defaultProps = { - size: 18, -}; - export default IconBinance; diff --git a/src/components/iconfont/IconCheckmark.js b/src/components/iconfont/IconCheckmark.js index 0df05cfc..f2ff8e59 100644 --- a/src/components/iconfont/IconCheckmark.js +++ b/src/components/iconfont/IconCheckmark.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconCheckmark = ({ size, color, style: _style, ...rest }) => { +const IconCheckmark = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconCheckmark = ({ size, color, style: _style, ...rest }) => { ); }; -IconCheckmark.defaultProps = { - size: 18, -}; - export default IconCheckmark; diff --git a/src/components/iconfont/IconChevronRight.js b/src/components/iconfont/IconChevronRight.js index 3f7b5436..973dac57 100644 --- a/src/components/iconfont/IconChevronRight.js +++ b/src/components/iconfont/IconChevronRight.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconChevronRight = ({ size, color, style: _style, ...rest }) => { +const IconChevronRight = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconChevronRight = ({ size, color, style: _style, ...rest }) => { ); }; -IconChevronRight.defaultProps = { - size: 18, -}; - export default IconChevronRight; diff --git a/src/components/iconfont/IconClose.js b/src/components/iconfont/IconClose.js index cb5d33a6..0493c2d9 100644 --- a/src/components/iconfont/IconClose.js +++ b/src/components/iconfont/IconClose.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconClose = ({ size, color, style: _style, ...rest }) => { +const IconClose = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconClose = ({ size, color, style: _style, ...rest }) => { ); }; -IconClose.defaultProps = { - size: 18, -}; - export default IconClose; diff --git a/src/components/iconfont/IconCoinbase.js b/src/components/iconfont/IconCoinbase.js index 87d94471..91f5110b 100644 --- a/src/components/iconfont/IconCoinbase.js +++ b/src/components/iconfont/IconCoinbase.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconCoinbase = ({ size, color, style: _style, ...rest }) => { +const IconCoinbase = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconCoinbase = ({ size, color, style: _style, ...rest }) => { ); }; -IconCoinbase.defaultProps = { - size: 18, -}; - export default IconCoinbase; diff --git a/src/components/iconfont/IconCopy.js b/src/components/iconfont/IconCopy.js index 6531a5fb..03111486 100644 --- a/src/components/iconfont/IconCopy.js +++ b/src/components/iconfont/IconCopy.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconCopy = ({ size, color, style: _style, ...rest }) => { +const IconCopy = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -25,8 +25,4 @@ const IconCopy = ({ size, color, style: _style, ...rest }) => { ); }; -IconCopy.defaultProps = { - size: 18, -}; - export default IconCopy; diff --git a/src/components/iconfont/IconCreate.js b/src/components/iconfont/IconCreate.js index 6bb709d6..ef0688ce 100644 --- a/src/components/iconfont/IconCreate.js +++ b/src/components/iconfont/IconCreate.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconCreate = ({ size, color, style: _style, ...rest }) => { +const IconCreate = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconCreate = ({ size, color, style: _style, ...rest }) => { ); }; -IconCreate.defaultProps = { - size: 18, -}; - export default IconCreate; diff --git a/src/components/iconfont/IconCurrency.js b/src/components/iconfont/IconCurrency.js index 58de08fe..68cce554 100644 --- a/src/components/iconfont/IconCurrency.js +++ b/src/components/iconfont/IconCurrency.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconCurrency = ({ size, color, style: _style, ...rest }) => { +const IconCurrency = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconCurrency = ({ size, color, style: _style, ...rest }) => { ); }; -IconCurrency.defaultProps = { - size: 18, -}; - export default IconCurrency; diff --git a/src/components/iconfont/IconDeveloper.js b/src/components/iconfont/IconDeveloper.js index ebc5344c..eaba96b1 100644 --- a/src/components/iconfont/IconDeveloper.js +++ b/src/components/iconfont/IconDeveloper.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconDeveloper = ({ size, color, style: _style, ...rest }) => { +const IconDeveloper = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconDeveloper = ({ size, color, style: _style, ...rest }) => { ); }; -IconDeveloper.defaultProps = { - size: 18, -}; - export default IconDeveloper; diff --git a/src/components/iconfont/IconDevices.js b/src/components/iconfont/IconDevices.js index 87a925cd..37cbb89f 100644 --- a/src/components/iconfont/IconDevices.js +++ b/src/components/iconfont/IconDevices.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconDevices = ({ size, color, style: _style, ...rest }) => { +const IconDevices = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconDevices = ({ size, color, style: _style, ...rest }) => { ); }; -IconDevices.defaultProps = { - size: 18, -}; - export default IconDevices; diff --git a/src/components/iconfont/IconDollar.js b/src/components/iconfont/IconDollar.js index bd37c7a5..92c13000 100644 --- a/src/components/iconfont/IconDollar.js +++ b/src/components/iconfont/IconDollar.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconDollar = ({ size, color, style: _style, ...rest }) => { +const IconDollar = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconDollar = ({ size, color, style: _style, ...rest }) => { ); }; -IconDollar.defaultProps = { - size: 18, -}; - export default IconDollar; diff --git a/src/components/iconfont/IconDropdown.js b/src/components/iconfont/IconDropdown.js index 7fe04b6f..14fab4b4 100644 --- a/src/components/iconfont/IconDropdown.js +++ b/src/components/iconfont/IconDropdown.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconDropdown = ({ size, color, style: _style, ...rest }) => { +const IconDropdown = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -17,8 +17,4 @@ const IconDropdown = ({ size, color, style: _style, ...rest }) => { ); }; -IconDropdown.defaultProps = { - size: 18, -}; - export default IconDropdown; diff --git a/src/components/iconfont/IconExec.js b/src/components/iconfont/IconExec.js index 8afcf34c..975eb808 100644 --- a/src/components/iconfont/IconExec.js +++ b/src/components/iconfont/IconExec.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconExec = ({ size, color, style: _style, ...rest }) => { +const IconExec = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconExec = ({ size, color, style: _style, ...rest }) => { ); }; -IconExec.defaultProps = { - size: 18, -}; - export default IconExec; diff --git a/src/components/iconfont/IconEye.js b/src/components/iconfont/IconEye.js index 2ccd6d57..714be98b 100644 --- a/src/components/iconfont/IconEye.js +++ b/src/components/iconfont/IconEye.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconEye = ({ size, color, style: _style, ...rest }) => { +const IconEye = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconEye = ({ size, color, style: _style, ...rest }) => { ); }; -IconEye.defaultProps = { - size: 18, -}; - export default IconEye; diff --git a/src/components/iconfont/IconFlow.js b/src/components/iconfont/IconFlow.js index 78c97680..a03075c0 100644 --- a/src/components/iconfont/IconFlow.js +++ b/src/components/iconfont/IconFlow.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconFlow = ({ size, color, style: _style, ...rest }) => { +const IconFlow = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -28,8 +28,4 @@ const IconFlow = ({ size, color, style: _style, ...rest }) => { ); }; -IconFlow.defaultProps = { - size: 18, -}; - export default IconFlow; diff --git a/src/components/iconfont/IconFlowns.js b/src/components/iconfont/IconFlowns.js index 822144cc..c26eda8e 100644 --- a/src/components/iconfont/IconFlowns.js +++ b/src/components/iconfont/IconFlowns.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconFlowns = ({ size, color, style: _style, ...rest }) => { +const IconFlowns = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -52,8 +52,4 @@ const IconFlowns = ({ size, color, style: _style, ...rest }) => { ); }; -IconFlowns.defaultProps = { - size: 18, -}; - export default IconFlowns; diff --git a/src/components/iconfont/IconFusd.js b/src/components/iconfont/IconFusd.js index ffc39ff2..91252e62 100644 --- a/src/components/iconfont/IconFusd.js +++ b/src/components/iconfont/IconFusd.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconFusd = ({ size, color, style: _style, ...rest }) => { +const IconFusd = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -28,8 +28,4 @@ const IconFusd = ({ size, color, style: _style, ...rest }) => { ); }; -IconFusd.defaultProps = { - size: 18, -}; - export default IconFusd; diff --git a/src/components/iconfont/IconGoogleDrive.js b/src/components/iconfont/IconGoogleDrive.js index 811a104e..6f96c3db 100644 --- a/src/components/iconfont/IconGoogleDrive.js +++ b/src/components/iconfont/IconGoogleDrive.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconGoogleDrive = ({ size, color, style: _style, ...rest }) => { +const IconGoogleDrive = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -28,8 +28,4 @@ const IconGoogleDrive = ({ size, color, style: _style, ...rest }) => { ); }; -IconGoogleDrive.defaultProps = { - size: 18, -}; - export default IconGoogleDrive; diff --git a/src/components/iconfont/IconHuobi.js b/src/components/iconfont/IconHuobi.js index adde9d62..e6a95b36 100644 --- a/src/components/iconfont/IconHuobi.js +++ b/src/components/iconfont/IconHuobi.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconHuobi = ({ size, color, style: _style, ...rest }) => { +const IconHuobi = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconHuobi = ({ size, color, style: _style, ...rest }) => { ); }; -IconHuobi.defaultProps = { - size: 18, -}; - export default IconHuobi; diff --git a/src/components/iconfont/IconImport.js b/src/components/iconfont/IconImport.js index bf624163..22cea085 100644 --- a/src/components/iconfont/IconImport.js +++ b/src/components/iconfont/IconImport.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconImport = ({ size, color, style: _style, ...rest }) => { +const IconImport = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconImport = ({ size, color, style: _style, ...rest }) => { ); }; -IconImport.defaultProps = { - size: 18, -}; - export default IconImport; diff --git a/src/components/iconfont/IconInbox.js b/src/components/iconfont/IconInbox.js index 90e88d24..dc2d9656 100644 --- a/src/components/iconfont/IconInbox.js +++ b/src/components/iconfont/IconInbox.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconInbox = ({ size, color, style: _style, ...rest }) => { +const IconInbox = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconInbox = ({ size, color, style: _style, ...rest }) => { ); }; -IconInbox.defaultProps = { - size: 18, -}; - export default IconInbox; diff --git a/src/components/iconfont/IconKraken.js b/src/components/iconfont/IconKraken.js index 04dca7b1..bf68d044 100644 --- a/src/components/iconfont/IconKraken.js +++ b/src/components/iconfont/IconKraken.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconKraken = ({ size, color, style: _style, ...rest }) => { +const IconKraken = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconKraken = ({ size, color, style: _style, ...rest }) => { ); }; -IconKraken.defaultProps = { - size: 18, -}; - export default IconKraken; diff --git a/src/components/iconfont/IconKucoin.js b/src/components/iconfont/IconKucoin.js index 68be3de6..eafd6e3a 100644 --- a/src/components/iconfont/IconKucoin.js +++ b/src/components/iconfont/IconKucoin.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconKucoin = ({ size, color, style: _style, ...rest }) => { +const IconKucoin = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconKucoin = ({ size, color, style: _style, ...rest }) => { ); }; -IconKucoin.defaultProps = { - size: 18, -}; - export default IconKucoin; diff --git a/src/components/iconfont/IconLock.js b/src/components/iconfont/IconLock.js index cd8cd716..c92334e0 100644 --- a/src/components/iconfont/IconLock.js +++ b/src/components/iconfont/IconLock.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconLock = ({ size, color, style: _style, ...rest }) => { +const IconLock = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconLock = ({ size, color, style: _style, ...rest }) => { ); }; -IconLock.defaultProps = { - size: 18, -}; - export default IconLock; diff --git a/src/components/iconfont/IconLogo.js b/src/components/iconfont/IconLogo.js index 8713afad..f59323cb 100644 --- a/src/components/iconfont/IconLogo.js +++ b/src/components/iconfont/IconLogo.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconLogo = ({ size, color, style: _style, ...rest }) => { +const IconLogo = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -32,8 +32,4 @@ const IconLogo = ({ size, color, style: _style, ...rest }) => { ); }; -IconLogo.defaultProps = { - size: 18, -}; - export default IconLogo; diff --git a/src/components/iconfont/IconMax.js b/src/components/iconfont/IconMax.js index fcb40d36..daf53dba 100644 --- a/src/components/iconfont/IconMax.js +++ b/src/components/iconfont/IconMax.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconMax = ({ size, color, style: _style, ...rest }) => { +const IconMax = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconMax = ({ size, color, style: _style, ...rest }) => { ); }; -IconMax.defaultProps = { - size: 18, -}; - export default IconMax; diff --git a/src/components/iconfont/IconNfts.js b/src/components/iconfont/IconNfts.js index 4d8acf45..8ce2ff0b 100644 --- a/src/components/iconfont/IconNfts.js +++ b/src/components/iconfont/IconNfts.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconNfts = ({ size, color, style: _style, ...rest }) => { +const IconNfts = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconNfts = ({ size, color, style: _style, ...rest }) => { ); }; -IconNfts.defaultProps = { - size: 18, -}; - export default IconNfts; diff --git a/src/components/iconfont/IconNotification.js b/src/components/iconfont/IconNotification.js index f04c17a3..d577f2da 100644 --- a/src/components/iconfont/IconNotification.js +++ b/src/components/iconfont/IconNotification.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconNotification = ({ size, color, style: _style, ...rest }) => { +const IconNotification = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconNotification = ({ size, color, style: _style, ...rest }) => { ); }; -IconNotification.defaultProps = { - size: 18, -}; - export default IconNotification; diff --git a/src/components/iconfont/IconPlayStore.js b/src/components/iconfont/IconPlayStore.js index dc731ff6..63965b68 100644 --- a/src/components/iconfont/IconPlayStore.js +++ b/src/components/iconfont/IconPlayStore.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconPlayStore = ({ size, color, style: _style, ...rest }) => { +const IconPlayStore = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconPlayStore = ({ size, color, style: _style, ...rest }) => { ); }; -IconPlayStore.defaultProps = { - size: 18, -}; - export default IconPlayStore; diff --git a/src/components/iconfont/IconPlus.js b/src/components/iconfont/IconPlus.js index 70469313..a91ca063 100644 --- a/src/components/iconfont/IconPlus.js +++ b/src/components/iconfont/IconPlus.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconPlus = ({ size, color, style: _style, ...rest }) => { +const IconPlus = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconPlus = ({ size, color, style: _style, ...rest }) => { ); }; -IconPlus.defaultProps = { - size: 18, -}; - export default IconPlus; diff --git a/src/components/iconfont/IconSearch.js b/src/components/iconfont/IconSearch.js index 6668ef5d..52b3b311 100644 --- a/src/components/iconfont/IconSearch.js +++ b/src/components/iconfont/IconSearch.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconSearch = ({ size, color, style: _style, ...rest }) => { +const IconSearch = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconSearch = ({ size, color, style: _style, ...rest }) => { ); }; -IconSearch.defaultProps = { - size: 18, -}; - export default IconSearch; diff --git a/src/components/iconfont/IconSecurity.js b/src/components/iconfont/IconSecurity.js index 15ef0a2b..49f62c76 100644 --- a/src/components/iconfont/IconSecurity.js +++ b/src/components/iconfont/IconSecurity.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconSecurity = ({ size, color, style: _style, ...rest }) => { +const IconSecurity = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconSecurity = ({ size, color, style: _style, ...rest }) => { ); }; -IconSecurity.defaultProps = { - size: 18, -}; - export default IconSecurity; diff --git a/src/components/iconfont/IconSetting.js b/src/components/iconfont/IconSetting.js index 52bf6207..1e5da15f 100644 --- a/src/components/iconfont/IconSetting.js +++ b/src/components/iconfont/IconSetting.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconSetting = ({ size, color, style: _style, ...rest }) => { +const IconSetting = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconSetting = ({ size, color, style: _style, ...rest }) => { ); }; -IconSetting.defaultProps = { - size: 18, -}; - export default IconSetting; diff --git a/src/components/iconfont/IconSubtract.js b/src/components/iconfont/IconSubtract.js index 53e66074..1b7d9f29 100644 --- a/src/components/iconfont/IconSubtract.js +++ b/src/components/iconfont/IconSubtract.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconSubtract = ({ size, color, style: _style, ...rest }) => { +const IconSubtract = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconSubtract = ({ size, color, style: _style, ...rest }) => { ); }; -IconSubtract.defaultProps = { - size: 18, -}; - export default IconSubtract; diff --git a/src/components/iconfont/IconSwitch.js b/src/components/iconfont/IconSwitch.js index 2c7c1d4d..c4cc2646 100644 --- a/src/components/iconfont/IconSwitch.js +++ b/src/components/iconfont/IconSwitch.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconSwitch = ({ size, color, style: _style, ...rest }) => { +const IconSwitch = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconSwitch = ({ size, color, style: _style, ...rest }) => { ); }; -IconSwitch.defaultProps = { - size: 18, -}; - export default IconSwitch; diff --git a/src/components/iconfont/IconTheme.js b/src/components/iconfont/IconTheme.js index a8de08ef..e03d8b25 100644 --- a/src/components/iconfont/IconTheme.js +++ b/src/components/iconfont/IconTheme.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconTheme = ({ size, color, style: _style, ...rest }) => { +const IconTheme = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconTheme = ({ size, color, style: _style, ...rest }) => { ); }; -IconTheme.defaultProps = { - size: 18, -}; - export default IconTheme; diff --git a/src/components/iconfont/IconUserSwitch.js b/src/components/iconfont/IconUserSwitch.js index 63ddc41a..54665a09 100644 --- a/src/components/iconfont/IconUserSwitch.js +++ b/src/components/iconfont/IconUserSwitch.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconUserSwitch = ({ size, color, style: _style, ...rest }) => { +const IconUserSwitch = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -24,8 +24,4 @@ const IconUserSwitch = ({ size, color, style: _style, ...rest }) => { ); }; -IconUserSwitch.defaultProps = { - size: 18, -}; - export default IconUserSwitch; diff --git a/src/components/iconfont/IconVector.js b/src/components/iconfont/IconVector.js index a5b3099c..391d97f0 100644 --- a/src/components/iconfont/IconVector.js +++ b/src/components/iconfont/IconVector.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconVector = ({ size, color, style: _style, ...rest }) => { +const IconVector = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconVector = ({ size, color, style: _style, ...rest }) => { ); }; -IconVector.defaultProps = { - size: 18, -}; - export default IconVector; diff --git a/src/components/iconfont/IconVector2.js b/src/components/iconfont/IconVector2.js index 8a8bd407..9e445211 100644 --- a/src/components/iconfont/IconVector2.js +++ b/src/components/iconfont/IconVector2.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconVector2 = ({ size, color, style: _style, ...rest }) => { +const IconVector2 = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconVector2 = ({ size, color, style: _style, ...rest }) => { ); }; -IconVector2.defaultProps = { - size: 18, -}; - export default IconVector2; diff --git a/src/components/iconfont/IconWallet.js b/src/components/iconfont/IconWallet.js index 0ea9dbf7..b7364401 100644 --- a/src/components/iconfont/IconWallet.js +++ b/src/components/iconfont/IconWallet.js @@ -7,7 +7,7 @@ const DEFAULT_STYLE = { display: 'block', }; -const IconWallet = ({ size, color, style: _style, ...rest }) => { +const IconWallet = ({ size = 18, color, style: _style, ...rest }) => { const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE; return ( @@ -20,8 +20,4 @@ const IconWallet = ({ size, color, style: _style, ...rest }) => { ); }; -IconWallet.defaultProps = { - size: 18, -}; - export default IconWallet; diff --git a/src/components/iconfont/helper.d.ts b/src/components/iconfont/helper.d.ts index 2154aa77..6c424df6 100644 --- a/src/components/iconfont/helper.d.ts +++ b/src/components/iconfont/helper.d.ts @@ -1,5 +1,3 @@ -/* eslint-disable */ - export declare const getIconColor: ( color: string | string[] | undefined, index: number, diff --git a/src/components/iconfont/helper.js b/src/components/iconfont/helper.js index a5970315..2e8a144a 100644 --- a/src/components/iconfont/helper.js +++ b/src/components/iconfont/helper.js @@ -1,5 +1,3 @@ -/* eslint-disable */ - /** * @param {string | string[] | undefined} color * @param {number} index diff --git a/src/components/iconfont/index.d.ts b/src/components/iconfont/index.d.ts index b5dacae8..b02360f0 100644 --- a/src/components/iconfont/index.d.ts +++ b/src/components/iconfont/index.d.ts @@ -34,7 +34,7 @@ export { default as IconAbout } from './IconAbout'; export { default as IconCreate } from './IconCreate'; export { default as IconLock } from './IconLock'; export { default as IconUserSwitch } from './IconUserSwitch'; -export { default as IconAddressBook } from './IconAddressBook'; +export { default as IconAddressbook } from './IconAddressbook'; export { default as IconAVector11Stroke } from './IconAVector11Stroke'; export { default as IconMax } from './IconMax'; export { default as IconVector2 } from './IconVector2'; diff --git a/src/components/iconfont/index.js b/src/components/iconfont/index.js index ee3eab15..4036a8a7 100644 --- a/src/components/iconfont/index.js +++ b/src/components/iconfont/index.js @@ -34,7 +34,7 @@ import IconAbout from './IconAbout'; import IconCreate from './IconCreate'; import IconLock from './IconLock'; import IconUserSwitch from './IconUserSwitch'; -import IconAddressBook from './IconAddressBook'; +import IconAddressbook from './IconAddressbook'; import IconAVector11Stroke from './IconAVector11Stroke'; import IconMax from './IconMax'; import IconVector2 from './IconVector2'; @@ -85,7 +85,7 @@ export { default as IconAbout } from './IconAbout'; export { default as IconCreate } from './IconCreate'; export { default as IconLock } from './IconLock'; export { default as IconUserSwitch } from './IconUserSwitch'; -export { default as IconAddressBook } from './IconAddressBook'; +export { default as IconAddressbook } from './IconAddressbook'; export { default as IconAVector11Stroke } from './IconAVector11Stroke'; export { default as IconMax } from './IconMax'; export { default as IconVector2 } from './IconVector2'; @@ -173,7 +173,7 @@ const IconFont = ({ name, ...rest }) => { case 'User-switch': return ; case 'Address-book': - return ; + return ; case 'a-Vector11Stroke': return ; case 'max': diff --git a/src/content-script/index.ts b/src/content-script/index.ts index c4c6248c..0eebe0dd 100644 --- a/src/content-script/index.ts +++ b/src/content-script/index.ts @@ -1,7 +1,8 @@ import { nanoid } from 'nanoid'; -import { Message } from 'utils'; import { v4 as uuid } from 'uuid'; +import { Message } from '@/shared/utils/messaging'; + const channelName = nanoid(); const injectProviderScript = async (isDefaultWallet) => { @@ -10,8 +11,6 @@ const injectProviderScript = async (isDefaultWallet) => { await localStorage.setItem('frw:isDefaultWallet', isDefaultWallet); await localStorage.setItem('frw:uuid', uuid()); - console.log(localStorage.getItem('frw:channelName')); - const container = document.head || document.documentElement; const scriptElement = document.createElement('script'); scriptElement.id = 'injectedScript'; @@ -79,37 +78,41 @@ window.addEventListener('message', function (event) { // chrome.runtime.sendMessage({type: 'FLOW::TX', ...event.detail}) // }) -const extMessageHandler = (msg, sender) => { +const extMessageHandler = (msg, _sender) => { if (msg.type === 'FCL:VIEW:READY') { - window && window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + if (window) { + window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + } } if (msg.f_type && msg.f_type === 'PollingResponse') { - window && - window.postMessage( - JSON.parse(JSON.stringify({ ...msg, type: 'FCL:VIEW:RESPONSE' } || {})), - '*' - ); + if (window) { + window.postMessage(JSON.parse(JSON.stringify({ ...msg, type: 'FCL:VIEW:RESPONSE' })), '*'); + } } if (msg.data?.f_type && msg.data?.f_type === 'PreAuthzResponse') { - window && - window.postMessage( - JSON.parse(JSON.stringify({ ...msg, type: 'FCL:VIEW:RESPONSE' } || {})), - '*' - ); + if (window) { + window.postMessage(JSON.parse(JSON.stringify({ ...msg, type: 'FCL:VIEW:RESPONSE' })), '*'); + } } if (msg.type === 'FCL:VIEW:CLOSE') { - window && window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + if (window) { + window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + } } if (msg.type === 'FLOW::TX') { - window && window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + if (window) { + window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + } } if (msg.type === 'LILICO:NETWORK') { - window && window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + if (window) { + window.postMessage(JSON.parse(JSON.stringify(msg || {})), '*'); + } } return true; diff --git a/src/content-script/pageProvider/eth/index.ts b/src/content-script/pageProvider/eth/index.ts index 8cb47774..e7995640 100644 --- a/src/content-script/pageProvider/eth/index.ts +++ b/src/content-script/pageProvider/eth/index.ts @@ -1,13 +1,15 @@ // this script is injected into webpage's context import { EventEmitter } from 'events'; + import { ethErrors, serializeError } from 'eth-rpc-errors'; -import BroadcastChannelMessage from './utils/message/broadcastChannelMessage'; -import PushEventHandlers from './pageProvider/pushEventHandlers'; -import { domReadyCall, $ } from './pageProvider/utils'; -import ReadyPromise from './pageProvider/readyPromise'; + import DedupePromise from './pageProvider/dedupePromise'; import { switchChainNotice } from './pageProvider/interceptors/switchChain'; import { switchWalletNotice } from './pageProvider/interceptors/switchWallet'; +import PushEventHandlers from './pageProvider/pushEventHandlers'; +import ReadyPromise from './pageProvider/readyPromise'; +import { domReadyCall, $ } from './pageProvider/utils'; +import BroadcastChannelMessage from './utils/message/broadcastChannelMessage'; import { getProviderMode, patchProvider } from './utils/metamask'; declare const __frw__channelName; diff --git a/src/content-script/pageProvider/eth/pageProvider/interceptors/switchChain.ts b/src/content-script/pageProvider/eth/pageProvider/interceptors/switchChain.ts index 2e284605..396644c3 100644 --- a/src/content-script/pageProvider/eth/pageProvider/interceptors/switchChain.ts +++ b/src/content-script/pageProvider/eth/pageProvider/interceptors/switchChain.ts @@ -1,8 +1,8 @@ +import IconArrow from '../../assets/arrow.svg'; import IconFlow from '../../assets/flow.svg'; import IconWarning from '../../assets/warning.svg'; -import IconArrow from '../../assets/arrow.svg'; -import notice from '../notice'; import { isInSameOriginIframe } from '../../utils/iframe'; +import notice from '../notice'; let instance: ReturnType | null; diff --git a/src/content-script/pageProvider/eth/pageProvider/interceptors/switchWallet.ts b/src/content-script/pageProvider/eth/pageProvider/interceptors/switchWallet.ts index 4f80dde8..a8ac76e8 100644 --- a/src/content-script/pageProvider/eth/pageProvider/interceptors/switchWallet.ts +++ b/src/content-script/pageProvider/eth/pageProvider/interceptors/switchWallet.ts @@ -1,8 +1,9 @@ -import IconMetamask from '../../assets/metamask.svg'; +import { flow } from 'lodash'; + import IconFlow from '../../assets/flow.svg'; -import notice from '../notice'; +import IconMetamask from '../../assets/metamask.svg'; import { isInSameOriginIframe } from '../../utils/iframe'; -import { flow } from 'lodash'; +import notice from '../notice'; let instance: ReturnType | null; diff --git a/src/content-script/pageProvider/eth/pageProvider/pushEventHandlers.ts b/src/content-script/pageProvider/eth/pageProvider/pushEventHandlers.ts index ef44ba58..48c80e6f 100644 --- a/src/content-script/pageProvider/eth/pageProvider/pushEventHandlers.ts +++ b/src/content-script/pageProvider/eth/pageProvider/pushEventHandlers.ts @@ -1,5 +1,6 @@ import { ethErrors } from 'eth-rpc-errors'; -import { EthereumProvider } from '../index'; + +import { type EthereumProvider } from '../index'; class PushEventHandlers { provider: EthereumProvider; diff --git a/src/content-script/pageProvider/eth/utils/message/portMessage.ts b/src/content-script/pageProvider/eth/utils/message/portMessage.ts index 77a0e651..43960cd8 100644 --- a/src/content-script/pageProvider/eth/utils/message/portMessage.ts +++ b/src/content-script/pageProvider/eth/utils/message/portMessage.ts @@ -1,8 +1,8 @@ -import browser, { Runtime } from 'webextension-polyfill'; +import browser, { type Runtime } from 'webextension-polyfill'; + import Message from './index'; class PortMessage extends Message { port: Runtime.Port | null = null; - listenCallback: any; constructor(port?: Runtime.Port) { super(); diff --git a/src/content-script/script.js b/src/content-script/script.js index d1244d89..055c9116 100644 --- a/src/content-script/script.js +++ b/src/content-script/script.js @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck import { WalletUtils } from '@onflow/fcl'; // import { nanoid } from 'nanoid'; diff --git a/src/eventBus.ts b/src/eventBus.ts index c6598bde..0ef4ae48 100644 --- a/src/eventBus.ts +++ b/src/eventBus.ts @@ -1,5 +1,9 @@ type Listener = (params?: any) => void; - +/** + * EventBus is a singleton class that allows for event-based communication between different parts of the application. + * It provides methods for emitting events, listening for events, and removing event listeners. + * IMPORTANT: This only works in one thread - either the background, content script, or UI. It does not work across threads. + */ class EventBus { events: Record = {}; diff --git a/src/shared/types/algo-types.ts b/src/shared/types/algo-types.ts new file mode 100644 index 00000000..707e68de --- /dev/null +++ b/src/shared/types/algo-types.ts @@ -0,0 +1,3 @@ +export type SignAlgoType = 'ECDSA_P256' | 'ECDSA_secp256k1' | 'unknown'; + +export type HashAlgoType = 'SHA256' | 'SHA2_256' | 'SHA3_256' | 'SHA2_384' | 'SHA3_384' | 'unknown'; diff --git a/src/shared/types/tracking-types.ts b/src/shared/types/tracking-types.ts new file mode 100644 index 00000000..4a8bbf2f --- /dev/null +++ b/src/shared/types/tracking-types.ts @@ -0,0 +1,129 @@ +import type { HashAlgoType, SignAlgoType } from './algo-types'; + +type OnRampSourceType = 'moonpay' | 'coinbase'; + +type KeyType = 'passkey' | 'google_drive' | 'seed_phrase' | 'keystore' | 'private_key'; + +type RecoveryMechanismType = + | 'multi-backup' + | 'seed-phrase' + | 'private_key' + | 'KeyStore' + | 'device_backup'; + +type AddressType = 'flow' | 'evm' | 'child' | 'coa'; + +export type TrackingEvents = { + // General Events + script_error: { + error: string; // Error message of the script, e.g., Rate limit exceeded + script_id: string; // Script name from script API, e.g. checkCoaLink + }; + delegation_created: { + address: string; // Address of the account that delegated + node_id: string; // ID of the node that was delegated to + amount: number; // Amount of FLOW. e.g. 200.12 + }; + on_ramp_clicked: { + source: OnRampSourceType; // The on ramp platform the user choose e.g. moonpay or coinbase + }; + coa_creation: { + tx_id: string; // The transaction ID + flow_address: string; // + error_message?: string; // Any error message + }; + security_tool: { + type: 'biometric' | 'pin' | 'none'; + }; + + // Backup Events + multi_backup_created: { + address: string; // Address of the account that set up multi-backup + providers: KeyType[]; // Providers used in the multi-backup, GoogleDrive, iCloud, Seed e.g. google_drive icloud seed_phrase + }; + multi_backup_creation_failed: { + address: string; // Address of the account that set up multi-backup + providers: KeyType[]; // Providers used in the multi-backup, GoogleDrive, iCloud, Seed e.g. google_drive icloud seed_phrase + }; + + // Transaction Events + + cadence_transaction_signed: { + cadence: string; // SHA256 Hashed Cadence that was signed. + tx_id: string; // String of the transaction ID. + authorizers: string[]; // Comma separated list of authorizer account address in the transaction + proposer: string; // Address of the transactions proposer. + payer: string; // Payer of the transaction. + success: boolean; // Boolean of if the transaction was sent successful or not. true/false + }; + evm_transaction_signed: { + success: boolean; // Boolean of if the transaction was sent successful or not. true/false + flow_address: string; // Address of the account that signed the transaction + evm_address: string; // EVM Address of the account that signed the transaction + tx_id: string; // transaction id + }; + ft_transfer: { + from_address: string; // Address of the account that transferred the FT + to_address: string; // Address of the account that received the FT + type: string; // Type of FT sent (e.g., "FLOW", "USDf") + amount: number; // The amount of FT + ft_identifier: string; // The identifier of fungible token + }; + nft_transfer: { + from_address: string; // Address of the account that transferred the FT + to_address: string; // Address of the account that received the FT + nft_identifier: string; // The identifier of non fungible token + tx_id: string; // ID of the NFT that was transferred + from_type: AddressType; // The type of from address whether it's flow, child account, coa or evm account. + to_type: AddressType; // The type of to address whether it's flow, child account, coa or evm account. + isMove: boolean; // The transfer flow is triggerred from Move account + }; + + transaction_result: { + tx_id: string; // The transaction id + is_successful: boolean; // If the transaction is successful + error_message?: string; // Error message of transaction + }; + // Account Events + account_created: { + public_key: string; // The public key used for creating the new account + key_type?: KeyType; // The key type of the account (if available) + sign_algo: SignAlgoType; // Signature algorithm of the key + hash_algo: HashAlgoType; // Hash algo Hash algorithm of the key + }; + + account_creation_time: { + // Timing Events + }; + account_recovered: { + address: string; // Address that was recovered + mechanism: RecoveryMechanismType; // The way the account was recovered + methods: KeyType[]; // Array of providers used in the multi-backup, GoogleDrive, iCloud, Seed + }; +}; + +export type TrackEventMessage = { + msg: 'track_event'; + eventName: T; + properties?: TrackingEvents[T]; +}; + +export type TrackUserMessage = { + msg: 'track_user'; + userId: string; +}; + +export type TrackResetMessage = { + msg: 'track_reset'; +}; + +export type TrackTimeMessage = { + msg: 'track_time'; + eventName: keyof TrackingEvents; +}; + +export type TrackMessage = + | TrackEventMessage + | TrackUserMessage + | TrackResetMessage + | TrackTimeMessage; diff --git a/src/ui/utils/address.ts b/src/shared/utils/address.ts similarity index 83% rename from src/ui/utils/address.ts rename to src/shared/utils/address.ts index 5d32d334..f77eceaf 100644 --- a/src/ui/utils/address.ts +++ b/src/shared/utils/address.ts @@ -1,13 +1,14 @@ -import { AccountKey } from 'background/service/networkModel'; import HDWallet from 'ethereum-hdwallet'; +import { type AccountKey } from 'background/service/networkModel'; + export function sansPrefix(address) { - if (address == null) return null; + if (!address) return null; return address.replace(/^0x/, '').replace(/^Fx/, ''); } export function withPrefix(address): string | null { - if (address == null) return null; + if (!address) return null; return '0x' + sansPrefix(address); } @@ -32,6 +33,11 @@ export const isValidEthereumAddress = (address) => { return regex.test(address); }; +export const isValidFlowAddress = (address) => { + const regex = /^(0x)?[0-9a-fA-F]{16}$/; + return regex.test(address); +}; + export const ensureEvmAddressPrefix = (address) => { const cleanAddress = address.startsWith('0x') ? address.slice(2) : address; diff --git a/src/shared/utils/algo.ts b/src/shared/utils/algo.ts new file mode 100644 index 00000000..d2565401 --- /dev/null +++ b/src/shared/utils/algo.ts @@ -0,0 +1,65 @@ +import type { HashAlgoType, SignAlgoType } from '@/shared/types/algo-types'; + +export function getHashAlgo(value: string): number { + switch (value) { + case 'unknown': + return 0; + case 'SHA2_256': + return 1; + case 'SHA2_384': + return 2; + case 'SHA3_256': + return 3; + case 'SHA3_384': + return 4; + default: + return -1; // Handle unknown values + } +} + +export function getSignAlgo(value: string): number { + switch (value) { + case 'unknown': + return 0; + case 'ECDSA_P256': + return 1; + case 'ECDSA_p256': + return 1; + case 'ECDSA_SECP256k1': + return 2; + case 'ECDSA_secp256k1': + return 2; + default: + return -1; // Handle unknown values + } +} + +export function getStringFromHashAlgo(value: number): HashAlgoType { + switch (value) { + case 0: + return 'unknown'; + case 1: + return 'SHA2_256'; + case 2: + return 'SHA2_384'; + case 3: + return 'SHA3_256'; + case 4: + return 'SHA3_384'; + default: + return 'unknown'; // Handle unknown values + } +} + +export function getStringFromSignAlgo(value: number): SignAlgoType { + switch (value) { + case 0: + return 'unknown'; + case 1: + return 'ECDSA_P256'; + case 2: + return 'ECDSA_secp256k1'; + default: + return 'unknown'; // Handle unknown values + } +} diff --git a/src/shared/utils/getPeriodFrequency.ts b/src/shared/utils/getPeriodFrequency.ts new file mode 100644 index 00000000..94db5532 --- /dev/null +++ b/src/shared/utils/getPeriodFrequency.ts @@ -0,0 +1,20 @@ +import { Period, PeriodFrequency } from '@/background/service/networkModel'; + +export const getPeriodFrequency = (period: Period): PeriodFrequency => { + switch (period) { + case Period.oneDay: + return PeriodFrequency.halfHour; + case Period.oneWeek: + return PeriodFrequency.oneHour; + case Period.oneMonth: + return PeriodFrequency.oneDay; + case Period.threeMonth: + return PeriodFrequency.oneDay; + case Period.oneYear: + return PeriodFrequency.threeDay; + case Period.all: + return PeriodFrequency.oneWeek; + default: + return PeriodFrequency.oneDay; + } +}; diff --git a/src/utils/message/broadcastChannelMessage.ts b/src/shared/utils/message/broadcastChannelMessage.ts similarity index 100% rename from src/utils/message/broadcastChannelMessage.ts rename to src/shared/utils/message/broadcastChannelMessage.ts diff --git a/src/utils/message/index.ts b/src/shared/utils/message/index.ts similarity index 100% rename from src/utils/message/index.ts rename to src/shared/utils/message/index.ts diff --git a/src/utils/message/portMessage.ts b/src/shared/utils/message/portMessage.ts similarity index 98% rename from src/utils/message/portMessage.ts rename to src/shared/utils/message/portMessage.ts index ceabf70f..dc69046b 100644 --- a/src/utils/message/portMessage.ts +++ b/src/shared/utils/message/portMessage.ts @@ -1,7 +1,6 @@ import Message from './index'; class PortMessage extends Message { port: chrome.runtime.Port | null = null; - listenCallback: any; constructor(port?: chrome.runtime.Port) { super(); diff --git a/src/shared/utils/messaging.ts b/src/shared/utils/messaging.ts new file mode 100644 index 00000000..8e3ad4a2 --- /dev/null +++ b/src/shared/utils/messaging.ts @@ -0,0 +1,9 @@ +import BroadcastChannelMessage from './message/broadcastChannelMessage'; +import PortMessage from './message/portMessage'; + +const Message = { + BroadcastChannelMessage, + PortMessage, +}; + +export { Message }; diff --git a/src/ui/FRWAssets/icons/CustomCheckboxIcons.tsx b/src/ui/FRWAssets/icons/CustomCheckboxIcons.tsx new file mode 100644 index 00000000..98bec5a1 --- /dev/null +++ b/src/ui/FRWAssets/icons/CustomCheckboxIcons.tsx @@ -0,0 +1,36 @@ +import { styled } from '@mui/material'; + +export const BpIcon = styled('span')(() => ({ + borderRadius: 8, + width: '21px !important', + height: '21px !important', + opacity: 1, + visibility: 'visible', +})); + +export const BpUncheked = styled(BpIcon)({ + borderRadius: 8, + width: 21, + height: 21, + display: 'block', + border: '1px solid #41CC5D', + opacity: 1, +}); + +export const BpCheckedIcon = styled(BpIcon)({ + backgroundColor: '#41CC5D', + backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', + '&:before': { + display: 'block', + width: 21, + height: 21, + backgroundImage: + "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + + " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + + "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", + content: '""', + }, + 'input:hover ~ &': { + backgroundColor: '#41CC5D', + }, +}); diff --git a/src/ui/FRWAssets/image/crown.png b/src/ui/FRWAssets/image/crown.png new file mode 100644 index 00000000..3e15d6c0 Binary files /dev/null and b/src/ui/FRWAssets/image/crown.png differ diff --git a/src/ui/FRWAssets/svg/crown.svg b/src/ui/FRWAssets/svg/crown.svg deleted file mode 100644 index cb9cea9f..00000000 --- a/src/ui/FRWAssets/svg/crown.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/ui/FRWAssets/svg/planetr.svg b/src/ui/FRWAssets/svg/planetr.svg deleted file mode 100644 index bc228c64..00000000 --- a/src/ui/FRWAssets/svg/planetr.svg +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ui/FRWComponent/Confetti.tsx b/src/ui/FRWComponent/Confetti.tsx new file mode 100644 index 00000000..6fb5cca9 --- /dev/null +++ b/src/ui/FRWComponent/Confetti.tsx @@ -0,0 +1,171 @@ +import Particles, { initParticlesEngine, type IParticlesProps } from '@tsparticles/react'; +import React, { useEffect, useRef } from 'react'; +import { loadFull } from 'tsparticles'; + +const CONFETTI_OPTIONS: IParticlesProps['options'] = { + fullScreen: { + zIndex: 1, + }, + emitters: [ + { + direction: 'bottom', + startCount: 0, + position: { x: 50, y: 0 }, + size: { + width: 20, + height: 0, + }, + rate: { + delay: 0, + quantity: 2, + }, + life: { + count: 200, + duration: 0.01, + // delay: 0.6, + }, + }, + ], + particles: { + number: { + value: 250, + }, + color: { + value: ['#9146FF', '#FFAAA8', '#8FFFD2', '#FFD37A', '#FF38DB'], + }, + shape: { + type: ['square', 'circle', 'heart'], + options: {}, + }, + opacity: { + value: { + min: 0, + max: 1, + }, + animation: { + enable: true, + speed: 0.5, + startValue: 'max', + destroy: 'min', + }, + }, + size: { + value: { + min: 2, + max: 5, + }, + }, + links: { + enable: false, + }, + life: { + duration: { + sync: true, + value: 10, + }, + count: 1, + }, + move: { + angle: { + value: 45, + offset: 0, + }, + drift: { + min: -0, + max: 0, + }, + enable: true, + gravity: { + enable: true, + acceleration: 20, + }, + speed: { + min: 20, + max: 90, + }, + decay: 0.1, + //direction: 'left', + straight: false, + outModes: { + default: 'none', + bottom: 'destroy', + }, + }, + rotate: { + value: { + min: 0, + max: 360, + }, + direction: 'random', + move: true, + animation: { + enable: true, + speed: 60, + }, + }, + tilt: { + direction: 'random', + enable: true, + move: true, + value: { + min: 0, + max: 360, + }, + animation: { + enable: true, + speed: 60, + }, + }, + roll: { + darken: { + enable: true, + value: 25, + }, + enable: true, + speed: { + min: 15, + max: 25, + }, + }, + wobble: { + distance: 20, + enable: true, + move: true, + speed: { + min: -15, + max: 15, + }, + }, + }, +}; + +export const useParticlesInit = () => { + const initRef = useRef | null | boolean>(false); + + useEffect(() => { + if (!initRef.current) { + initRef.current = initParticlesEngine(async (engine) => { + await loadFull(engine); + }).then(() => { + return true; + }); + } + }, []); + + return !!initRef.current; +}; + +// Confetti component +// This is using the particles library. +// It would be a good idea to replace it with react-confetti +const Confetti = () => { + const isInitialized = useParticlesInit(); + + if (!isInitialized) { + return null; + } + console.log('Confetti'); + return ; +}; + +export default Confetti; diff --git a/src/ui/FRWComponent/CredentialBox.tsx b/src/ui/FRWComponent/CredentialBox.tsx index bc25e722..4a9c6567 100644 --- a/src/ui/FRWComponent/CredentialBox.tsx +++ b/src/ui/FRWComponent/CredentialBox.tsx @@ -1,6 +1,7 @@ -import React from 'react'; -import { styled } from '@mui/material/styles'; import { Box, Grid, IconButton, Typography } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import React from 'react'; + import IconCopy from '../../components/iconfont/IconCopy'; export const CredentialBox = ({ data }) => { diff --git a/src/ui/FRWComponent/FRWChildProfile.tsx b/src/ui/FRWComponent/FRWChildProfile.tsx index a902e425..df9aa928 100644 --- a/src/ui/FRWComponent/FRWChildProfile.tsx +++ b/src/ui/FRWComponent/FRWChildProfile.tsx @@ -1,29 +1,11 @@ -import React, { useState, useEffect } from 'react'; -import { - Box, - Typography, - Avatar, - Skeleton, - Select, - MenuItem, - FormControl, - InputLabel, -} from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; -import { makeStyles } from '@mui/styles'; -import { useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; +import { Box, Typography, Avatar } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; -const tempEmoji = { - emoji: '🥥', - name: 'Coconut', - bgcolor: '#FFE4C4', -}; +import { isValidEthereumAddress } from '@/shared/utils/address'; +import { useWallet } from 'ui/utils'; export const FRWChildProfile = ({ contact, address, isLoading = false }) => { const usewallet = useWallet(); - const [emoji, setEmoji] = useState(tempEmoji); const getName = (name: string) => { if (!name) { @@ -36,21 +18,8 @@ export const FRWChildProfile = ({ contact, address, isLoading = false }) => { } }; - const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); - if (isValidEthereumAddress(contact.address)) { - setEmoji(emojiList[1]); - } else { - setEmoji(emojiList[0]); - } - }; - - useEffect(() => { - getEmoji(); - }, [contact]); - return ( - + <> { - + ); }; diff --git a/src/ui/FRWComponent/FRWDropdownProfileCard.tsx b/src/ui/FRWComponent/FRWDropdownProfileCard.tsx index 34908407..7f28c8c0 100644 --- a/src/ui/FRWComponent/FRWDropdownProfileCard.tsx +++ b/src/ui/FRWComponent/FRWDropdownProfileCard.tsx @@ -1,4 +1,3 @@ -import React, { useState, useEffect } from 'react'; import { Box, Typography, @@ -9,17 +8,11 @@ import { FormControl, InputLabel, } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; import { makeStyles } from '@mui/styles'; -import { useWallet, formatAddress, isEmoji } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; +import React, { useState, useEffect, useCallback } from 'react'; -const tempEmoji = { - emoji: '🥥', - name: 'Coconut', - bgcolor: '#FFE4C4', -}; +import { isValidEthereumAddress } from '@/shared/utils/address'; +import { useWallet, formatAddress, isEmoji } from 'ui/utils'; export const FRWDropdownProfileCard = ({ contact, @@ -28,7 +21,6 @@ export const FRWDropdownProfileCard = ({ isLoading = false, }) => { const usewallet = useWallet(); - const [emoji, setEmoji] = useState(tempEmoji); const contactKeys = Object.keys(contacts); const [selectedChild, setSelectedChild] = React.useState( @@ -62,21 +54,8 @@ export const FRWDropdownProfileCard = ({ } }; - const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); - if (isValidEthereumAddress(contact.address)) { - setEmoji(emojiList[1]); - } else { - setEmoji(emojiList[0]); - } - }; - - useEffect(() => { - getEmoji(); - }, [contact]); - return ( - + <> - + ); }; diff --git a/src/ui/FRWComponent/FRWProfile.tsx b/src/ui/FRWComponent/FRWProfile.tsx index 73ecfb5a..13daa155 100644 --- a/src/ui/FRWComponent/FRWProfile.tsx +++ b/src/ui/FRWComponent/FRWProfile.tsx @@ -1,35 +1,50 @@ -import React, { useState, useEffect } from 'react'; import { Box, Typography, Avatar, Skeleton } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; + import { useWallet, formatAddress, isEmoji } from 'ui/utils'; const tempEmoji = { emoji: '🥥', - name: 'Coconut', - bgcolor: '#FFE4C4', + name: '', + bgcolor: '', }; -export const FRWProfile = ({ contact, isLoading = false, isEvm = false }) => { +export const FRWProfile = ({ contact, isLoading = false, isEvm = false, fromEvm = '1' }) => { const usewallet = useWallet(); const [emoji, setEmoji] = useState(tempEmoji); + const [isload, setLoad] = useState(true); - const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); + const getEmoji = useCallback(async () => { + setLoad(true); if (isEvm) { - setEmoji(emojiList[1]); + const currentWallet = await usewallet.getEvmWallet(); + console.log('getEvmWallet ', currentWallet); + const emojiObject = tempEmoji; + emojiObject.emoji = currentWallet.icon; + emojiObject.name = currentWallet.name; + emojiObject.bgcolor = currentWallet.color; + emojiObject['type'] = 'evm'; + setEmoji(emojiObject); + setLoad(false); } else { - setEmoji(emojiList[0]); + const currentWallet = await usewallet.getCurrentWallet(); + const emojiObject = tempEmoji; + emojiObject.emoji = currentWallet.icon; + emojiObject.name = currentWallet.name; + emojiObject.bgcolor = currentWallet.color; + emojiObject['type'] = 'parent'; + setEmoji(emojiObject); + setLoad(false); } - }; + }, [isEvm, usewallet]); useEffect(() => { getEmoji(); - }, [contact]); + }, [contact, getEmoji]); return ( - + <> { alignItems: 'center', }} > - {!isLoading ? ( + {!isLoading && !isload ? ( { ) : ( )} - {!isLoading ? ( + {!isLoading && !isload ? ( {isEmoji(contact.avatar) ? contact.contact_name : emoji.name} @@ -66,7 +81,7 @@ export const FRWProfile = ({ contact, isLoading = false, isEvm = false }) => { )} - {!isLoading ? ( + {!isLoading && !isload ? ( { )} - + ); }; diff --git a/src/ui/FRWComponent/FRWProfileCard.tsx b/src/ui/FRWComponent/FRWProfileCard.tsx index 095f9376..d63299de 100644 --- a/src/ui/FRWComponent/FRWProfileCard.tsx +++ b/src/ui/FRWComponent/FRWProfileCard.tsx @@ -1,10 +1,9 @@ -import React, { useState, useEffect } from 'react'; import { Box, Typography, Avatar, Skeleton } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; + +import { isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; const tempEmoji = { emoji: '🥥', @@ -27,21 +26,32 @@ export const FRWProfileCard = ({ contact, isEvm = false, isLoading = false }) => } }; - const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); + const getEmoji = useCallback(async () => { if (isValidEthereumAddress(contact.address)) { - setEmoji(emojiList[1]); + const currentWallet = await usewallet.getEvmWallet(); + const emojiObject = tempEmoji; + emojiObject.emoji = currentWallet.icon; + emojiObject.name = currentWallet.name; + emojiObject.bgcolor = currentWallet.color; + emojiObject['type'] = 'evm'; + setEmoji(emojiObject); } else { - setEmoji(emojiList[0]); + const currentWallet = await usewallet.getCurrentWallet(); + const emojiObject = tempEmoji; + emojiObject.emoji = currentWallet.icon; + emojiObject.name = currentWallet.name; + emojiObject.bgcolor = currentWallet.color; + emojiObject['type'] = 'parent'; + setEmoji(emojiObject); } - }; + }, [contact, usewallet]); useEffect(() => { getEmoji(); - }, [contact]); + }, [contact, getEmoji]); return ( - + <> - + ); }; diff --git a/src/ui/FRWComponent/FRWTargetProfile.tsx b/src/ui/FRWComponent/FRWTargetProfile.tsx new file mode 100644 index 00000000..6f1594c1 --- /dev/null +++ b/src/ui/FRWComponent/FRWTargetProfile.tsx @@ -0,0 +1,103 @@ +import { Box, Typography, Avatar, Skeleton } from '@mui/material'; +import { ThemeProvider } from '@mui/material/styles'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; + +import { useWallet, formatAddress, isEmoji } from 'ui/utils'; + +import theme from '../style/LLTheme'; + +const tempEmoji = { + emoji: '🥥', + name: '', + bgcolor: '', +}; + +export const FRWTargetProfile = ({ contact, isLoading = false, isEvm = false, fromEvm = '1' }) => { + const usewallet = useWallet(); + const [emoji, setEmoji] = useState(tempEmoji); + const [isload, setLoad] = useState(true); + + const getEmoji = useCallback(async () => { + setLoad(true); + if (isEvm) { + const currentWallet = await usewallet.getEvmWallet(); + const emojiObject = { + ...tempEmoji, + emoji: currentWallet.icon, + name: currentWallet.name, + bgcolor: currentWallet.color, + type: 'evm', + }; + setEmoji(emojiObject); + } else { + const currentWallet = await usewallet.getCurrentWallet(); + const emojiObject = { + ...tempEmoji, + emoji: currentWallet.icon, + name: currentWallet.name, + bgcolor: currentWallet.color, + type: 'parent', + }; + setEmoji(emojiObject); + } + setLoad(false); + }, [isEvm, usewallet]); + + useEffect(() => { + getEmoji(); + }, [getEmoji]); + + return ( + + + {!isLoading && !isload ? ( + + + {isEmoji(contact.avatar) ? contact.avatar : emoji.emoji} + + + ) : ( + + )} + {!isLoading && !isload ? ( + + {isEmoji(contact.avatar) ? contact.contact_name : emoji.name} + + ) : ( + + )} + + {!isLoading && !isload ? ( + + {`${formatAddress(contact.address)}`} + + ) : ( + + )} + + + + ); +}; diff --git a/src/ui/FRWComponent/FWContactCard.tsx b/src/ui/FRWComponent/FWContactCard.tsx index 1936198e..eccc6ddd 100644 --- a/src/ui/FRWComponent/FWContactCard.tsx +++ b/src/ui/FRWComponent/FWContactCard.tsx @@ -1,13 +1,12 @@ -import React, { useState } from 'react'; -import { Box, Typography, Avatar, IconButton, CardMedia, Skeleton } from '@mui/material'; -import { useWallet, formatAddress } from 'ui/utils'; import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; +import { Box, Typography, Avatar, IconButton, CardMedia, Skeleton } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import closex from 'ui/assets/closex.svg'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import closex from 'ui/assets/closex.svg'; +import { useWallet, formatAddress } from 'ui/utils'; + const useStyles = makeStyles(() => ({ ContactCardAvatar: { mr: '13px', @@ -83,7 +82,7 @@ export const FWContactCard = ({ contact, hideCloseButton, isSend = false, isLoad }; return ( - + <> )} - + ); }; diff --git a/src/ui/FRWComponent/FWDropDownProfile.tsx b/src/ui/FRWComponent/FWDropDownProfile.tsx index b830db80..866a6a0b 100644 --- a/src/ui/FRWComponent/FWDropDownProfile.tsx +++ b/src/ui/FRWComponent/FWDropDownProfile.tsx @@ -1,4 +1,3 @@ -import React, { useState, useEffect } from 'react'; import { Box, Typography, @@ -9,17 +8,11 @@ import { FormControl, InputLabel, } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; import { makeStyles } from '@mui/styles'; -import { useWallet, isEmoji, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; +import React, { useState, useEffect, useCallback } from 'react'; -const tempEmoji = { - emoji: '🥥', - name: 'Coconut', - bgcolor: '#FFE4C4', -}; +import { isValidEthereumAddress } from '@/shared/utils/address'; +import { useWallet, isEmoji, formatAddress } from 'ui/utils'; export const FWDropDownProfile = ({ contact, @@ -28,7 +21,6 @@ export const FWDropDownProfile = ({ isLoading = false, }) => { const usewallet = useWallet(); - const [emoji, setEmoji] = useState(tempEmoji); const contactKeys = Object.keys(contacts); const [selectedChild, setSelectedChild] = React.useState( @@ -51,21 +43,8 @@ export const FWDropDownProfile = ({ setSelectedChildAccount(select); }; - const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); - if (isValidEthereumAddress(contact.address)) { - setEmoji(emojiList[1]); - } else { - setEmoji(emojiList[0]); - } - }; - - useEffect(() => { - getEmoji(); - }, [contact]); - return ( - + <> - + ); }; diff --git a/src/ui/FRWComponent/KeyPathInputs.tsx b/src/ui/FRWComponent/KeyPathInputs.tsx index 040cb45e..a9d8645f 100644 --- a/src/ui/FRWComponent/KeyPathInputs.tsx +++ b/src/ui/FRWComponent/KeyPathInputs.tsx @@ -1,8 +1,5 @@ -import { useEffect, useState, useContext } from 'react'; -import React from 'react'; import { Box, - Button, Typography, CardMedia, TextareaAutosize, @@ -10,13 +7,14 @@ import { AccordionSummary, AccordionDetails, } from '@mui/material'; +import { styled } from '@mui/material/styles'; import { makeStyles } from '@mui/styles'; -import { LLSpinner } from 'ui/FRWComponent'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import React, { useEffect, useState } from 'react'; + +import { storage } from 'background/webapi'; + import Expand from '../FRWAssets/svg/expand.svg'; import Hide from '../FRWAssets/svg/hide.svg'; -import { styled } from '@mui/material/styles'; -import { storage } from 'background/webapi'; const useStyles = makeStyles((theme) => ({ form: { diff --git a/src/ui/FRWComponent/LLComingSoonWarning.tsx b/src/ui/FRWComponent/LLComingSoonWarning.tsx index 7c8df38e..79a5b76a 100644 --- a/src/ui/FRWComponent/LLComingSoonWarning.tsx +++ b/src/ui/FRWComponent/LLComingSoonWarning.tsx @@ -1,6 +1,6 @@ -import React from 'react'; -import { IconButton, Alert, Collapse } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; +import { IconButton, Alert, Collapse } from '@mui/material'; +import React from 'react'; interface ComingSoonProps { alertOpen: boolean; diff --git a/src/ui/FRWComponent/LLConnectLoading.tsx b/src/ui/FRWComponent/LLConnectLoading.tsx index 443f4458..bcabcf98 100644 --- a/src/ui/FRWComponent/LLConnectLoading.tsx +++ b/src/ui/FRWComponent/LLConnectLoading.tsx @@ -1,7 +1,6 @@ -import React, { useState, useEffect } from 'react'; - import { Box, CardMedia, Typography } from '@mui/material'; import Avatar from '@mui/material/Avatar'; +import React, { useState, useEffect } from 'react'; export const LLConnectLoading = ({ logo }) => { const [count, setCount] = useState(0); diff --git a/src/ui/FRWComponent/LLContactCard.tsx b/src/ui/FRWComponent/LLContactCard.tsx index 2037af7b..f33b43d2 100644 --- a/src/ui/FRWComponent/LLContactCard.tsx +++ b/src/ui/FRWComponent/LLContactCard.tsx @@ -1,13 +1,12 @@ -import React, { useState } from 'react'; -import { Box, Typography, Avatar, IconButton, CardMedia, Skeleton } from '@mui/material'; -import { useWallet, formatAddress, isEmoji } from 'ui/utils'; import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; +import { Box, Typography, Avatar, IconButton, CardMedia, Skeleton } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import closex from 'ui/assets/closex.svg'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import closex from 'ui/assets/closex.svg'; +import { useWallet, formatAddress, isEmoji } from 'ui/utils'; + const useStyles = makeStyles(() => ({ ContactCardAvatar: { mr: '13px', @@ -70,7 +69,7 @@ export const LLContactCard = ({ contact, hideCloseButton, isSend = false, isLoad }; return ( - + <> )} - + ); }; diff --git a/src/ui/FRWComponent/LLContactEth.tsx b/src/ui/FRWComponent/LLContactEth.tsx index 16fc45db..b032b43a 100644 --- a/src/ui/FRWComponent/LLContactEth.tsx +++ b/src/ui/FRWComponent/LLContactEth.tsx @@ -1,13 +1,12 @@ -import React, { useState } from 'react'; -import { Box, Typography, Avatar, IconButton, CardMedia, Skeleton } from '@mui/material'; -import { useWallet, formatAddress } from 'ui/utils'; import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; +import { Box, Typography, Avatar, IconButton, CardMedia, Skeleton } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import closex from 'ui/assets/closex.svg'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; +import closex from 'ui/assets/closex.svg'; +import { useWallet, formatAddress } from 'ui/utils'; + const useStyles = makeStyles(() => ({ ContactCardAvatar: { mr: '13px', @@ -73,7 +72,7 @@ export const LLContactEth = ({ contact, hideCloseButton, isSend = false, isLoadi }; return ( - + <> )} - + ); }; diff --git a/src/ui/FRWComponent/LLDeleteBackupPopup.tsx b/src/ui/FRWComponent/LLDeleteBackupPopup.tsx index de2ebd18..7f868bf2 100644 --- a/src/ui/FRWComponent/LLDeleteBackupPopup.tsx +++ b/src/ui/FRWComponent/LLDeleteBackupPopup.tsx @@ -1,6 +1,8 @@ -import React from 'react'; import { Typography, Box, Drawer, Stack } from '@mui/material'; +import React from 'react'; + import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; + import IconSubtract from '../../components/iconfont/IconSubtract'; interface DeleteBackupProps { diff --git a/src/ui/FRWComponent/LLFlownsPop.tsx b/src/ui/FRWComponent/LLFlownsPop.tsx index 6435bca8..3c2ad0d5 100644 --- a/src/ui/FRWComponent/LLFlownsPop.tsx +++ b/src/ui/FRWComponent/LLFlownsPop.tsx @@ -1,11 +1,12 @@ -import React, { useState, useEffect } from 'react'; -import { Typography, Box, Stack, CardMedia, IconButton } from '@mui/material'; -import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; -import IconSubtract from '../../components/iconfont/IconSubtract'; +import CloseIcon from '@mui/icons-material/Close'; +import { Typography, Box, IconButton } from '@mui/material'; import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; + +import { LLPrimaryButton } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; + import lilicoIcon from '../../../_raw/images/icon-256.png'; -import CloseIcon from '@mui/icons-material/Close'; interface DeleteBackupProps { deleteBackupPop: boolean; @@ -58,14 +59,14 @@ export const LLFlownsPop = (props: DeleteBackupProps) => { setExpand(true); }; - const getUsername = async () => { + const getUsername = useCallback(async () => { const userInfo = await wallet.getUserInfo(false); setUsername(userInfo.username); - }; + }, [wallet]); useEffect(() => { getUsername(); - }, []); + }, [getUsername]); const renderContent = () => ( { }; return ( - - - {inputValue && ( - - - {genHelperText(isValidating, isValid, errorMsg, successMsg)} - - - )} - - + <> + + + {genHelperText(isValidating, isValid, errorMsg, successMsg)} + + + ); }; diff --git a/src/ui/FRWComponent/LLHeader.tsx b/src/ui/FRWComponent/LLHeader.tsx index f407a4e6..dad9db3c 100644 --- a/src/ui/FRWComponent/LLHeader.tsx +++ b/src/ui/FRWComponent/LLHeader.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { Grid, IconButton, Typography, Tooltip } from '@mui/material'; -import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import { Grid, IconButton, Typography, Tooltip } from '@mui/material'; import { styled } from '@mui/material/styles'; +import React from 'react'; import { useHistory } from 'react-router-dom'; interface LLHeaderProps { diff --git a/src/ui/FRWComponent/LLLinkingLoading.tsx b/src/ui/FRWComponent/LLLinkingLoading.tsx index 117b0dc1..02aaba6b 100644 --- a/src/ui/FRWComponent/LLLinkingLoading.tsx +++ b/src/ui/FRWComponent/LLLinkingLoading.tsx @@ -1,10 +1,11 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router-dom'; -import { makeStyles } from '@mui/styles'; import { Box, CardMedia, Typography } from '@mui/material'; import Avatar from '@mui/material/Avatar'; -import { LLPrimaryButton } from 'ui/FRWComponent'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; + import IconCheck from 'ui/assets/check.svg'; +import { LLPrimaryButton } from 'ui/FRWComponent'; const useStyles = makeStyles({ IconCheck: { diff --git a/src/ui/FRWComponent/LLNotFound.tsx b/src/ui/FRWComponent/LLNotFound.tsx index aabfd9c2..af57046f 100644 --- a/src/ui/FRWComponent/LLNotFound.tsx +++ b/src/ui/FRWComponent/LLNotFound.tsx @@ -1,16 +1,14 @@ +import { Box, Button, Typography, CardMedia, Stack } from '@mui/material'; import React from 'react'; -import { Box, Button, Typography, CardMedia, Stack, CssBaseline } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; -import NotFoundIcon from 'ui/FRWAssets/svg/notfound.svg'; import { useHistory } from 'react-router-dom'; +import NotFoundIcon from 'ui/FRWAssets/svg/notfound.svg'; + export const LLNotFound = ({ setShowDialog }) => { const history = useHistory(); return ( - - + <> { - + ); }; diff --git a/src/ui/FRWComponent/LLPinAlert.tsx b/src/ui/FRWComponent/LLPinAlert.tsx index 2017ef2c..0280f050 100644 --- a/src/ui/FRWComponent/LLPinAlert.tsx +++ b/src/ui/FRWComponent/LLPinAlert.tsx @@ -1,21 +1,15 @@ -import React from 'react'; -import { Box, Typography } from '@mui/material'; -import { Snackbar, SnackbarContent, Slide } from '@mui/material'; -import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; import ExtensionRoundedIcon from '@mui/icons-material/ExtensionRounded'; +import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; +import { Snackbar, SnackbarContent, Box, Typography } from '@mui/material'; +import React from 'react'; + import lilicoIcon from '../../../_raw/images/icon-128.png'; -const slideTransition = (props) => { - return ; -}; +import SlideLeftRight from './SlideLeftRight'; export const LLPinAlert = ({ open }) => { return ( - + { const getName = (name: string) => { @@ -18,7 +17,7 @@ export const LLProfile = ({ contact, isLoading = false }) => { }; return ( - + <> { }} > {!isLoading ? ( - - {getName(contact.contact_name)} - + isEmoji(contact.avatar) ? ( + + {contact.avatar} + + ) : ( + + {getName(contact.contact_name)} + + ) ) : ( )} + {!isLoading ? ( {contact.domain?.value || formatAddress(contact.contact_name)} @@ -64,6 +80,6 @@ export const LLProfile = ({ contact, isLoading = false }) => { )} - + ); }; diff --git a/src/ui/FRWComponent/LLResetPopup.tsx b/src/ui/FRWComponent/LLResetPopup.tsx index 72be1fe2..5b766985 100644 --- a/src/ui/FRWComponent/LLResetPopup.tsx +++ b/src/ui/FRWComponent/LLResetPopup.tsx @@ -1,8 +1,10 @@ +import { Typography, Box, Drawer, Stack } from '@mui/material'; import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { Typography, Box, Drawer, Stack } from '@mui/material'; + import { LLPrimaryButton, LLSecondaryButton, LLWarningButton } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; + import IconSubtract from '../../components/iconfont/IconSubtract'; interface AddOrEditAddressProps { diff --git a/src/ui/FRWComponent/LLSecondaryButton.tsx b/src/ui/FRWComponent/LLSecondaryButton.tsx index 2037dfe8..868a1263 100644 --- a/src/ui/FRWComponent/LLSecondaryButton.tsx +++ b/src/ui/FRWComponent/LLSecondaryButton.tsx @@ -1,6 +1,6 @@ -import React from 'react'; -import Button, { ButtonProps } from '@mui/material/Button'; +import Button, { type ButtonProps } from '@mui/material/Button'; import { styled } from '@mui/material/styles'; +import React from 'react'; interface LLSecondaryButtonProps extends ButtonProps { label: string; diff --git a/src/ui/FRWComponent/LLSpinner.tsx b/src/ui/FRWComponent/LLSpinner.tsx index 84c7fe09..73768d99 100644 --- a/src/ui/FRWComponent/LLSpinner.tsx +++ b/src/ui/FRWComponent/LLSpinner.tsx @@ -1,9 +1,9 @@ -import React from 'react'; import Box from '@mui/material/Box'; import CircularProgress, { circularProgressClasses, - CircularProgressProps, + type CircularProgressProps, } from '@mui/material/CircularProgress'; +import React from 'react'; // Inspired by the former Facebook spinners. function LLCircularProgress(props: CircularProgressProps) { diff --git a/src/ui/FRWComponent/LLSwap.tsx b/src/ui/FRWComponent/LLSwap.tsx index 9550db1f..47323664 100644 --- a/src/ui/FRWComponent/LLSwap.tsx +++ b/src/ui/FRWComponent/LLSwap.tsx @@ -1,12 +1,10 @@ -import React from 'react'; import { Box, Typography, Avatar, Skeleton } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../style/LLTheme'; import { makeStyles } from '@mui/styles'; +import React from 'react'; export const LLSwap = ({ token, amount, isLoading = false }) => { return ( - + <> { )} - + ); }; diff --git a/src/ui/FRWComponent/LLWarningButton.tsx b/src/ui/FRWComponent/LLWarningButton.tsx index c9787320..e01e8df2 100644 --- a/src/ui/FRWComponent/LLWarningButton.tsx +++ b/src/ui/FRWComponent/LLWarningButton.tsx @@ -1,6 +1,6 @@ -import React from 'react'; -import Button, { ButtonProps } from '@mui/material/Button'; +import Button, { type ButtonProps } from '@mui/material/Button'; import { styled } from '@mui/material/styles'; +import React from 'react'; interface LLWarningButtonProps extends ButtonProps { label: string | JSX.Element; diff --git a/src/ui/FRWComponent/NumberTransition.tsx b/src/ui/FRWComponent/NumberTransition.tsx new file mode 100644 index 00000000..9fb59734 --- /dev/null +++ b/src/ui/FRWComponent/NumberTransition.tsx @@ -0,0 +1,51 @@ +import { Box } from '@mui/material'; +import { keyframes } from '@mui/system'; +import React, { useEffect, useState } from 'react'; + +const slideDown = keyframes` + from { + opacity: 0; + transform: translateY(-1em); + } + to { + opacity: 1; + transform: translateY(0); + } +`; + +interface NumberTransitionProps { + number: string; + delay?: number; +} + +export const NumberTransition = ({ number, delay = 0 }: NumberTransitionProps) => { + const [show, setShow] = useState(false); + + useEffect(() => { + const timer = setTimeout(() => { + setShow(true); + }, delay); + + return () => clearTimeout(timer); + }, [delay, number]); + + return ( + span': { + display: 'inline-block', + visibility: show ? 'visible' : 'hidden', + animation: show ? `${slideDown} 300ms ease forwards` : 'none', + animationDelay: `${delay}ms`, + }, + }} + > + {number} + + ); +}; diff --git a/src/ui/FRWComponent/PopupModal/errorModel.tsx b/src/ui/FRWComponent/PopupModal/errorModel.tsx index 184459d9..a8ad324f 100644 --- a/src/ui/FRWComponent/PopupModal/errorModel.tsx +++ b/src/ui/FRWComponent/PopupModal/errorModel.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Button, Dialog, @@ -10,7 +9,9 @@ import { Select, Typography, } from '@mui/material'; +import React from 'react'; import { useHistory } from 'react-router-dom'; + import { CustomDialog } from './importAddressModal'; const ErrorModel = ({ isOpen, onOpenChange, errorName, errorMessage, isGoback = false }) => { diff --git a/src/ui/FRWComponent/PopupModal/importAddressModal.tsx b/src/ui/FRWComponent/PopupModal/importAddressModal.tsx index 72ad4ef7..cdc37dc9 100644 --- a/src/ui/FRWComponent/PopupModal/importAddressModal.tsx +++ b/src/ui/FRWComponent/PopupModal/importAddressModal.tsx @@ -1,6 +1,3 @@ -import React from 'react'; -import { styled } from '@mui/material/styles'; - import { Box, Typography, @@ -13,6 +10,8 @@ import { FormControl, Select, } from '@mui/material'; +import { styled } from '@mui/material/styles'; +import React from 'react'; export const CustomDialog = styled(Dialog)({ '& .MuiPaper-root': { diff --git a/src/ui/FRWComponent/PopupModal/resetModal.tsx b/src/ui/FRWComponent/PopupModal/resetModal.tsx index 45e4ae73..268a757a 100644 --- a/src/ui/FRWComponent/PopupModal/resetModal.tsx +++ b/src/ui/FRWComponent/PopupModal/resetModal.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Button, Dialog, @@ -10,7 +9,9 @@ import { Select, Typography, } from '@mui/material'; +import React from 'react'; import { useHistory } from 'react-router-dom'; + import { CustomDialog } from './importAddressModal'; const ResetModal = ({ diff --git a/src/ui/FRWComponent/SlideDown.tsx b/src/ui/FRWComponent/SlideDown.tsx new file mode 100644 index 00000000..b24f5cb1 --- /dev/null +++ b/src/ui/FRWComponent/SlideDown.tsx @@ -0,0 +1,23 @@ +import { Box, Slide } from '@mui/material'; +import React, { useRef } from 'react'; + +const SlideDown = ({ + show, + children, +}: { + show: boolean; + children: React.ReactElement; + container?: HTMLElement; +}) => { + const containerRef = useRef(null); + return ( + <> + + + {children} + + + ); +}; + +export default SlideDown; diff --git a/src/ui/FRWComponent/SlideLeftRight.tsx b/src/ui/FRWComponent/SlideLeftRight.tsx new file mode 100644 index 00000000..ee2b54f1 --- /dev/null +++ b/src/ui/FRWComponent/SlideLeftRight.tsx @@ -0,0 +1,26 @@ +import { Box, Slide } from '@mui/material'; +import React from 'react'; + +const SlideLeftRight = React.forwardRef( + ( + { + show, + direction = 'left', + children, + }: { + show: boolean; + direction: 'left' | 'right'; + children: React.ReactElement; + }, + ref + ) => { + const showIt = !!show; + if (showIt) { + return children; + } else { + return null; + } + } +); + +export default SlideLeftRight; diff --git a/src/ui/FRWComponent/SlideRelative.tsx b/src/ui/FRWComponent/SlideRelative.tsx new file mode 100644 index 00000000..b097b306 --- /dev/null +++ b/src/ui/FRWComponent/SlideRelative.tsx @@ -0,0 +1,31 @@ +import { Box, Slide } from '@mui/material'; +import React, { useRef } from 'react'; + +const SlideRelative = React.forwardRef( + ( + { + show, + direction, + children, + }: { show: boolean; direction: 'up' | 'down' | 'left' | 'right'; children: React.ReactElement }, + ref + ) => { + const containerRef = useRef(null); + return ( + <> + + + {children} + + + ); + } +); + +export default SlideRelative; diff --git a/src/ui/FRWComponent/WarningStorageLowSnackbar.tsx b/src/ui/FRWComponent/WarningStorageLowSnackbar.tsx index eb7bc96c..8f1e9adc 100644 --- a/src/ui/FRWComponent/WarningStorageLowSnackbar.tsx +++ b/src/ui/FRWComponent/WarningStorageLowSnackbar.tsx @@ -22,6 +22,7 @@ export const WarningStorageLowSnackbar = ({ return null; } return ( - {}} alertIcon={warningIcon} message={message} /> + // {}} alertIcon={warningIcon} message={message} /> + <> ); }; diff --git a/src/ui/FRWComponent/index.tsx b/src/ui/FRWComponent/index.tsx index f82621ea..d735eb6c 100644 --- a/src/ui/FRWComponent/index.tsx +++ b/src/ui/FRWComponent/index.tsx @@ -25,3 +25,4 @@ export * from './FWContactCard'; export * from './FWDropDownProfile'; export * from './FWMoveDropdown'; export * from './LLContactEth'; +export * from './FRWTargetProfile'; diff --git a/src/ui/index.html b/src/ui/index.html index 0457e908..583cff87 100644 --- a/src/ui/index.html +++ b/src/ui/index.html @@ -124,6 +124,9 @@ margin: 0px; } + <% if (devMode && hasDevTools) { %> + + <% } %> diff --git a/src/ui/index.tsx b/src/ui/index.tsx index 84678200..86f8df56 100644 --- a/src/ui/index.tsx +++ b/src/ui/index.tsx @@ -1,10 +1,12 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import Views from './views'; -import { Message } from '@/utils'; -import { getUITypeName } from 'ui/utils'; +import React, { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; + import eventBus from '@/eventBus'; +import { Message } from '@/shared/utils/messaging'; import { EVENTS } from 'consts'; +import { getUITypeName } from 'ui/utils'; + +import Views from './views'; // import './style/index.less'; function initAppMeta() { @@ -54,7 +56,6 @@ const wallet: Record = new Proxy( }, } ); - break; default: return function (...params: any) { chrome.runtime.sendMessage( @@ -63,7 +64,7 @@ const wallet: Record = new Proxy( method: key, params, }, - function (response) { + function (_response) { // console.log('portMessageChannel 3 ->', response); } ); @@ -97,4 +98,10 @@ eventBus.addEventListener(EVENTS.broadcastToBackground, (data) => { }); }); -ReactDOM.render(, document.getElementById('root')); +const container = document.getElementById('root'); +const root = createRoot(container!); // createRoot(container!) if you use TypeScript +root.render( + + + +); diff --git a/src/ui/popup.html b/src/ui/popup.html index 3a1df1a3..b260a156 100644 --- a/src/ui/popup.html +++ b/src/ui/popup.html @@ -133,6 +133,9 @@ } + <% if (devMode && hasDevTools) { %> + + <% } %> diff --git a/src/ui/style/LLTheme.ts b/src/ui/style/LLTheme.ts index 394c6aaa..59c5034d 100644 --- a/src/ui/style/LLTheme.ts +++ b/src/ui/style/LLTheme.ts @@ -1,8 +1,7 @@ -import { createTheme } from '@mui/material/styles'; -import { Theme as SystemTheme } from '@mui/system'; +import { createTheme, type ThemeOptions } from '@mui/material/styles'; import './fonts.css'; -const theme: SystemTheme = createTheme({ +const themeOptions: ThemeOptions = { components: { MuiCssBaseline: { styleOverrides: { @@ -157,7 +156,7 @@ const theme: SystemTheme = createTheme({ fontWeight: 600, }, }, -}); +}; declare module '@mui/material/Button' { interface ButtonPropsColorOverrides { @@ -165,4 +164,4 @@ declare module '@mui/material/Button' { } } -export default theme; +export default themeOptions; diff --git a/src/ui/utils/hooks.ts b/src/ui/utils/hooks.ts index a5705f7c..dddb7eba 100644 --- a/src/ui/utils/hooks.ts +++ b/src/ui/utils/hooks.ts @@ -1,53 +1,66 @@ -import { useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useMemo, useState } from 'react'; import { useHistory } from 'react-router-dom'; + import { useWallet } from './WalletContext'; + import { getUiType } from './index'; export const useApproval = () => { // console.log('useApproval 1') - const wallet = useWallet(); + const usewallet = useWallet(); const history = useHistory(); // console.log('useApproval 2') - const getApproval = wallet.getApproval; + const getApproval = useCallback(() => usewallet.getApproval(), [usewallet]); + const stableUsewallet = useMemo(() => usewallet, [usewallet]); + const stableHistory = useMemo(() => history, [history]); - const linkningConfirm = async (data?: any, stay = false, forceReject = false) => { - const approval = await getApproval(); + const linkingConfirm = useCallback( + async (data?: any, stay = false, forceReject = false) => { + const approval = await getApproval(); - if (approval) { - await wallet.resolveApproval(data, forceReject); - return; - } - if (stay) { - return; - } - // setTimeout(() => { - // history.replace('/'); - // }); - }; + if (approval) { + await stableUsewallet.resolveApproval(data, forceReject); + return; + } + if (stay) { + return; + } + // setTimeout(() => { + // stableHistory.replace('/'); + // }); + }, + [getApproval, stableUsewallet] + ); - const resolveApproval = async (data?: any, stay = false, forceReject = false) => { - const approval = await getApproval(); + const resolveApproval = useCallback( + async (data?: any, stay = false, forceReject = false) => { + const approval = await getApproval(); - if (approval) { - wallet.resolveApproval(data, forceReject); - } - if (stay) { - return; - } - setTimeout(() => { - history.replace('/'); - }); - }; - - const rejectApproval = async (err?) => { - const approval = await getApproval(); - if (approval) { - await wallet.rejectApproval(err); - } - history.push('/'); - }; + if (approval) { + stableUsewallet.resolveApproval(data, forceReject); + } + if (stay) { + return; + } + setTimeout(() => { + stableHistory.replace('/'); + }); + }, + [getApproval, stableUsewallet, stableHistory] + ); + + const rejectApproval = useCallback( + async (err?) => { + const approval = await getApproval(); + if (approval) { + await stableUsewallet.rejectApproval(err); + } + stableHistory.push('/'); + }, + [getApproval, stableUsewallet, stableHistory] + ); useEffect(() => { console.log('useApproval', getUiType(), getUiType().isNotification); @@ -58,9 +71,9 @@ export const useApproval = () => { window.addEventListener('beforeunload', rejectApproval); return () => window.removeEventListener('beforeunload', rejectApproval); - }, []); + }, [rejectApproval]); - return [getApproval, resolveApproval, rejectApproval, linkningConfirm] as const; + return [getApproval, resolveApproval, rejectApproval, linkingConfirm] as const; }; export const useSelectOption = ({ @@ -75,7 +88,7 @@ export const useSelectOption = ({ value?: T[]; }) => { const isControlled = useRef(typeof value !== 'undefined').current; - const [idxs, setChoosedIdxs] = useState( + const [chosenIndexes, setChosenIndexes] = useState( (isControlled ? value! : defaultValue).map((x) => options.indexOf(x)) ); @@ -85,50 +98,64 @@ export const useSelectOption = ({ } // shallow compare - if (value && idxs.some((x, i) => options[x] != value[i])) { - setChoosedIdxs(value.map((x) => options.indexOf(x))); + if (value) { + setChosenIndexes(value.map((x) => options.indexOf(x))); } - }, [value]); + }, [value, options, isControlled]); - const changeValue = (idxs: number[]) => { - setChoosedIdxs([...idxs]); - onChange && onChange(idxs.map((o) => options[o])); - }; + const changeValue = useCallback( + (indexes: number[]) => { + setChosenIndexes([...indexes]); + if (onChange) { + onChange(indexes.map((o) => options[o])); + } + }, + [options, onChange] + ); - const handleRemove = (i: number) => { - idxs.splice(i, 1); - changeValue(idxs); - }; + const handleRemove = useCallback( + (i: number) => { + chosenIndexes.splice(i, 1); + changeValue(chosenIndexes); + }, + [chosenIndexes, changeValue] + ); - const handleChoose = (i: number) => { - if (idxs.includes(i)) { - return; - } + const handleChoose = useCallback( + (i: number) => { + if (chosenIndexes.includes(i)) { + return; + } - idxs.push(i); - changeValue(idxs); - }; + chosenIndexes.push(i); + changeValue(chosenIndexes); + }, + [chosenIndexes, changeValue] + ); - const handleToggle = (i: number) => { - const inIdxs = idxs.indexOf(i); - if (inIdxs !== -1) { - handleRemove(inIdxs); - } else { - handleChoose(i); - } - }; + const handleToggle = useCallback( + (i: number) => { + const inIdxs = chosenIndexes.indexOf(i); + if (inIdxs !== -1) { + handleRemove(inIdxs); + } else { + handleChoose(i); + } + }, + [chosenIndexes, handleRemove, handleChoose] + ); - const handleClear = () => { + const handleClear = useCallback(() => { changeValue([]); - }; + }, [changeValue]); return [ - idxs.map((o) => options[o]), + chosenIndexes.map((o) => options[o]), handleRemove, handleChoose, handleToggle, handleClear, - idxs, + chosenIndexes, ] as const; }; @@ -154,27 +181,34 @@ export const useWalletRequest = ( const [res, setRes] = useState(); const [err, setErr] = useState(); - const run = async (...args) => { - setLoading(true); - try { - const _res = await Promise.resolve(requestFn(...args)); - if (!mounted.current) { - return; - } - setRes(_res); - onSuccess && onSuccess(_res); - } catch (err) { - if (!mounted.current) { - return; - } - setErr(err); - onError && onError(err); - } finally { - if (mounted.current) { - setLoading(false); + const run = useCallback( + async (...args) => { + setLoading(true); + try { + const _res = await Promise.resolve(requestFn(...args)); + if (!mounted.current) { + return; + } + setRes(_res); + if (onSuccess) { + onSuccess(_res); + } + } catch (err) { + if (!mounted.current) { + return; + } + setErr(err); + if (onError) { + onError(err); + } + } finally { + if (mounted.current) { + setLoading(false); + } } - } - }; + }, + [requestFn, mounted, onSuccess, onError] + ); return [run, loading, res, err] as const; }; @@ -190,19 +224,24 @@ export const useHover = ({ mouseEnterDelayMS = 0, mouseLeaveDelayMS = 0 }: UseHo HoverProps, ] => { const [isHovering, setIsHovering] = useState(false); - let mouseEnterTimer: number | undefined; - let mouseOutTimer: number | undefined; + const mouseEnterTimer = useRef(); + const mouseOutTimer = useRef(); + + const onMouseEnter = useCallback(() => { + clearTimeout(mouseOutTimer.current); + mouseEnterTimer.current = window.setTimeout(() => setIsHovering(true), mouseEnterDelayMS); + }, [mouseEnterDelayMS, mouseOutTimer]); + + const onMouseLeave = useCallback(() => { + clearTimeout(mouseEnterTimer.current); + mouseOutTimer.current = window.setTimeout(() => setIsHovering(false), mouseLeaveDelayMS); + }, [mouseLeaveDelayMS, mouseEnterTimer]); + return [ isHovering, { - onMouseEnter: () => { - clearTimeout(mouseOutTimer); - mouseEnterTimer = window.setTimeout(() => setIsHovering(true), mouseEnterDelayMS); - }, - onMouseLeave: () => { - clearTimeout(mouseEnterTimer); - mouseOutTimer = window.setTimeout(() => setIsHovering(false), mouseLeaveDelayMS); - }, + onMouseEnter, + onMouseLeave, }, ]; }; diff --git a/src/ui/utils/index.ts b/src/ui/utils/index.ts index a96c2e82..3c0f1846 100644 --- a/src/ui/utils/index.ts +++ b/src/ui/utils/index.ts @@ -1,6 +1,5 @@ import { IS_CHROME, CHECK_METAMASK_INSTALLED_URL } from 'consts'; -import { Account } from 'background/service/preference'; -// eslint-disable-next-line @typescript-eslint/no-empty-function + export const noop = () => {}; export * from './WalletContext'; @@ -14,10 +13,10 @@ export * from './time'; export * from './number'; -export * from './options'; - export * from './saveStorage'; +export * from './mixpanelBrowserService'; + const UI_TYPE = { Tab: 'index', Pop: 'popup', @@ -125,7 +124,7 @@ export const isMetaMaskActive = async () => { await res.text(); return true; - } catch (e) { + } catch { return false; } }; @@ -141,70 +140,6 @@ export const ellipsisOverflowedText = (str: string, length = 5, removeLastComma return `${cut}...`; }; -export function getHashAlgo(value: string): number { - switch (value) { - case 'unknown': - return 0; - case 'SHA2_256': - return 1; - case 'SHA2_384': - return 2; - case 'SHA3_256': - return 3; - case 'SHA3_384': - return 4; - default: - return -1; // Handle unknown values - } -} - -export function getSignAlgo(value: string): number { - switch (value) { - case 'unknown': - return 0; - case 'ECDSA_P256': - return 1; - case 'ECDSA_p256': - return 1; - case 'ECDSA_SECP256k1': - return 2; - case 'ECDSA_secp256k1': - return 2; - default: - return -1; // Handle unknown values - } -} - -export function getStringFromHashAlgo(value: number): string { - switch (value) { - case 0: - return 'unknown'; - case 1: - return 'SHA2_256'; - case 2: - return 'SHA2_384'; - case 3: - return 'SHA3_256'; - case 4: - return 'SHA3_384'; - default: - return 'unknown'; // Handle unknown values - } -} - -export function getStringFromSignAlgo(value: number): string { - switch (value) { - case 0: - return 'unknown'; - case 1: - return 'ECDSA_P256'; - case 2: - return 'ECDSA_SECP256k1'; - default: - return 'unknown'; // Handle unknown values - } -} - export const formatAddress = (address) => { if (address && address.length >= 30) { return `${address.substring(0, 6)}...${address.substring(address.length - 8)}`; diff --git a/src/ui/utils/mixpanelBrowserService.ts b/src/ui/utils/mixpanelBrowserService.ts new file mode 100644 index 00000000..0a362d23 --- /dev/null +++ b/src/ui/utils/mixpanelBrowserService.ts @@ -0,0 +1,147 @@ +import mixpanel from 'mixpanel-browser'; + +import type { TrackingEvents, TrackMessage } from '@/shared/types/tracking-types'; + +import packageJson from '../../../package.json'; +const { version } = packageJson; + +// Super properties that will be sent with every event +type SuperProperties = { + app_version: string; + platform: 'extension'; + environment: 'development' | 'production'; + wallet_type: 'flow'; +}; + +class MixpanelBrowserService { + private static instance: MixpanelBrowserService; + private initialized = false; + + private mixpanelEventMessageHandler: (message: TrackMessage) => void; + + private constructor() { + this.initMixpanel(); + + this.mixpanelEventMessageHandler = (message: TrackMessage) => { + switch (message.msg) { + case 'track_event': + // TypeScript knows eventName and properties are available here + this.track(message.eventName, message.properties); + break; + case 'track_user': + // TypeScript knows userId is available here + this.identify(message.userId); + break; + case 'track_reset': + // TypeScript knows this is just a reset message + this.reset(); + break; + case 'track_time': + // TypeScript knows eventName is available here + this.time(message.eventName); + break; + } + }; + + this.setupEventListener(); + } + + private setupEventListener() { + // Listen for messages from the background script + // This feels blunt as we have to switch on the message type + // TODO: We should use a more elegant approach to filter messages based on the sender + chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + switch (message.msg) { + case 'track_event': + case 'track_user': + case 'track_reset': + case 'track_time': + this.mixpanelEventMessageHandler(message); + sendResponse({ success: true }); + break; + } + return true; // Keep the message channel open for asynchronous response + }); + } + + init() { + // Don't need to do anything here + // Mixpanel is initialized in the constructor + } + cleanup() { + // Remove the event listener + chrome.runtime.onMessage.removeListener(this.mixpanelEventMessageHandler); + } + + static getInstance(): MixpanelBrowserService { + if (!MixpanelBrowserService.instance) { + MixpanelBrowserService.instance = new MixpanelBrowserService(); + } + return MixpanelBrowserService.instance; + } + + private registerSuperProperties() { + const superProperties: SuperProperties = { + app_version: version, + platform: 'extension', + environment: process.env.NODE_ENV === 'production' ? 'production' : 'development', + wallet_type: 'flow', + }; + + mixpanel.register(superProperties); + } + + private initMixpanel() { + if (this.initialized) return; + + const token = process.env.MIXPANEL_TOKEN; + if (!token) { + console.warn('Mixpanel token not found'); + return; + } + + mixpanel.init(token, { + debug: process.env.NODE_ENV !== 'production', + track_pageview: 'full-url', // track the full url including the hash + persistence: 'localStorage', + batch_requests: true, + batch_size: 10, + batch_flush_interval_ms: 2000, + }); + + this.registerSuperProperties(); + this.initialized = true; + } + + track(eventName: T, properties?: TrackingEvents[T]) { + if (!this.initialized) { + console.warn('Mixpanel not initialized'); + return; + } + + const baseProps = { + timestamp: Date.now(), + }; + + mixpanel.track(eventName, { + ...baseProps, + ...properties, + }); + } + + time(eventName: T) { + mixpanel.time_event(eventName); + } + + identify(userId: string) { + if (!this.initialized) return; + mixpanel.identify(userId); + } + + reset() { + if (!this.initialized) return; + mixpanel.reset(); + } +} + +export const mixpanelBrowserService = MixpanelBrowserService.getInstance(); diff --git a/src/ui/utils/modules/findAddressWithPK.tsx b/src/ui/utils/modules/findAddressWithPK.tsx index 120ba664..dd24750c 100644 --- a/src/ui/utils/modules/findAddressWithPK.tsx +++ b/src/ui/utils/modules/findAddressWithPK.tsx @@ -1,7 +1,7 @@ +import { findAddressWithKey, findAddressOnlyKey } from './findAddressWithPubKey'; import { pk2PubKey, seed2PubKey, seed2PubKeyTemp } from './passkey'; -import { findAddressWithKey } from './findAddressWithPubKey'; -const findAddress = async (pubKTuple, address) => { +export const findAddress = async (pubKTuple, address) => { const { P256, SECP256K1 } = pubKTuple; const p256Accounts = (await findAddressWithKey(P256.pubK, address)) || []; const sepc256k1Accounts = (await findAddressWithKey(SECP256K1.pubK, address)) || []; @@ -9,10 +9,6 @@ const findAddress = async (pubKTuple, address) => { const pS = sepc256k1Accounts.map((s) => ({ ...s, pk: SECP256K1.pk })); const accounts = pA.concat(pS); - // console.log('accounts 222 ==>', accounts); - if (accounts[0].weight < 1000) { - return null; - } if (!accounts || accounts.length === 0) { SECP256K1['weight'] = 1000; SECP256K1['hashAlgo'] = 'SHA2_256'; @@ -23,6 +19,31 @@ const findAddress = async (pubKTuple, address) => { return accounts; }; +export const findAddressWithNetwork = async (pubKTuple, network) => { + const { P256, SECP256K1 } = pubKTuple; + const p256Accounts = (await findAddressOnlyKey(P256.pubK, network)) || []; + const sepc256k1Accounts = (await findAddressOnlyKey(SECP256K1.pubK, network)) || []; + const pA = p256Accounts.map((s) => ({ ...s, pk: P256.pk })); + const pS = sepc256k1Accounts.map((s) => ({ ...s, pk: SECP256K1.pk })); + const accounts = pA.concat(pS); + + // console.log('accounts 222 ==>', accounts); + if (!accounts || accounts.length === 0) { + return [ + { + ...SECP256K1, + weight: 1000, + hashAlgo: 'SHA2_256', + signAlgo: 'ECDSA_secp256k1', + keyIndex: 0, + }, + ]; + } + + const account = accounts.find((account) => account.weight >= 1000); + return account ? accounts : null; +}; + export const findAddressWithPK = async (pk, address) => { const pubKTuple = await pk2PubKey(pk); return await findAddress(pubKTuple, address); diff --git a/src/ui/utils/modules/findAddressWithPubKey.tsx b/src/ui/utils/modules/findAddressWithPubKey.tsx index eac0a380..543b7ffa 100644 --- a/src/ui/utils/modules/findAddressWithPubKey.tsx +++ b/src/ui/utils/modules/findAddressWithPubKey.tsx @@ -1,6 +1,7 @@ import * as fcl from '@onflow/fcl'; -import { fclMainnetConfig } from 'background/fclConfig'; +import { fclMainnetConfig, fclTestnetConfig } from 'background/fclConfig'; +import { userWalletService } from 'background/service'; export const findAddressWithKey = async (pubKeyHex, address) => { if (!address) { @@ -22,15 +23,49 @@ export const findAddressWithKey = async (pubKeyHex, address) => { return await findAddres(address, pubKeyHex); }; -export default async function getAddressByIndexer(publicKey) { +export const findAddressOnlyKey = async (pubKeyHex, network) => { + let data; + if (network === 'testnet') { + data = await getAddressTestnet(pubKeyHex); + } else { + data = await getAddressByIndexer(pubKeyHex); + } + if (data.accounts && data.accounts.length > 0) { + const outputArray = data.accounts.map((account) => ({ + address: account.address, + keyIndex: account.keyId, + weight: account.weight, + hashAlgo: account.hashing, + signAlgo: account.signing, + pubK: pubKeyHex, + })); + const filteredResults = outputArray.filter((result) => result !== null); + return filteredResults.flat(); + } + return null; +}; + +export async function getAddressByIndexer(publicKey) { const url = `https://production.key-indexer.flow.com/key/${publicKey}`; const result = await fetch(url); const json = await result.json(); return json; } +export async function getAddressTestnet(publicKey) { + const url = `https://staging.key-indexer.flow.com/key/${publicKey}`; + const result = await fetch(url); + const json = await result.json(); + return json; +} + const findAddres = async (address, pubKeyHex) => { - await fclMainnetConfig(); + const network = await userWalletService.getNetwork(); + if (network === 'testnet') { + await fclTestnetConfig(); + } else { + await fclMainnetConfig(); + } const account = await fcl.account(address); const keys = account.keys .filter((key) => key.publicKey === pubKeyHex && !key.revoked) diff --git a/src/ui/utils/modules/passkey.js b/src/ui/utils/modules/passkey.js index ab55c4af..867d3528 100644 --- a/src/ui/utils/modules/passkey.js +++ b/src/ui/utils/modules/passkey.js @@ -1,16 +1,19 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck + +import { initWasm } from '@trustwallet/wallet-core'; + +import { getStringFromHashAlgo, getStringFromSignAlgo } from '@/shared/utils/algo'; +import { storage } from 'background/webapi'; + +import { decodeArray, encodeArray } from './base64'; +import { FLOW_BIP44_PATH, HASH_ALGO, KEY_TYPE, SIGN_ALGO } from './constants'; +import { addCredential, readSettings } from './settings'; import { decodeAuthenticatorData, decodeClientDataJSON, decodeAttestationObject, } from './WebAuthnDecoder'; -import { decodeArray, encodeArray } from './base64'; -import { initWasm } from '@trustwallet/wallet-core'; -import { addCredential, readSettings } from './settings'; -import { FLOW_BIP44_PATH, HASH_ALGO, KEY_TYPE, SIGN_ALGO } from './constants'; -import { getStringFromHashAlgo, getStringFromSignAlgo } from 'ui/utils'; -import { storage } from 'background/webapi'; const jsonToKey = async (json, password) => { try { @@ -73,10 +76,7 @@ const seed2PubKey = async (seed) => { (await storage.get(pathKeyId)) ?? (await storage.get(pathKeyIndex)) ?? FLOW_BIP44_PATH; const passphrase = (await storage.get(phraseKeyId)) ?? (await storage.get(phraseKeyIndex)) ?? ''; - // console.log('pathpathpath ', path) - // console.log('pathKey ', pathKey) - // console.log('phraseKey ', phraseKey) - // console.log('passphrase ', passphrase) + const wallet = HDWallet.createWithMnemonic(seed, passphrase); const p256PK = wallet.getKeyByCurve(Curve.nist256p1, path); const p256PubK = Buffer.from(p256PK.getPublicKeyNist256p1().uncompressed().data()) @@ -127,7 +127,7 @@ const seed2PubKeyTemp = async (seed) => { }; function getRandomBytes(length) { - var array = new Uint8Array(length ?? 32); + const array = new Uint8Array(length ?? 32); crypto.getRandomValues(array); return array; } diff --git a/src/ui/utils/number.ts b/src/ui/utils/number.ts index de30d011..390d72e1 100644 --- a/src/ui/utils/number.ts +++ b/src/ui/utils/number.ts @@ -6,7 +6,6 @@ export const splitNumberByStep = ( symbol = ',', forceInt = false ) => { - // eslint-disable-next-line prefer-const let [int, float] = (num + '').split('.'); const reg = new RegExp(`(\\d)(?=(\\d{${step}})+(?!\\d))`, 'g'); @@ -50,14 +49,12 @@ export const formatLargeNumber = (num) => { export const addDotSeparators = (num) => { // replace with http://numeraljs.com/ if more requirements const [integerPart, decimalPart] = parseFloat(num).toFixed(8).split('.'); - const newIntegerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ','); - let result = `${newIntegerPart}.${decimalPart}`; + // Format the integer part with comma separators + const newIntegerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ','); - // Check if the total length of the result exceeds 13 characters - if (result.length > 13) { - result = result.slice(0, 13) + '...'; - } + const trimmedDecimal = decimalPart.replace(/0+$/, ''); + const formattedDecimal = trimmedDecimal.length > 0 ? trimmedDecimal : decimalPart.slice(-3); - return result; + return `${newIntegerPart}.${formattedDecimal}`; }; diff --git a/src/ui/utils/options.ts b/src/ui/utils/options.ts deleted file mode 100644 index 322fa2d1..00000000 --- a/src/ui/utils/options.ts +++ /dev/null @@ -1,125 +0,0 @@ -const Options = { - fullScreen: true, - fpsLimit: 120, - detectRetina: true, - emitters: { - direction: 'bottom', - startCount: 0, - position: { x: 50, y: 0 }, - size: { - width: 20, - height: 0, - }, - rate: { - delay: 0, - quantity: 2, - }, - life: { - count: 200, - duration: 0.01, - // delay:0.6, - }, - }, - particles: { - number: { - value: 250, - }, - color: { - value: ['#9146FF', '#FFAAA8', '#8FFFD2', '#FFD37A', '#FF38DB'], - }, - shape: { - type: ['square', 'circle', 'heart'], - }, - opacity: { - value: 1, - animation: { - enable: true, - minimumValue: 0, - speed: 0.5, - startValue: 'max', - destroy: 'min', - }, - }, - size: { - value: 5, - }, - links: { - enable: false, - }, - life: { - duration: { - sync: true, - value: 10, - }, - count: 1, - }, - move: { - angle: { - value: 45, - offset: 0, - }, - drift: { - min: -0, - max: 0, - }, - enable: true, - gravity: { - enable: true, - acceleration: 20, - }, - speed: 90, - decay: 1 - 0.9, - direction: -90, - random: true, - straight: false, - outModes: { - default: 'none', - bottom: 'destroy', - }, - }, - rotate: { - value: { - min: 0, - max: 360, - }, - direction: 'random', - animation: { - enable: true, - speed: 60, - }, - }, - tilt: { - direction: 'random', - enable: true, - value: { - min: 0, - max: 360, - }, - animation: { - enable: true, - speed: 60, - }, - }, - roll: { - darken: { - enable: true, - value: 25, - }, - enable: true, - speed: { - min: 15, - max: 25, - }, - }, - wobble: { - distance: 20, - enable: true, - speed: { - min: -15, - max: 15, - }, - }, - }, -}; - -export { Options }; diff --git a/src/ui/utils/profileHooks.ts b/src/ui/utils/profileHooks.ts index 73d99460..50c9af1f 100644 --- a/src/ui/utils/profileHooks.ts +++ b/src/ui/utils/profileHooks.ts @@ -17,7 +17,7 @@ const tempEmoji = [ export const profileHooks = () => { const usewallet = useWallet(); - const [emojis, setEmojis] = useState(tempEmoji); + const [emojis, setEmojis] = useState(tempEmoji); const fetchEmojis = useCallback(async () => { try { console.log('fetchEmojis'); diff --git a/src/ui/utils/saveStorage.ts b/src/ui/utils/saveStorage.ts index 415a99d2..0f5196ee 100644 --- a/src/ui/utils/saveStorage.ts +++ b/src/ui/utils/saveStorage.ts @@ -24,34 +24,3 @@ export const saveIndex = async (username = '', userId = null) => { await storage.set('currentId', userId); } }; - -export const getStoragedAccount = async () => { - const accountIndex = (await storage.get('currentAccountIndex')) || 0; - const currentId = (await storage.get('currentId')) || null; - const loggedInAccounts = (await storage.get('loggedInAccounts')) || []; - console.log('loggedInAccounts ', loggedInAccounts); - console.log('currentId ', currentId); - let account; - - // Check if currentId is provided and valid - if (currentId !== null) { - // Find account with the currentId - account = loggedInAccounts.find((acc) => acc.id === currentId); - - // If no account is found with currentId, default to accountIndex - if (!account) { - account = loggedInAccounts[accountIndex]; - } - } else { - // If currentId is not provided, use accountIndex - account = loggedInAccounts[accountIndex]; - } - - if (!account) { - // Handle the case when no account is found - throw new Error('Account info not found.'); - } else { - // Return account - return account; - } -}; diff --git a/src/ui/utils/transaction.ts b/src/ui/utils/transaction.ts index 35ab2f3e..64ba3ac1 100644 --- a/src/ui/utils/transaction.ts +++ b/src/ui/utils/transaction.ts @@ -1,6 +1,6 @@ // import abi from 'human-standard-token-abi'; -import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; +import { ethers } from 'ethers'; // const hstInterface = new ethers.utils.Interface(abi); diff --git a/src/ui/utils/useMixpanel.ts b/src/ui/utils/useMixpanel.ts new file mode 100644 index 00000000..24809766 --- /dev/null +++ b/src/ui/utils/useMixpanel.ts @@ -0,0 +1,32 @@ +import { useCallback } from 'react'; + +import type { TrackingEvents } from '@/shared/types/tracking-types'; + +import { mixpanelBrowserService } from './mixpanelBrowserService'; + +export const useMixpanel = () => { + const track = useCallback( + (eventName: T, properties?: TrackingEvents[T]) => { + mixpanelBrowserService.track(eventName, properties); + }, + [] + ); + const time = useCallback((eventName: T) => { + mixpanelBrowserService.time(eventName); + }, []); + + const identify = useCallback((userId: string) => { + mixpanelBrowserService.identify(userId); + }, []); + + const reset = useCallback(() => { + mixpanelBrowserService.reset(); + }, []); + + return { + track, + time, + identify, + reset, + }; +}; diff --git a/src/ui/utils/useStorageCheck.ts b/src/ui/utils/useStorageCheck.ts index 4254bcfd..9ce9f625 100644 --- a/src/ui/utils/useStorageCheck.ts +++ b/src/ui/utils/useStorageCheck.ts @@ -12,12 +12,14 @@ interface StorageCheckResult { } interface UseStorageCheckProps { - transferAmount?: number | undefined; + transferAmount?: number; + coin?: string; movingBetweenEVMAndFlow?: boolean; } export const useStorageCheck = ({ - transferAmount, - movingBetweenEVMAndFlow, + transferAmount, // amount in coins + coin, // coin name + movingBetweenEVMAndFlow = false, // are we moving between EVM and Flow? }: UseStorageCheckProps = {}): StorageCheckResult => { const wallet = useWallet(); @@ -26,6 +28,7 @@ export const useStorageCheck = ({ undefined ); const [storageInfo, setStorageInfo] = useState(undefined); + // Check general storage status const checkStorageStatus = useCallback(async (): Promise<{ sufficient: boolean; @@ -35,7 +38,8 @@ export const useStorageCheck = ({ try { const { isStorageSufficient, isStorageSufficientAfterAction, storageInfo } = await wallet.checkStorageStatus({ - transferAmount, + transferAmount: transferAmount, + coin, movingBetweenEVMAndFlow, }); @@ -52,7 +56,7 @@ export const useStorageCheck = ({ storageInfo: { available: 0, used: 0, capacity: 0 }, }; // Default to true to not block transactions on error } - }, [movingBetweenEVMAndFlow, transferAmount, wallet]); + }, [movingBetweenEVMAndFlow, transferAmount, wallet, coin]); // Initial storage check useEffect(() => { diff --git a/src/ui/utils/webapi.ts b/src/ui/utils/webapi.ts index 41eac084..c71f71c5 100644 --- a/src/ui/utils/webapi.ts +++ b/src/ui/utils/webapi.ts @@ -1,4 +1,4 @@ -import { WalletController } from './index'; +import { type WalletController } from './index'; export const getCurrentTab = async () => { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); diff --git a/src/ui/views/AddWelcome/AddRegister/AllSet.tsx b/src/ui/views/AddWelcome/AddRegister/AllSet.tsx index cb2f5d6b..b4bea0e9 100644 --- a/src/ui/views/AddWelcome/AddRegister/AllSet.tsx +++ b/src/ui/views/AddWelcome/AddRegister/AllSet.tsx @@ -1,9 +1,9 @@ +import { Button, Typography, CardMedia } from '@mui/material'; +import { Box } from '@mui/system'; import React, { useEffect } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline, CardMedia } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import AllSetIcon from 'ui/FRWAssets/svg/allset.svg'; + import { storage } from 'background/webapi'; +import AllSetIcon from 'ui/FRWAssets/svg/allset.svg'; const AllSet = ({ handleClick }) => { const removeTempPass = () => { @@ -14,8 +14,7 @@ const AllSet = ({ handleClick }) => { removeTempPass(); }, []); return ( - - + <> { - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/GoogleBackup.tsx b/src/ui/views/AddWelcome/AddRegister/GoogleBackup.tsx index e38e70a9..135de36c 100644 --- a/src/ui/views/AddWelcome/AddRegister/GoogleBackup.tsx +++ b/src/ui/views/AddWelcome/AddRegister/GoogleBackup.tsx @@ -1,12 +1,13 @@ +import InfoIcon from '@mui/icons-material/Info'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; + import IconGoogleDrive from '../../../../components/iconfont/IconGoogleDrive'; -import { LLSpinner } from 'ui/FRWComponent'; -import InfoIcon from '@mui/icons-material/Info'; -import { Presets } from 'react-component-transition'; const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { const wallets = useWallet(); @@ -33,8 +34,7 @@ const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { } }; return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -94,35 +94,29 @@ const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { - {backupErr && ( - - - {/* */} - - - {chrome.i18n.getMessage( - 'Backup_failed_you_may_still_conduct_backup_inside_extension' - )} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage( + 'Backup_failed_you_may_still_conduct_backup_inside_extension' + )} + + + - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/PickUsername.tsx b/src/ui/views/AddWelcome/AddRegister/PickUsername.tsx index 05e057c5..a38cddbf 100644 --- a/src/ui/views/AddWelcome/AddRegister/PickUsername.tsx +++ b/src/ui/views/AddWelcome/AddRegister/PickUsername.tsx @@ -1,13 +1,21 @@ -import React, { useEffect, useState } from 'react'; +import { + CircularProgress, + IconButton, + Button, + Typography, + FormControl, + Input, + InputAdornment, +} from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import theme from '../../../style/LLTheme'; -import { Presets } from 'react-component-transition'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet } from 'ui/utils'; -import { CircularProgress, IconButton } from '@mui/material'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; import EmailIcon from '../../../assets/alternate-email.svg'; const useStyles = makeStyles((theme) => ({ @@ -57,19 +65,22 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { ); - const usernameCorrect = ( - - - - {chrome.i18n.getMessage('Sounds_good')} - - + const usernameCorrect = useMemo( + () => ( + + + + {chrome.i18n.getMessage('Sounds_good')} + + + ), + [] ); const usernameLoading = () => ( { ); - const [username, setUsername] = useState(savedUsername || ''); + const [username, setUsername] = useState(savedUsername || ''); const [helperText, setHelperText] = useState(
); - const regex = /^[A-Za-z0-9]{3,15}$/; + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setUsernameValid(false); + setHelperText(usernameError(message)); + }, + [setLoading, setUsernameValid, setHelperText] + ); - const setErrorMessage = (message: string) => { - setLoading(false); - setUsernameValid(false); - setHelperText(usernameError(message)); - }; + const runCheckUsername = useCallback( + (username) => { + wallet.openapi + .checkUsername(username.toLowerCase()) + .then((response) => { + setLoading(false); + if (response.data.username !== username.toLowerCase()) { + setLoading(false); + return; + } + if (response.data.unique) { + setUsernameValid(true); + setHelperText(usernameCorrect); + } else { + if (response.message === 'Username is reserved') { + setErrorMessage( + chrome.i18n.getMessage('This__username__is__reserved__Please__contact') + ); + } else { + setErrorMessage(chrome.i18n.getMessage('This__name__is__taken')); + } + } + }) + .catch(() => { + setErrorMessage(chrome.i18n.getMessage('Oops__unexpected__error')); + }); + }, + [setErrorMessage, setUsernameValid, setHelperText, usernameCorrect, wallet.openapi] + ); useEffect(() => { setUsernameValid(false); @@ -100,44 +142,26 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const delayDebounceFn = setTimeout(() => { if (username.length < 3) { setErrorMessage(chrome.i18n.getMessage('Too__short')); + setLoading(false); return; } if (username.length > 15) { setErrorMessage(chrome.i18n.getMessage('Too__long')); + setLoading(false); return; } + const regex = /^[A-Za-z0-9]{3,15}$/; if (!regex.test(username)) { setErrorMessage( chrome.i18n.getMessage('Your__username__can__only__contain__letters__and__numbers') ); + setLoading(false); return; } - wallet.openapi - .checkUsername(username.toLowerCase()) - .then((response) => { - setLoading(false); - if (response.data.username != username.toLowerCase()) { - setLoading(false); - return; - } - if (response.data.unique) { - setUsernameValid(true); - setHelperText(usernameCorrect); - } else { - if (response.message == 'Username is reserved') { - setErrorMessage( - chrome.i18n.getMessage('This__username__is__reserved__Please__contact') - ); - } else { - setErrorMessage(chrome.i18n.getMessage('This__name__is__taken')); - } - } - }) - .catch((error) => { - setErrorMessage(chrome.i18n.getMessage('Oops__unexpected__error')); - }); + + runCheckUsername(username); }, 500); return () => clearTimeout(delayDebounceFn); @@ -151,8 +175,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { }; return ( - - + <> {chrome.i18n.getMessage('Pick__Your')} @@ -196,20 +219,18 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { } /> - - {username && ( - - {helperText} - - )} - + + + {helperText} + + @@ -233,7 +254,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/RecoveryPhrase.tsx b/src/ui/views/AddWelcome/AddRegister/RecoveryPhrase.tsx index 1c2df908..4c5cd4b1 100644 --- a/src/ui/views/AddWelcome/AddRegister/RecoveryPhrase.tsx +++ b/src/ui/views/AddWelcome/AddRegister/RecoveryPhrase.tsx @@ -1,238 +1,234 @@ -import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, IconButton, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import InfoIcon from '@mui/icons-material/Info'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography, IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import IconCopy from '../../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; -import InfoIcon from '@mui/icons-material/Info'; const RecoveryPhrase = ({ handleClick, mnemonic }) => { const [canGoNext, setCanGoNext] = useState(false); const [isCoverBlur, coverBlur] = useState(true); return ( - - - - - {chrome.i18n.getMessage('Recovery')} - - {chrome.i18n.getMessage('Phrase')} - - - - {chrome.i18n.getMessage( - 'Write__down__this__phrase__in__this__exact__order__and__keep__them__safe' - )} - + + + {chrome.i18n.getMessage('Recovery')} + + {chrome.i18n.getMessage('Phrase')} + + + + {chrome.i18n.getMessage( + 'Write__down__this__phrase__in__this__exact__order__and__keep__them__safe' + )} + + - - {mnemonic.split(' ').map((word, i) => { - return ( + {mnemonic.split(' ').map((word, i) => { + return ( + - - {i + 1} - - - {word} - + {i + 1} - ); - })} + + {word} + + + ); + })} + { + coverBlur(!isCoverBlur); + }} + component="span" + sx={{ + position: 'absolute', + bottom: '0', + right: '0', + height: '40px', + width: '40px', + my: '16px', + mx: '24px', + backgroundColor: 'neutral1.main', + transition: 'all .3s ease-in-out', + justifySelf: 'end', + opacity: isCoverBlur ? 0 : 1, + // visibility: isCoverBlur ? 'hidden' : 'visible', + // ':hover': { + // bgcolor: '#41CC5D', + // }, + }} + > + + + + + {isCoverBlur && ( + { coverBlur(!isCoverBlur); + setCanGoNext(true); }} component="span" sx={{ - position: 'absolute', - bottom: '0', - right: '0', - height: '40px', - width: '40px', - my: '16px', - mx: '24px', backgroundColor: 'neutral1.main', - transition: 'all .3s ease-in-out', - justifySelf: 'end', - opacity: isCoverBlur ? 0 : 1, - // visibility: isCoverBlur ? 'hidden' : 'visible', // ':hover': { // bgcolor: '#41CC5D', // }, }} > - + + + {chrome.i18n.getMessage('Click__here__to__reveal__phrase')} + + )} + + + + + - {isCoverBlur && ( - - { - coverBlur(!isCoverBlur); - setCanGoNext(true); - }} - component="span" - sx={{ - backgroundColor: 'neutral1.main', - // ':hover': { - // bgcolor: '#41CC5D', - // }, - }} - > - - - - {chrome.i18n.getMessage('Click__here__to__reveal__phrase')} - - - )} - - - - - - - - + + - + + {chrome.i18n.getMessage('Okay__I__have__saved__it__properly')} + + - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/RegisterHeader.tsx b/src/ui/views/AddWelcome/AddRegister/RegisterHeader.tsx index 31399d20..fb499d7f 100644 --- a/src/ui/views/AddWelcome/AddRegister/RegisterHeader.tsx +++ b/src/ui/views/AddWelcome/AddRegister/RegisterHeader.tsx @@ -1,12 +1,11 @@ -import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography } from '@mui/material'; -import theme from '../../../style/LLTheme'; import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React from 'react'; const RegisterHeader = () => { return ( - + <> { - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/RepeatPhrase.tsx b/src/ui/views/AddWelcome/AddRegister/RepeatPhrase.tsx index 6d40db1d..7cc83c5a 100644 --- a/src/ui/views/AddWelcome/AddRegister/RepeatPhrase.tsx +++ b/src/ui/views/AddWelcome/AddRegister/RepeatPhrase.tsx @@ -1,12 +1,9 @@ -import React, { useState, useEffect } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; -import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; -import IconCopy from '../../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; import InfoIcon from '@mui/icons-material/Info'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback, useMemo } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; const randomElement = (list: any[]) => { return list[Math.floor(Math.random() * list.length)]; @@ -26,22 +23,28 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { const [selectedPhrase, setSelect] = useState([]); const [repeatArray, setRepeat] = useState([[], [], []]); - const mnemonicArray = mnemonic.split(' '); - const fullIndex = [...Array(mnemonicArray.length).keys()]; - const positionList: number[][] = chunkArray(fullIndex, Math.floor(mnemonicArray.length / 3)); + const mnemonicArray = useMemo(() => mnemonic.split(' '), [mnemonic]); + const fullIndex = useMemo(() => [...Array(mnemonicArray.length).keys()], [mnemonicArray]); + const positionList = useMemo( + () => chunkArray(fullIndex, Math.floor(mnemonicArray.length / 3)), + [fullIndex, mnemonicArray] + ); - const setSelected = (i, v) => { - const tempArray = selectedPhrase; - tempArray[i] = v; - setSelect([...tempArray]); - }; + const setSelected = useCallback( + (i, v) => { + const tempArray = selectedPhrase; + tempArray[i] = v; + setSelect([...tempArray]); + }, + [selectedPhrase] + ); const checkMatch = () => { const correctMatch = chosenIndex.map((index) => mnemonicArray[index]); if ( - selectedPhrase[0] == correctMatch[0] && - selectedPhrase[1] == correctMatch[1] && - selectedPhrase[2] == correctMatch[2] + selectedPhrase[0] === correctMatch[0] && + selectedPhrase[1] === correctMatch[1] && + selectedPhrase[2] === correctMatch[2] ) { handleClick(); return; @@ -55,7 +58,7 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { }, 5000); }; - const handleRandom = () => { + const handleRandom = useCallback(() => { const arr: number[] = []; // [[0,1,2,3],[4,5,6,7],[8,9,10,11]] const repeatIndex: number[][] = [[], [], []]; @@ -65,7 +68,7 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { positionList.forEach((list, i) => { const picked = randomElement(list); const exclude = fullIndex - .filter((item) => item != picked) + .filter((item) => item !== picked) .sort(() => { return Math.random() - 0.5; }); @@ -78,14 +81,13 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { }); setChosen(arr); setRepeat(repeatMap); - }; + }, [mnemonicArray, positionList]); useEffect(() => { handleRandom(); - }, []); + }, [handleRandom]); return ( - - + <> {chrome.i18n.getMessage('Verify') + ' '} @@ -152,14 +154,14 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { height: '100%', width: '100%', borderRadius: '8px', - backgroundColor: `${selectedPhrase[i] == v ? '#fff' : 'none'}`, + backgroundColor: `${selectedPhrase[i] === v ? '#fff' : 'none'}`, }} > {v} @@ -184,33 +186,27 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { justifyContent: 'flex-end', }} > - {incorrect && ( - - - - - {chrome.i18n.getMessage('Incorrect_recovery_phrases_please_try_again')} - - - - )} + + + + + {chrome.i18n.getMessage('Incorrect_recovery_phrases_please_try_again')} + + + - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/SetPassword.tsx b/src/ui/views/AddWelcome/AddRegister/SetPassword.tsx index 598394c0..3f765398 100644 --- a/src/ui/views/AddWelcome/AddRegister/SetPassword.tsx +++ b/src/ui/views/AddWelcome/AddRegister/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -12,22 +11,24 @@ import { InputAdornment, FormGroup, LinearProgress, - CssBaseline, + Checkbox, + FormControlLabel, } from '@mui/material'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; -import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; -import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; -import { AccountKey } from 'background/service/networkModel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; import HDWallet from 'ethereum-hdwallet'; -import { LLSpinner } from 'ui/FRWComponent'; +import React, { useEffect, useState } from 'react'; +import zxcvbn from 'zxcvbn'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { type AccountKey } from 'background/service/networkModel'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex, mixpanelBrowserService } from 'ui/utils'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; +import { BpUncheked, BpCheckedIcon } from '../../../FRWAssets/icons/CustomCheckboxIcons'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -63,32 +64,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -213,6 +188,8 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword, tempPassw await saveIndex(username); const accountKey = getAccountKey(mnemonic); + // track the time until account_created is called + mixpanelBrowserService.time('account_created'); wallet.openapi .register(accountKey, username) .then((response) => { @@ -238,8 +215,7 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword, tempPassw }; return ( - - + <> {chrome.i18n.getMessage('Confirm__Password')} @@ -280,16 +256,17 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword, tempPassw } /> - - {password && helperText} - + + + {helperText} + + - } + icon={} checkedIcon={} onChange={(event) => setCheck(event.target.checked)} /> @@ -345,7 +322,7 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword, tempPassw {errMessage} - + ); }; diff --git a/src/ui/views/AddWelcome/AddRegister/index.tsx b/src/ui/views/AddWelcome/AddRegister/index.tsx index ffc9ae3d..373c4f38 100644 --- a/src/ui/views/AddWelcome/AddRegister/index.tsx +++ b/src/ui/views/AddWelcome/AddRegister/index.tsx @@ -1,23 +1,24 @@ -import React, { useEffect, useState } from 'react'; -import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; import { IconButton, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import * as bip39 from 'bip39'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; + +import { LLPinAlert } from '@/ui/FRWComponent'; +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import { storage } from 'background/webapi'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from './RegisterHeader'; + +import AllSet from './AllSet'; +import GoogleBackup from './GoogleBackup'; import PickUsername from './PickUsername'; import RecoveryPhrase from './RecoveryPhrase'; +import RegisterHeader from './RegisterHeader'; import RepeatPhrase from './RepeatPhrase'; -import GoogleBackup from './GoogleBackup'; -import AllSet from './AllSet'; import SetPassword from './SetPassword'; -import Particles from 'react-tsparticles'; -import * as bip39 from 'bip39'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { LLPinAlert } from '@/ui/FRWComponent'; -import options from '../../Import/options'; -import { useWallet } from 'ui/utils'; -import { storage } from 'background/webapi'; enum Direction { Right, @@ -31,13 +32,13 @@ const AddRegister = () => { const [direction, setDirection] = useState(Direction.Right); const [username, setUsername] = useState(''); const [password, setPassword] = useState(null); - const [mnemonic, setMnemonic] = useState(bip39.generateMnemonic()); + const [mnemonic] = useState(bip39.generateMnemonic()); const getUsername = (username: string) => { setUsername(username.toLowerCase()); }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -49,14 +50,14 @@ const AddRegister = () => { .catch(() => { return; }); - }; + }, [wallet, history]); - const loadTempPassword = async () => { + const loadTempPassword = useCallback(async () => { const temp = await storage.get('tempPassword'); if (temp) { setPassword(temp); } - }; + }, []); const goNext = () => { setDirection(Direction.Right); @@ -115,12 +116,10 @@ const AddRegister = () => { useEffect(() => { loadView(); loadTempPassword(); - }, []); - - const height = [480, 600, 640, 620, 480, 480]; + }, [loadView, loadTempPassword]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 5 && ( - - )} + {activeIndex === 5 && } - + {/* height why not use auto */} @@ -189,30 +183,14 @@ const AddRegister = () => { - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/GoogleBackup.tsx b/src/ui/views/AddWelcome/AddressImport/GoogleBackup.tsx index e38e70a9..135de36c 100644 --- a/src/ui/views/AddWelcome/AddressImport/GoogleBackup.tsx +++ b/src/ui/views/AddWelcome/AddressImport/GoogleBackup.tsx @@ -1,12 +1,13 @@ +import InfoIcon from '@mui/icons-material/Info'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; + import IconGoogleDrive from '../../../../components/iconfont/IconGoogleDrive'; -import { LLSpinner } from 'ui/FRWComponent'; -import InfoIcon from '@mui/icons-material/Info'; -import { Presets } from 'react-component-transition'; const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { const wallets = useWallet(); @@ -33,8 +34,7 @@ const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { } }; return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -94,35 +94,29 @@ const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { - {backupErr && ( - - - {/* */} - - - {chrome.i18n.getMessage( - 'Backup_failed_you_may_still_conduct_backup_inside_extension' - )} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage( + 'Backup_failed_you_may_still_conduct_backup_inside_extension' + )} + + + - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/GoogleImport/DecryptWallet.tsx b/src/ui/views/AddWelcome/AddressImport/GoogleImport/DecryptWallet.tsx index 525d41f0..723901e5 100644 --- a/src/ui/views/AddWelcome/AddressImport/GoogleImport/DecryptWallet.tsx +++ b/src/ui/views/AddWelcome/AddressImport/GoogleImport/DecryptWallet.tsx @@ -1,22 +1,15 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { - Button, - Typography, - IconButton, - Input, - InputAdornment, - FormGroup, - CssBaseline, -} from '@mui/material'; -import CancelIcon from '../../../../../components/iconfont/IconClose'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; -import theme from '../../../../style/LLTheme'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import { Button, Typography, IconButton, Input, InputAdornment, FormGroup } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet } from 'ui/utils'; +import CancelIcon from '../../../../../components/iconfont/IconClose'; + // const helperTextStyles = makeStyles(() => ({ // root: { // size: '16px', @@ -123,8 +116,7 @@ const DecryptWallet = ({ handleClick, setMnemonic, username }) => { }, [password]); return ( - - + <> {chrome.i18n.getMessage('Welcome__Back')} @@ -168,7 +160,9 @@ const DecryptWallet = ({ handleClick, setMnemonic, username }) => { } /> - {password && helperText} + + {helperText} + @@ -192,7 +186,7 @@ const DecryptWallet = ({ handleClick, setMnemonic, username }) => { - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/GoogleImport/GoogleAccounts.tsx b/src/ui/views/AddWelcome/AddressImport/GoogleImport/GoogleAccounts.tsx index f5eb1ada..bcb4b65a 100644 --- a/src/ui/views/AddWelcome/AddressImport/GoogleImport/GoogleAccounts.tsx +++ b/src/ui/views/AddWelcome/AddressImport/GoogleImport/GoogleAccounts.tsx @@ -1,5 +1,4 @@ -import React, { useState, useEffect } from 'react'; -import { ThemeProvider } from '@mui/system'; +import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded'; import { Typography, Avatar, @@ -10,10 +9,9 @@ import { ListItemText, IconButton, ListItem, - CssBaseline, } from '@mui/material'; -import theme from '../../../../style/LLTheme'; -import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded'; +import React, { useState, useEffect, useCallback } from 'react'; + import { useWallet } from 'ui/utils'; const FetchAvatar = ({ username }) => { @@ -22,27 +20,27 @@ const FetchAvatar = ({ username }) => { ); const wallet = useWallet(); - const fetchUserAvatar = async (username) => { - const { data } = await wallet.openapi.searchUser(username); - const users = data.users; - if (users.length > 0 && users[0].avatar) { - setAvatar(users[0].avatar); - } - }; + const fetchUserAvatar = useCallback( + async (username) => { + const { data } = await wallet.openapi.searchUser(username); + const users = data.users; + if (users.length > 0 && users[0].avatar) { + setAvatar(users[0].avatar); + } + }, + [setAvatar, wallet.openapi] + ); useEffect(() => { fetchUserAvatar(username); - }, []); + }, [fetchUserAvatar, username]); return ; }; const GoogleAccounts = ({ handleClick, accounts, setUsername }) => { - const [canGoNext, setCanGoNext] = useState(true); - return ( - - + <> {chrome.i18n.getMessage('We__ve__found') + ' '} @@ -104,7 +102,7 @@ const GoogleAccounts = ({ handleClick, accounts, setUsername }) => { - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoverPassword.tsx b/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoverPassword.tsx index 8655cf9b..0276fb36 100644 --- a/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoverPassword.tsx +++ b/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,22 +10,19 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; - -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../../style/LLTheme'; + +import { LLSpinner, LLNotFound } from '@/ui/FRWComponent'; import { useWallet, saveIndex } from 'ui/utils'; -import { LLNotFound } from 'ui/FRWComponent'; -import { storage } from '@/background/webapi'; + +import CheckCircleIcon from '../../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../../components/iconfont/IconClose'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -232,11 +228,10 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { setPassword(''); setConfirmPassword(''); } - }, [isCheck]); + }, [isCheck, lastPassword]); return ( - - + <> {!showDialog ? ( @@ -333,7 +328,7 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { {errorMessage} - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoveryPhrase.tsx b/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoveryPhrase.tsx index e95f09f5..bdf0ad9d 100644 --- a/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoveryPhrase.tsx +++ b/src/ui/views/AddWelcome/AddressImport/GoogleImport/RecoveryPhrase.tsx @@ -1,20 +1,20 @@ -import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, IconButton, CssBaseline } from '@mui/material'; -import theme from '../../../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import InfoIcon from '@mui/icons-material/Info'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography, IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import IconCopy from '../../../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; -import InfoIcon from '@mui/icons-material/Info'; const RecoveryPhrase = ({ handleClick, mnemonic }) => { const [canGoNext, setCanGoNext] = useState(true); const [isCoverBlur, coverBlur] = useState(false); return ( - - + <> {chrome.i18n.getMessage('Review') + ' '} @@ -191,7 +191,7 @@ const RecoveryPhrase = ({ handleClick, mnemonic }) => { marginBottom: '8px', }} > - + { )} - + - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/GoogleImport/index.tsx b/src/ui/views/AddWelcome/AddressImport/GoogleImport/index.tsx index 4a38d0ea..eab1e689 100644 --- a/src/ui/views/AddWelcome/AddressImport/GoogleImport/index.tsx +++ b/src/ui/views/AddWelcome/AddressImport/GoogleImport/index.tsx @@ -1,20 +1,22 @@ -import React, { useEffect, useState } from 'react'; -import { useHistory, useLocation } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; import { IconButton, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; + +import { LLPinAlert } from '@/ui/FRWComponent'; +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { storage } from 'background/webapi'; + import BackButtonIcon from '../../../../../components/iconfont/IconBackButton'; -import theme from '../../../../style/LLTheme'; -import RegisterHeader from '../../../Register/RegisterHeader'; import AllSet from '../../../Register/AllSet'; +import RegisterHeader from '../../../Register/RegisterHeader'; + import DecryptWallet from './DecryptWallet'; -import RecoveryPhrase from './RecoveryPhrase'; import GoogleAccounts from './GoogleAccounts'; import RecoveryPassword from './RecoverPassword'; -import Particles from 'react-tsparticles'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { LLPinAlert } from '@/ui/FRWComponent'; -import { Options } from 'ui/utils'; -import { storage } from 'background/webapi'; +import RecoveryPhrase from './RecoveryPhrase'; enum Direction { Right, @@ -53,14 +55,14 @@ const GoogleImport = () => { } }; - const loadTempPassword = async () => { + const loadTempPassword = useCallback(async () => { const temp = await storage.get('tempPassword'); if (temp) { setPassword(temp); } - }; + }, []); - const getGoogleAccounts = async () => { + const getGoogleAccounts = useCallback(async () => { // const backupFile = await storage.get('googleBackup'); // await setBackup(backupFile); const users = location.state.accounts; @@ -71,12 +73,12 @@ const GoogleImport = () => { } else { setAccounts(users); } - }; + }, [location?.state?.accounts]); useEffect(() => { getGoogleAccounts(); loadTempPassword(); - }, []); + }, [getGoogleAccounts, loadTempPassword]); const page = (index) => { switch (index) { @@ -104,10 +106,8 @@ const GoogleImport = () => { } }; - const heights = [500, 500, 600, 600, 500]; - return ( - + <> { alignItems: 'center', }} > - {activeIndex == 4 && ( - - )} - + {activeIndex === 4 && } + { - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/ImportPager.tsx b/src/ui/views/AddWelcome/AddressImport/ImportPager.tsx index 668a216d..bd0bfd5d 100644 --- a/src/ui/views/AddWelcome/AddressImport/ImportPager.tsx +++ b/src/ui/views/AddWelcome/AddressImport/ImportPager.tsx @@ -44,7 +44,6 @@ const ImportPager = ({ setShowError, }) => { const [selectedTab, setSelectedTab] = useState(0); - const [isImport, setImport] = useState(false); const [mnemonicValid, setMnemonicValid] = useState(true); const [isSignLoading, setSignLoading] = useState(false); @@ -58,21 +57,16 @@ const ImportPager = ({ }; const handleImport = async (accountKey?: any) => { - if (accountKey.length > 1) { - setAccounts(accountKey); - setImport(true); + setAccounts(accountKey); + const result = await wallet.openapi.checkImport(accountKey[0].pubK); + if (result.status === 409) { + goPassword(); } else { - setAccounts(accountKey); - const result = await wallet.openapi.checkImport(accountKey[0].pubK); - if (result.status === 409) { - goPassword(); - } else { - if (!accountKey[0].address) { - handleNotFoundPopup(); - return; - } - handleClick(); + if (!accountKey[0].address) { + handleNotFoundPopup(); + return; } + handleClick(); } }; const setmnemonic = (mnemonic) => { @@ -82,22 +76,6 @@ const ImportPager = ({ storage.set('premnemonic', formatted); }; - const handleShowModel = (show) => { - setImport(show); - }; - - const handleAddressSelection = async (address) => { - const account = accounts.filter((account) => account.address === address)[0]; - const result = await wallet.openapi.checkImport(account.pubK); - if (result.status === 409) { - setAccounts([account]); - goPassword(); - } else { - setAccounts([account]); - handleClick(); - } - }; - const handleNotFoundPopup = async () => { setAddressFound(!addressFound); }; @@ -176,15 +154,6 @@ const ImportPager = ({ isGoback={true} /> )} - - {isImport && ( - - )} ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/PickUsername.tsx b/src/ui/views/AddWelcome/AddressImport/PickUsername.tsx index c93b36bd..fbb28246 100644 --- a/src/ui/views/AddWelcome/AddressImport/PickUsername.tsx +++ b/src/ui/views/AddWelcome/AddressImport/PickUsername.tsx @@ -1,16 +1,24 @@ -import React, { useEffect, useState } from 'react'; +import { + CircularProgress, + IconButton, + Button, + Typography, + FormControl, + Input, + InputAdornment, +} from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import CancelIcon from '../../../../components/iconfont/IconClose'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { useWallet } from 'ui/utils'; + import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import theme from '../../../style/LLTheme'; +import CancelIcon from '../../../../components/iconfont/IconClose'; import EmailIcon from '../../../assets/alternate-email.svg'; -import { Presets } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import { CircularProgress, IconButton } from '@mui/material'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_theme) => ({ customInputLabel: { '& legend': { visibility: 'visible', @@ -57,41 +65,78 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { ); - const usernameCorrect = ( - - - - {chrome.i18n.getMessage('Sounds_good')} - - + const usernameCorrect = useMemo( + () => ( + + + + {chrome.i18n.getMessage('Sounds_good')} + + + ), + [] ); - const usernameLoading = () => ( - - - {chrome.i18n.getMessage('Checking')} - + const usernameLoading = useMemo( + () => ( + + + {chrome.i18n.getMessage('Checking')} + + ), + [] ); const [username, setUsername] = useState(savedUsername || ''); const [helperText, setHelperText] = useState(
); - const regex = /^[A-Za-z0-9]{3,15}$/; + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setUsernameValid(false); + setHelperText(usernameError(message)); + }, + [setLoading, setUsernameValid, setHelperText] + ); - const setErrorMessage = (message: string) => { - setLoading(false); - setUsernameValid(false); - setHelperText(usernameError(message)); - }; + const runCheckUsername = useCallback( + (username) => { + wallet.openapi + .checkUsername(username.toLowerCase()) + .then((response) => { + setLoading(false); + if (response.data.username !== username.toLowerCase()) { + setLoading(false); + return; + } + if (response.data.unique) { + setUsernameValid(true); + setHelperText(usernameCorrect); + } else { + if (response.message === 'Username is reserved') { + setErrorMessage( + chrome.i18n.getMessage('This__username__is__reserved__Please__contact') + ); + } else { + setErrorMessage(chrome.i18n.getMessage('This__name__is__taken')); + } + } + }) + .catch(() => { + setErrorMessage(chrome.i18n.getMessage('Oops__unexpected__error')); + }); + }, + [setErrorMessage, setUsernameValid, setHelperText, usernameCorrect, wallet.openapi] + ); useEffect(() => { setUsernameValid(false); @@ -100,59 +145,40 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const delayDebounceFn = setTimeout(() => { if (username.length < 3) { setErrorMessage(chrome.i18n.getMessage('Too__short')); + setLoading(false); return; } if (username.length > 15) { setErrorMessage(chrome.i18n.getMessage('Too__long')); + setLoading(false); return; } + const regex = /^[A-Za-z0-9]{3,15}$/; if (!regex.test(username)) { setErrorMessage( chrome.i18n.getMessage('Your__username__can__only__contain__letters__and__numbers') ); + setLoading(false); return; } - wallet.openapi - .checkUsername(username.toLowerCase()) - .then((response) => { - setLoading(false); - if (response.data.username != username.toLowerCase()) { - setLoading(false); - return; - } - if (response.data.unique) { - setUsernameValid(true); - setHelperText(usernameCorrect); - } else { - if (response.message == 'Username is reserved') { - setErrorMessage( - chrome.i18n.getMessage('This__username__is__reserved__Please__contact') - ); - } else { - setErrorMessage(chrome.i18n.getMessage('This__name__is__taken')); - } - } - }) - .catch((error) => { - setErrorMessage(chrome.i18n.getMessage('Oops__unexpected__error')); - }); + + runCheckUsername(username); }, 500); return () => clearTimeout(delayDebounceFn); }, [username]); - const msgBgColor = () => { + const msgBgColor = useCallback(() => { if (isLoading) { return 'neutral.light'; } return usernameValid ? 'success.light' : 'error.light'; - }; + }, [isLoading, usernameValid]); return ( - - + <> {chrome.i18n.getMessage('Pick__Your')} @@ -196,20 +222,18 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { } /> - - {username && ( - - {helperText} - - )} - + + + {helperText} + + @@ -233,7 +257,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/RecoverPassword.tsx b/src/ui/views/AddWelcome/AddressImport/RecoverPassword.tsx index 93583041..902966a4 100644 --- a/src/ui/views/AddWelcome/AddressImport/RecoverPassword.tsx +++ b/src/ui/views/AddWelcome/AddressImport/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,13 +10,13 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; -import { LLSpinner } from 'ui/FRWComponent'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; + +import { LLSpinner } from 'ui/FRWComponent'; import { useWallet, saveIndex } from 'ui/utils'; import ErrorModel from '../../../FRWComponent/PopupModal/errorModel'; @@ -138,7 +137,6 @@ const SetPassword = ({ handleClick, mnemonic, pk, tempPassword, goEnd, accountKe const [password, setPassword] = useState(tempPassword); const [newKey, setKeyNew] = useState(true); - const [isImport, setImport] = useState(false); const [isLoading, setLoading] = useState(false); @@ -172,7 +170,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, tempPassword, goEnd, accountKe } catch (error) { setLoading(false); if (error.message === 'NoUserFound') { - setImport(false); + setLoading(false); } else { setKeyNew(false); } @@ -190,7 +188,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, tempPassword, goEnd, accountKe console.log(error); setLoading(false); if (error.message === 'NoUserFound') { - setImport(false); + setLoading(false); } else { setKeyNew(false); } @@ -223,8 +221,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, tempPassword, goEnd, accountKe }; return ( - - + <> {chrome.i18n.getMessage('Welcome__Back__import')} @@ -315,7 +312,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, tempPassword, goEnd, accountKe isGoback={true} /> )} - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/SetPassword.tsx b/src/ui/views/AddWelcome/AddressImport/SetPassword.tsx index f5cb3640..18e3f49e 100644 --- a/src/ui/views/AddWelcome/AddressImport/SetPassword.tsx +++ b/src/ui/views/AddWelcome/AddressImport/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -12,21 +11,24 @@ import { InputAdornment, FormGroup, LinearProgress, - CssBaseline, } from '@mui/material'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; -import { useWallet, getHashAlgo, getSignAlgo, saveIndex } from 'ui/utils'; + +import { storage } from '@/background/webapi'; +import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { AccountKey } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; -import { storage } from '@/background/webapi'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; +import { BpUncheked, BpCheckedIcon } from '../../../FRWAssets/icons/CustomCheckboxIcons'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -62,32 +64,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -151,13 +127,13 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, tempPassword, accoun setShowError(false); }; - const loadTempPassword = async () => { + const loadTempPassword = useCallback(async () => { setPassword(tempPassword); - }; + }, [tempPassword]); useEffect(() => { loadTempPassword(); - }, []); + }, [loadTempPassword]); const successInfo = (message) => { return ( @@ -205,68 +181,64 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, tempPassword, accoun const handleImport = async () => { setLoading(true); - if (accounts.length > 1) { - setLoading(true); - } else { - const accountKeyStruct = { - public_key: accounts[0].pubK, - sign_algo: getSignAlgo(accounts[0].signAlgo), - hash_algo: getHashAlgo(accounts[0].hashAlgo), - weight: 1000, - }; - const result = await wallet.openapi.getLocation(); - const installationId = await wallet.openapi.getInstallationId(); - const userlocation = result.data; - const device_info = { - city: userlocation.city, - continent: userlocation.country, - continentCode: userlocation.countryCode, - country: userlocation.country, - countryCode: userlocation.countryCode, - currency: userlocation.countryCode, - device_id: installationId, - district: '', - ip: userlocation.query, - isp: userlocation.as, - lat: userlocation.lat, - lon: userlocation.lon, - name: 'FRW Chrome Extension', - org: userlocation.org, - regionName: userlocation.regionName, - type: '2', - user_agent: 'Chrome', - zip: userlocation.zip, - }; - const address = accounts[0].address.replace(/^0x/, ''); - wallet.openapi - .importKey(accountKeyStruct, device_info, username, {}, address) - .then((response) => { - return wallet.boot(password); - }) - .then(async (response) => { - storage.remove('premnemonic'); + const accountKeyStruct = { + public_key: accounts[0].pubK, + sign_algo: getSignAlgo(accounts[0].signAlgo), + hash_algo: getHashAlgo(accounts[0].hashAlgo), + weight: 1000, + }; + const result = await wallet.openapi.getLocation(); + const installationId = await wallet.openapi.getInstallationId(); + const userlocation = result.data; + const device_info = { + city: userlocation.city, + continent: userlocation.country, + continentCode: userlocation.countryCode, + country: userlocation.country, + countryCode: userlocation.countryCode, + currency: userlocation.countryCode, + device_id: installationId, + district: '', + ip: userlocation.query, + isp: userlocation.as, + lat: userlocation.lat, + lon: userlocation.lon, + name: 'FRW Chrome Extension', + org: userlocation.org, + regionName: userlocation.regionName, + type: '2', + user_agent: 'Chrome', + zip: userlocation.zip, + }; + const address = accounts[0].address.replace(/^0x/, ''); + wallet.openapi + .importKey(accountKeyStruct, device_info, username, {}, address) + .then((response) => { + return wallet.boot(password); + }) + .then(async (response) => { + storage.remove('premnemonic'); - await saveIndex(username); - if (pk) { - return wallet.importPrivateKey(pk); - } else { - return wallet.createKeyringWithMnemonics(mnemonic); - } - }) - .then((address) => { - setLoading(false); - if (pk) { - goEnd(); - } else { - handleClick(); - } - }) - .catch((error) => { - console.log('error', error); - setShowError(true); - setLoading(false); - }); - } + await saveIndex(username); + if (pk) { + return wallet.importPrivateKey(pk); + } else { + return wallet.createKeyringWithMnemonics(mnemonic); + } + }) + .then((address) => { + setLoading(false); + if (pk) { + goEnd(); + } else { + handleClick(); + } + }) + .catch((error) => { + console.log('error', error); + setShowError(true); + setLoading(false); + }); }; useEffect(() => { @@ -280,8 +252,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, tempPassword, accoun }, [password]); return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -327,16 +298,16 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, tempPassword, accoun } /> - - {password && helperText} - + + {helperText} + } + icon={} checkedIcon={} onChange={(event) => setCheck(event.target.checked)} /> @@ -392,7 +363,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, tempPassword, accoun {errMessage} - + ); }; diff --git a/src/ui/views/AddWelcome/AddressImport/index.tsx b/src/ui/views/AddWelcome/AddressImport/index.tsx index 5991d6c7..73405e25 100644 --- a/src/ui/views/AddWelcome/AddressImport/index.tsx +++ b/src/ui/views/AddWelcome/AddressImport/index.tsx @@ -1,23 +1,23 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton, Typography, Snackbar, Alert } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import { storage } from 'background/webapi'; +import { LLPinAlert } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import IconGoogleDrive from '../../../../components/iconfont/IconGoogleDrive'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../../Register/RegisterHeader'; import AllSet from '../../Register/AllSet'; -import SeedPhrase from './importComponent/SeedPhrase'; -import PickUsername from './PickUsername'; -import SetPassword from './SetPassword'; +import RegisterHeader from '../../Register/RegisterHeader'; + import GoogleBackup from './GoogleBackup'; -import { storage } from 'background/webapi'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; import ImportPager from './ImportPager'; +import PickUsername from './PickUsername'; import RecoverPassword from './RecoverPassword'; +import SetPassword from './SetPassword'; enum Direction { Right, @@ -34,10 +34,8 @@ const AddressImport = () => { const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); const [showError, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); const [password, setPassword] = useState(null); const [accounts, setAccounts] = useState([]); - const [isImport, setImport] = useState(false); const getUsername = (username: string) => { setUsername(username.toLowerCase()); @@ -50,7 +48,7 @@ const AddressImport = () => { } }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -62,7 +60,7 @@ const AddressImport = () => { .catch(() => { return; }); - }; + }, [history, wallet]); const goNext = () => { setDirection(Direction.Right); if (activeIndex < 5) { @@ -166,12 +164,11 @@ const AddressImport = () => { }; useEffect(() => { - console.log('wallet'); loadView(); - }, []); + }, [loadView]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 5 && ( - - )} + {activeIndex === 5 && } - + {/* height why not use auto */} @@ -237,26 +229,75 @@ const AddressImport = () => { {chrome.i18n.getMessage('STEP')} {activeIndex + 1}/5 + + + + + + - + + + + + + + + + - {page(activeIndex)} - + + @@ -271,7 +312,7 @@ const AddressImport = () => { - + ); }; diff --git a/src/ui/views/AddWelcome/ProxySync/ProxyQr.tsx b/src/ui/views/AddWelcome/ProxySync/ProxyQr.tsx index 13cfb93a..4c5feb3f 100644 --- a/src/ui/views/AddWelcome/ProxySync/ProxyQr.tsx +++ b/src/ui/views/AddWelcome/ProxySync/ProxyQr.tsx @@ -1,17 +1,17 @@ -import React, { useEffect, useCallback, useState } from 'react'; +import { Typography } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import { useWallet } from 'ui/utils'; +import { Box } from '@mui/system'; import { Core } from '@walletconnect/core'; -import { FCLWalletConnectMethod } from '@/ui/utils/type'; import SignClient from '@walletconnect/sign-client'; -import { PairingTypes, SessionTypes } from '@walletconnect/types'; +import { type SessionTypes } from '@walletconnect/types'; import * as bip39 from 'bip39'; -import { storage } from 'background/webapi'; +import React, { useEffect, useCallback, useState } from 'react'; import { QRCode } from 'react-qrcode-logo'; + +import { FCLWalletConnectMethod } from '@/ui/utils/type'; +import { storage } from 'background/webapi'; import lilo from 'ui/FRWAssets/image/lilo.png'; +import { useWallet } from 'ui/utils'; interface DeviceInfoRequest { deviceId: string; @@ -37,7 +37,7 @@ interface DeviceInfoRequest { device_id?: string; } -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_theme) => ({ customInputLabel: { '& legend': { visibility: 'visible', @@ -74,24 +74,117 @@ const ProxyQr = ({ const [loading, setShowLoading] = useState(false); const [session, setSession] = useState(); const [mnemonic, setMnemonic] = useState(bip39.generateMnemonic()); - const [currentNetwork, setNetwork] = useState( - process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet' - ); + const [currentNetwork, setNetwork] = useState('mainnet'); - const loadNetwork = async () => { + const loadNetwork = useCallback(async () => { const currentNetwork = await usewallet.getNetwork(); setNetwork(currentNetwork); - }; + }, [usewallet]); useEffect(() => { loadNetwork(); + }, [loadNetwork]); + + const onSessionConnected = useCallback(async (_session: SessionTypes.Struct) => { + console.log('_session ', _session); + setShowLoading(true); + setSession(_session); }, []); + const _subscribeToEvents = useCallback( + async (_client: SignClient) => { + if (typeof _client === 'undefined') { + throw new Error('WalletConnect is not initialized'); + } + + _client.on('session_update', ({ topic, params }) => { + console.log('EVENT', 'session_update', { topic, params }); + const { namespaces } = params; + const _session = _client.session.get(topic); + const updatedSession = { ..._session, namespaces }; + onSessionConnected(updatedSession); + }); + console.log('EVENT _client ', _client); + }, + [onSessionConnected] + ); + + const getDeviceInfo = useCallback(async (): Promise => { + const result = await usewallet.openapi.getLocation(); + const installationId = await usewallet.openapi.getInstallationId(); + // console.log('location ', userlocation); + const userlocation = result.data; + const deviceInfo: DeviceInfoRequest = { + city: userlocation.city, + continent: userlocation.country, + continentCode: userlocation.countryCode, + country: userlocation.country, + countryCode: userlocation.countryCode, + currency: userlocation.countryCode, + deviceId: installationId, + device_id: installationId, + district: '', + ip: userlocation.query, + isp: userlocation.as, + lat: userlocation.lat, + lon: userlocation.lon, + name: 'FRW Chrome Extension', + org: userlocation.org, + regionName: userlocation.regionName, + type: '2', + userAgent: 'Chrome', + zip: userlocation.zip, + }; + return deviceInfo; + }, [usewallet]); + + const sendRequest = useCallback( + async (wallet: SignClient, topic: string) => { + console.log(wallet); + const deviceInfo: DeviceInfoRequest = await getDeviceInfo(); + const jwtToken = await usewallet.requestProxyToken(); + wallet + .request({ + topic: topic, + chainId: `flow:${currentNetwork}`, + request: { + method: FCLWalletConnectMethod.proxyaccount, + params: { + method: FCLWalletConnectMethod.proxyaccount, + data: { + deviceInfo: deviceInfo, + jwt: jwtToken, + }, + }, + }, + }) + .then(async (result: any) => { + console.log(result); + const jsonObject = JSON.parse(result); + const accountKey = { + public_key: jsonObject.data.publicKey, + hash_algo: Number(jsonObject.data.hashAlgo), + sign_algo: Number(jsonObject.data.signAlgo), + weight: Number(jsonObject.data.weight), + }; + usewallet.openapi.loginV3(accountKey, deviceInfo, jsonObject.data.signature); + storage.set(`${jsonObject.data.userId}Topic`, topic); + confirmMnemonic(mnemonic); + confirmPk(jsonObject.data.publicKey); + console.log('jsonObject ', jsonObject); + handleClick(); + }) + .catch((error) => { + console.error('Error in first wallet request:', error); + }); + }, + [usewallet, currentNetwork, confirmMnemonic, confirmPk, mnemonic, handleClick, getDeviceInfo] + ); + useEffect(() => { const createWeb3Wallet = async () => { try { const wallet = await SignClient.init({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Unreachable code error core: new Core({ projectId: process.env.WC_PROJECTID, @@ -143,104 +236,10 @@ const ProxyQr = ({ } }; createWeb3Wallet(); - }, []); - - const onSessionConnected = useCallback(async (_session: SessionTypes.Struct) => { - console.log('_session ', _session); - setShowLoading(true); - setSession(_session); - }, []); - - const _subscribeToEvents = useCallback( - async (_client: SignClient) => { - if (typeof _client === 'undefined') { - throw new Error('WalletConnect is not initialized'); - } - - _client.on('session_update', ({ topic, params }) => { - console.log('EVENT', 'session_update', { topic, params }); - const { namespaces } = params; - const _session = _client.session.get(topic); - const updatedSession = { ..._session, namespaces }; - onSessionConnected(updatedSession); - }); - console.log('EVENT _client ', _client); - }, - [onSessionConnected] - ); - - async function sendRequest(wallet: SignClient, topic: string) { - console.log(wallet); - const deviceInfo: DeviceInfoRequest = await getDeviceInfo(); - const jwtToken = await usewallet.requestProxyToken(); - wallet - .request({ - topic: topic, - chainId: `flow:${currentNetwork}`, - request: { - method: FCLWalletConnectMethod.proxyaccount, - params: { - method: FCLWalletConnectMethod.proxyaccount, - data: { - deviceInfo: deviceInfo, - jwt: jwtToken, - }, - }, - }, - }) - .then(async (result: any) => { - console.log(result); - const jsonObject = JSON.parse(result); - const accountKey = { - public_key: jsonObject.data.publicKey, - hash_algo: Number(jsonObject.data.hashAlgo), - sign_algo: Number(jsonObject.data.signAlgo), - weight: Number(jsonObject.data.weight), - }; - usewallet.openapi.loginV3(accountKey, deviceInfo, jsonObject.data.signature); - storage.set(`${jsonObject.data.userId}Topic`, topic); - confirmMnemonic(mnemonic); - confirmPk(jsonObject.data.publicKey); - console.log('jsonObject ', jsonObject); - handleClick(); - }) - .catch((error) => { - console.error('Error in first wallet request:', error); - }); - } - - const getDeviceInfo = async (): Promise => { - const result = await usewallet.openapi.getLocation(); - const installationId = await usewallet.openapi.getInstallationId(); - // console.log('location ', userlocation); - const userlocation = result.data; - const deviceInfo: DeviceInfoRequest = { - city: userlocation.city, - continent: userlocation.country, - continentCode: userlocation.countryCode, - country: userlocation.country, - countryCode: userlocation.countryCode, - currency: userlocation.countryCode, - deviceId: installationId, - device_id: installationId, - district: '', - ip: userlocation.query, - isp: userlocation.as, - lat: userlocation.lat, - lon: userlocation.lon, - name: 'FRW Chrome Extension', - org: userlocation.org, - regionName: userlocation.regionName, - type: '2', - userAgent: 'Chrome', - zip: userlocation.zip, - }; - return deviceInfo; - }; + }, [_subscribeToEvents, currentNetwork, onSessionConnected, sendRequest]); return ( - - + <> {/* */} - + ); }; diff --git a/src/ui/views/AddWelcome/ProxySync/RegisterHeader.tsx b/src/ui/views/AddWelcome/ProxySync/RegisterHeader.tsx index 31399d20..fb499d7f 100644 --- a/src/ui/views/AddWelcome/ProxySync/RegisterHeader.tsx +++ b/src/ui/views/AddWelcome/ProxySync/RegisterHeader.tsx @@ -1,12 +1,11 @@ -import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography } from '@mui/material'; -import theme from '../../../style/LLTheme'; import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React from 'react'; const RegisterHeader = () => { return ( - + <> { - + ); }; diff --git a/src/ui/views/AddWelcome/ProxySync/SetPassword.tsx b/src/ui/views/AddWelcome/ProxySync/SetPassword.tsx index 47839d40..6ec9a061 100644 --- a/src/ui/views/AddWelcome/ProxySync/SetPassword.tsx +++ b/src/ui/views/AddWelcome/ProxySync/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,18 +10,19 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -243,8 +243,7 @@ const SetPassword = ({ }, [password]); return ( - - + <> } /> - {password && helperText} + + {helperText} + @@ -372,7 +373,7 @@ const SetPassword = ({ - + ); }; diff --git a/src/ui/views/AddWelcome/ProxySync/index.tsx b/src/ui/views/AddWelcome/ProxySync/index.tsx index 1ac2f301..6e2cdf1f 100644 --- a/src/ui/views/AddWelcome/ProxySync/index.tsx +++ b/src/ui/views/AddWelcome/ProxySync/index.tsx @@ -1,18 +1,20 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLPinAlert } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import IconGoogleDrive from '../../../../components/iconfont/IconGoogleDrive'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../AddRegister/RegisterHeader'; import AllSet from '../AddRegister/AllSet'; -import SetPassword from './SetPassword'; +import RegisterHeader from '../AddRegister/RegisterHeader'; + import ProxyQr from './ProxyQr'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; +import SetPassword from './SetPassword'; enum Direction { Right, @@ -26,10 +28,7 @@ const ProxySync = () => { const [publickey, setPubkey] = useState(''); const [mnemonic, setMnemonic] = useState(''); const [username, setUsername] = useState(''); - const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); - const [showError, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); const [accountKey, setAccountKey] = useState(null); const [deviceInfo, setDeviceInfo] = useState(null); @@ -37,7 +36,7 @@ const ProxySync = () => { setUsername(username.toLowerCase()); }; - const loadView = async () => { + const loadView = useCallback(async () => { wallet .getCurrentAccount() .then((res) => { @@ -48,7 +47,7 @@ const ProxySync = () => { .catch(() => { return; }); - }; + }, [history, wallet]); const goNext = () => { setDirection(Direction.Right); if (activeIndex < 2) { @@ -67,13 +66,6 @@ const ProxySync = () => { } }; - const handleErrorClose = (event?: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway') { - return; - } - setShowError(false); - }; - const page = (index) => { switch (index) { case 0: @@ -109,10 +101,10 @@ const ProxySync = () => { useEffect(() => { loadView(); - }, []); + }, [loadView]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 2 && ( - - )} + {activeIndex === 2 && } - + {/* height why not use auto */} @@ -160,31 +147,15 @@ const ProxySync = () => { )} - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/AddWelcome/Sync/RegisterHeader.tsx b/src/ui/views/AddWelcome/Sync/RegisterHeader.tsx index 31399d20..fb499d7f 100644 --- a/src/ui/views/AddWelcome/Sync/RegisterHeader.tsx +++ b/src/ui/views/AddWelcome/Sync/RegisterHeader.tsx @@ -1,12 +1,11 @@ -import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography } from '@mui/material'; -import theme from '../../../style/LLTheme'; import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React from 'react'; const RegisterHeader = () => { return ( - + <> { - + ); }; diff --git a/src/ui/views/AddWelcome/Sync/SetPassword.tsx b/src/ui/views/AddWelcome/Sync/SetPassword.tsx index 86e3d561..dbac7f00 100644 --- a/src/ui/views/AddWelcome/Sync/SetPassword.tsx +++ b/src/ui/views/AddWelcome/Sync/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,18 +10,19 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -237,8 +237,7 @@ const SetPassword = ({ handleClick, mnemonic, username, setUsername, accountKey, }, [password]); return ( - - + <> } /> - {password && helperText} + + {helperText} + @@ -366,7 +367,7 @@ const SetPassword = ({ handleClick, mnemonic, username, setUsername, accountKey, - + ); }; diff --git a/src/ui/views/AddWelcome/Sync/SyncQr.tsx b/src/ui/views/AddWelcome/Sync/SyncQr.tsx index 8716a58f..19e15144 100644 --- a/src/ui/views/AddWelcome/Sync/SyncQr.tsx +++ b/src/ui/views/AddWelcome/Sync/SyncQr.tsx @@ -1,17 +1,17 @@ -import React, { useEffect, useCallback, useState } from 'react'; +import { Typography } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import { useWallet } from 'ui/utils'; +import { Box } from '@mui/system'; import { Core } from '@walletconnect/core'; -import { FCLWalletConnectMethod } from '@/ui/utils/type'; import SignClient from '@walletconnect/sign-client'; -import { PairingTypes, SessionTypes } from '@walletconnect/types'; +import { type SessionTypes } from '@walletconnect/types'; import * as bip39 from 'bip39'; import HDWallet from 'ethereum-hdwallet'; +import React, { useEffect, useCallback, useState } from 'react'; import { QRCode } from 'react-qrcode-logo'; + +import { FCLWalletConnectMethod } from '@/ui/utils/type'; import lilo from 'ui/FRWAssets/image/lilo.png'; +import { useWallet } from 'ui/utils'; interface AccountKey { hashAlgo: number; @@ -80,73 +80,16 @@ const SyncQr = ({ const [loading, setShowLoading] = useState(false); const [session, setSession] = useState(); const [mnemonic, setMnemonic] = useState(bip39.generateMnemonic()); - const [currentNetwork, setNetwork] = useState( - process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet' - ); + const [currentNetwork, setNetwork] = useState('mainnet'); - const loadNetwork = async () => { + const loadNetwork = useCallback(async () => { const currentNetwork = await usewallet.getNetwork(); setNetwork(currentNetwork); - }; + }, [usewallet]); useEffect(() => { loadNetwork(); - }, []); - - useEffect(() => { - const createWeb3Wallet = async () => { - try { - const wallet = await SignClient.init({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore: Unreachable code error - core: new Core({ - projectId: process.env.WC_PROJECTID, - }), - metadata: { - name: 'Flow Walllet', - description: 'Digital wallet created for everyone.', - url: 'https://fcw-link.lilico.app', - icons: ['https://fcw-link.lilico.app/logo.png'], - }, - }); - await _subscribeToEvents(wallet); - - try { - const { uri, approval } = await wallet.connect({ - requiredNamespaces: { - flow: { - methods: [FCLWalletConnectMethod.accountInfo, FCLWalletConnectMethod.addDeviceInfo], - chains: [`flow:${currentNetwork}`], - events: [], - }, - }, - }); - - // Open QRCode modal if a URI was returned (i.e. we're not connecting an existing pairing). - if (uri) { - console.log('uri ', uri); - await setUri(uri); - // Await session approval from the wallet. - const session = await approval(); - await onSessionConnected(session); - - console.log('session ', session); - sendRequest(wallet, session.topic); - - // onSessionConnect(session) - // Close the QRCode modal in case it was open. - } - } catch (e) { - console.error(e); - } - await setWeb3Wallet(wallet); - console.log('web3wallet', web3wallet); - } catch (e) { - console.error(e); - } - }; - createWeb3Wallet(); - }, []); + }, [loadNetwork]); const onSessionConnected = useCallback(async (_session: SessionTypes.Struct) => { console.log('_session ', _session); @@ -171,73 +114,7 @@ const SyncQr = ({ }, [onSessionConnected] ); - - async function sendRequest(wallet: SignClient, topic: string) { - console.log(wallet); - wallet - .request({ - topic: topic, - chainId: `flow:${currentNetwork}`, - request: { - method: FCLWalletConnectMethod.accountInfo, - params: [], - }, - }) - .then(async (result: any) => { - console.log('result ', result); - const jsonObject = JSON.parse(result); - console.log('jsonObject ', jsonObject); - if (jsonObject.method === FCLWalletConnectMethod.accountInfo) { - const accountKey: AccountKey = getAccountKey(); - const deviceInfo: DeviceInfoRequest = await getDeviceInfo(); - const ak = { - public_key: accountKey.publicKey, - hash_algo: accountKey.hashAlgo, - sign_algo: accountKey.signAlgo, - weight: accountKey.weight, - }; - console.log('sent ->', accountKey); - confirmMnemonic(mnemonic); - setAccountKey(ak); - setDeviceInfo(deviceInfo); - wallet - .request({ - topic: topic, - chainId: `flow:${currentNetwork}`, - request: { - method: FCLWalletConnectMethod.addDeviceInfo, - params: { - method: '', - data: { - username: '', - accountKey: accountKey, - deviceInfo: deviceInfo, - }, - }, - }, - }) - .then(async (sent) => { - handleClick(); - // usewallet.signInV3(mnemonic, ak, deviceInfo).then(async (result) => { - - // const userInfo = await usewallet.getUserInfo(true); - // setUsername(userInfo.username); - // handleClick(); - // }).catch((error) => { - // console.error('Error in sign in wallet request:', error); - // }); - }) - .catch((error) => { - console.error('Error in second wallet request:', error); - }); - } - }) - .catch((error) => { - console.error('Error in first wallet request:', error); - }); - } - - const getAccountKey = () => { + const getAccountKey = useCallback(() => { const hdwallet = HDWallet.fromMnemonic(mnemonic); const publicKey = hdwallet.derive("m/44'/539'/0'/0/0").getPublicKey().toString('hex'); const key: AccountKey = { @@ -247,9 +124,9 @@ const SyncQr = ({ publicKey: publicKey, }; return key; - }; + }, [mnemonic]); - const getDeviceInfo = async (): Promise => { + const getDeviceInfo = useCallback(async (): Promise => { const result = await usewallet.openapi.getLocation(); const installationId = await usewallet.openapi.getInstallationId(); // console.log('location ', userlocation); @@ -276,11 +153,141 @@ const SyncQr = ({ zip: userlocation.zip, }; return deviceInfo; - }; + }, [usewallet]); + + const sendRequest = useCallback( + async (wallet: SignClient, topic: string) => { + console.log(wallet); + wallet + .request({ + topic: topic, + chainId: `flow:${currentNetwork}`, + request: { + method: FCLWalletConnectMethod.accountInfo, + params: [], + }, + }) + .then(async (result: any) => { + console.log('result ', result); + const jsonObject = JSON.parse(result); + console.log('jsonObject ', jsonObject); + if (jsonObject.method === FCLWalletConnectMethod.accountInfo) { + const accountKey: AccountKey = getAccountKey(); + const deviceInfo: DeviceInfoRequest = await getDeviceInfo(); + const ak = { + public_key: accountKey.publicKey, + hash_algo: accountKey.hashAlgo, + sign_algo: accountKey.signAlgo, + weight: accountKey.weight, + }; + console.log('sent ->', accountKey); + confirmMnemonic(mnemonic); + setAccountKey(ak); + setDeviceInfo(deviceInfo); + wallet + .request({ + topic: topic, + chainId: `flow:${currentNetwork}`, + request: { + method: FCLWalletConnectMethod.addDeviceInfo, + params: { + method: '', + data: { + username: '', + accountKey: accountKey, + deviceInfo: deviceInfo, + }, + }, + }, + }) + .then(async (sent) => { + handleClick(); + // usewallet.signInV3(mnemonic, ak, deviceInfo).then(async (result) => { + + // const userInfo = await usewallet.getUserInfo(true); + // setUsername(userInfo.username); + // handleClick(); + // }).catch((error) => { + // console.error('Error in sign in wallet request:', error); + // }); + }) + .catch((error) => { + console.error('Error in second wallet request:', error); + }); + } + }) + .catch((error) => { + console.error('Error in first wallet request:', error); + }); + }, + [ + confirmMnemonic, + currentNetwork, + getAccountKey, + getDeviceInfo, + handleClick, + mnemonic, + setAccountKey, + setDeviceInfo, + ] + ); + + useEffect(() => { + const createWeb3Wallet = async () => { + try { + const wallet = await SignClient.init({ + // @ts-ignore: Unreachable code error + core: new Core({ + projectId: process.env.WC_PROJECTID, + }), + metadata: { + name: 'Flow Walllet', + description: 'Digital wallet created for everyone.', + url: 'https://fcw-link.lilico.app', + icons: ['https://fcw-link.lilico.app/logo.png'], + }, + }); + await _subscribeToEvents(wallet); + + try { + const { uri, approval } = await wallet.connect({ + requiredNamespaces: { + flow: { + methods: [FCLWalletConnectMethod.accountInfo, FCLWalletConnectMethod.addDeviceInfo], + chains: [`flow:${currentNetwork}`], + events: [], + }, + }, + }); + + // Open QRCode modal if a URI was returned (i.e. we're not connecting an existing pairing). + if (uri) { + console.log('uri ', uri); + await setUri(uri); + // Await session approval from the wallet. + const session = await approval(); + await onSessionConnected(session); + + console.log('session ', session); + sendRequest(wallet, session.topic); + + // onSessionConnect(session) + // Close the QRCode modal in case it was open. + } + } catch (e) { + console.error(e); + } + await setWeb3Wallet(wallet); + console.log('web3wallet', web3wallet); + } catch (e) { + console.error(e); + } + }; + createWeb3Wallet(); + }, [_subscribeToEvents, currentNetwork, onSessionConnected, sendRequest, web3wallet]); return ( - - + <> {/* */} - + ); }; diff --git a/src/ui/views/AddWelcome/Sync/index.tsx b/src/ui/views/AddWelcome/Sync/index.tsx index e5a21829..79e54925 100644 --- a/src/ui/views/AddWelcome/Sync/index.tsx +++ b/src/ui/views/AddWelcome/Sync/index.tsx @@ -1,18 +1,20 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLPinAlert } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import IconGoogleDrive from '../../../../components/iconfont/IconGoogleDrive'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../AddRegister/RegisterHeader'; import AllSet from '../AddRegister/AllSet'; +import RegisterHeader from '../AddRegister/RegisterHeader'; + import SetPassword from './SetPassword'; import SyncQr from './SyncQr'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; enum Direction { Right, @@ -25,10 +27,7 @@ const Sync = () => { const [activeIndex, onChange] = useState(0); const [mnemonic, setMnemonic] = useState(''); const [username, setUsername] = useState(''); - const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); - const [showError, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); const [accountKey, setAccountKey] = useState(null); const [deviceInfo, setDeviceInfo] = useState(null); @@ -36,7 +35,7 @@ const Sync = () => { setUsername(username.toLowerCase()); }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -48,7 +47,7 @@ const Sync = () => { .catch(() => { return; }); - }; + }, [history, wallet]); const goNext = () => { setDirection(Direction.Right); if (activeIndex < 2) { @@ -67,13 +66,6 @@ const Sync = () => { } }; - const handleErrorClose = (event?: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway') { - return; - } - setShowError(false); - }; - const page = (index) => { switch (index) { case 0: @@ -106,12 +98,11 @@ const Sync = () => { }; useEffect(() => { - console.log('wallet'); loadView(); - }, []); + }, [loadView]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 2 && ( - - )} + {activeIndex === 2 && } - + {/* height why not use auto */} @@ -159,31 +145,15 @@ const Sync = () => { )} - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/AddWelcome/index.tsx b/src/ui/views/AddWelcome/index.tsx index 559b595f..c7f9fa9c 100644 --- a/src/ui/views/AddWelcome/index.tsx +++ b/src/ui/views/AddWelcome/index.tsx @@ -1,20 +1,19 @@ +import { Typography, Button, CardMedia } from '@mui/material'; +import { Box } from '@mui/system'; import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Typography, Button, CssBaseline, CardMedia } from '@mui/material'; -import theme from '../../style/LLTheme'; -import RegisterHeader from '../Register/RegisterHeader'; +import { Link } from 'react-router-dom'; + +import IconFlow from '../../../components/iconfont/IconFlow'; import appicon from '../../FRWAssets/image/appicon.png'; import create from '../../FRWAssets/svg/create.svg'; import importPng from '../../FRWAssets/svg/import.svg'; -import qr from '../../FRWAssets/svg/scanIcon.svg'; import outside from '../../FRWAssets/svg/importoutside.svg'; -import { Link } from 'react-router-dom'; -import IconFlow from '../../../components/iconfont/IconFlow'; +import qr from '../../FRWAssets/svg/scanIcon.svg'; +import RegisterHeader from '../Register/RegisterHeader'; const AddWelcome = () => { return ( - - + <> { margin: '24px 0 44px', }} > - {/* {chrome.i18n.getMessage('appDescription')} {' '} */} - {chrome.i18n.getMessage('A_crypto_wallet_on_Flow')} - - {chrome.i18n.getMessage('Explorers_Collectors_and_Gamers')} - + {chrome.i18n.getMessage('A_crypto_wallet_on_Flow')}{' '} + + {chrome.i18n.getMessage('Explorers_Collectors_and_Gamers')} + - {/* - */} - - + ); }; diff --git a/src/ui/views/AddressImport/GoogleImport/DecryptWallet.tsx b/src/ui/views/AddressImport/GoogleImport/DecryptWallet.tsx index 85d3d3cb..53660340 100644 --- a/src/ui/views/AddressImport/GoogleImport/DecryptWallet.tsx +++ b/src/ui/views/AddressImport/GoogleImport/DecryptWallet.tsx @@ -1,22 +1,15 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { - Button, - Typography, - IconButton, - Input, - InputAdornment, - FormGroup, - CssBaseline, -} from '@mui/material'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; -import theme from '../../../style/LLTheme'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import { Button, Typography, IconButton, Input, InputAdornment, FormGroup } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet } from 'ui/utils'; +import CancelIcon from '../../../../components/iconfont/IconClose'; + // const helperTextStyles = makeStyles(() => ({ // root: { // size: '16px', @@ -124,8 +117,7 @@ const DecryptWallet = ({ handleClick, setMnemonic, username, setNextPassword }) }, [password]); return ( - - + <> {chrome.i18n.getMessage('Welcome__Back')} @@ -169,7 +161,9 @@ const DecryptWallet = ({ handleClick, setMnemonic, username, setNextPassword }) } /> - {password && helperText} + + {helperText} + @@ -193,7 +187,7 @@ const DecryptWallet = ({ handleClick, setMnemonic, username, setNextPassword }) - + ); }; diff --git a/src/ui/views/AddressImport/GoogleImport/GoogleAccounts.tsx b/src/ui/views/AddressImport/GoogleImport/GoogleAccounts.tsx index 76cc4e6f..2b91ed3a 100644 --- a/src/ui/views/AddressImport/GoogleImport/GoogleAccounts.tsx +++ b/src/ui/views/AddressImport/GoogleImport/GoogleAccounts.tsx @@ -1,5 +1,4 @@ -import React, { useState, useEffect } from 'react'; -import { ThemeProvider } from '@mui/system'; +import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded'; import { Typography, Avatar, @@ -10,10 +9,9 @@ import { ListItemText, IconButton, ListItem, - CssBaseline, } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded'; +import React, { useState, useEffect, useCallback } from 'react'; + import { useWallet } from 'ui/utils'; const FetchAvatar = ({ username }) => { @@ -22,27 +20,27 @@ const FetchAvatar = ({ username }) => { ); const wallet = useWallet(); - const fetchUserAvatar = async (username) => { - const { data } = await wallet.openapi.searchUser(username); - const users = data.users; - if (users.length > 0 && users[0].avatar) { - setAvatar(users[0].avatar); - } - }; + const fetchUserAvatar = useCallback( + async (username) => { + const { data } = await wallet.openapi.searchUser(username); + const users = data.users; + if (users.length > 0 && users[0].avatar) { + setAvatar(users[0].avatar); + } + }, + [wallet] + ); useEffect(() => { fetchUserAvatar(username); - }, []); + }, [fetchUserAvatar, username]); return ; }; const GoogleAccounts = ({ handleClick, accounts, setUsername }) => { - const [canGoNext, setCanGoNext] = useState(true); - return ( - - + <> {chrome.i18n.getMessage('We__ve__found') + ' '} @@ -104,7 +102,7 @@ const GoogleAccounts = ({ handleClick, accounts, setUsername }) => { - + ); }; diff --git a/src/ui/views/AddressImport/GoogleImport/RecoverPassword.tsx b/src/ui/views/AddressImport/GoogleImport/RecoverPassword.tsx index 36cab46f..2adce01b 100644 --- a/src/ui/views/AddressImport/GoogleImport/RecoverPassword.tsx +++ b/src/ui/views/AddressImport/GoogleImport/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,21 +10,21 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; - -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; + +import { LLSpinner, LLNotFound } from '@/ui/FRWComponent'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet, saveIndex } from 'ui/utils'; -import { LLNotFound } from 'ui/FRWComponent'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; +import { BpUncheked, BpCheckedIcon } from '../../../FRWAssets/icons/CustomCheckboxIcons'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -68,32 +67,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -253,11 +226,10 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { setPassword(''); setConfirmPassword(''); } - }, [isCheck]); + }, [isCheck, lastPassword]); return ( - - + <> {!showDialog ? ( @@ -305,7 +277,9 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + @@ -340,7 +314,7 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { control={ } + icon={} checkedIcon={} onChange={(event) => setCheck(event.target.checked)} /> @@ -383,7 +357,7 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { {errorMessage} - + ); }; diff --git a/src/ui/views/AddressImport/GoogleImport/RecoveryPhrase.tsx b/src/ui/views/AddressImport/GoogleImport/RecoveryPhrase.tsx index c9e2a32f..456f377a 100644 --- a/src/ui/views/AddressImport/GoogleImport/RecoveryPhrase.tsx +++ b/src/ui/views/AddressImport/GoogleImport/RecoveryPhrase.tsx @@ -1,20 +1,20 @@ -import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, IconButton, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import InfoIcon from '@mui/icons-material/Info'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography, IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import IconCopy from '../../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; -import InfoIcon from '@mui/icons-material/Info'; const RecoveryPhrase = ({ handleClick, mnemonic }) => { const [canGoNext, setCanGoNext] = useState(true); const [isCoverBlur, coverBlur] = useState(false); return ( - - + <> {chrome.i18n.getMessage('Review') + ' '} @@ -191,7 +191,7 @@ const RecoveryPhrase = ({ handleClick, mnemonic }) => { marginBottom: '8px', }} > - + { )} - + - + ); }; diff --git a/src/ui/views/AddressImport/GoogleImport/index.tsx b/src/ui/views/AddressImport/GoogleImport/index.tsx index 27f5eb74..017f7fe2 100644 --- a/src/ui/views/AddressImport/GoogleImport/index.tsx +++ b/src/ui/views/AddressImport/GoogleImport/index.tsx @@ -1,19 +1,20 @@ -import React, { useEffect, useState } from 'react'; -import { useHistory, useLocation } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; import { IconButton, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; + +import { LLPinAlert } from '@/ui/FRWComponent'; +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../../Register/RegisterHeader'; import AllSet from '../../Register/AllSet'; +import RegisterHeader from '../../Register/RegisterHeader'; + import DecryptWallet from './DecryptWallet'; -import RecoveryPhrase from './RecoveryPhrase'; import GoogleAccounts from './GoogleAccounts'; import RecoveryPassword from './RecoverPassword'; -import Particles from 'react-tsparticles'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { LLPinAlert } from '@/ui/FRWComponent'; -import options from '../../Import/options'; +import RecoveryPhrase from './RecoveryPhrase'; enum Direction { Right, @@ -52,16 +53,16 @@ const GoogleImport = () => { } }; - const getGoogleAccounts = async () => { + const getGoogleAccounts = useCallback(async () => { // const backupFile = await storage.get('googleBackup'); // await setBackup(backupFile); - const users = location.state.accounts; + const users = location?.state?.accounts; setAccounts(users); - }; + }, [location?.state?.accounts]); useEffect(() => { getGoogleAccounts(); - }, []); + }, [getGoogleAccounts]); const page = (index) => { switch (index) { @@ -96,10 +97,8 @@ const GoogleImport = () => { } }; - const heights = [500, 500, 600, 600, 500]; - return ( - + <> { alignItems: 'center', }} > - {activeIndex == 4 && ( - - )} - + {activeIndex === 4 && } + { - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/AddressImport/ImportPager.tsx b/src/ui/views/AddressImport/ImportPager.tsx index e4660fc9..c0910e7f 100644 --- a/src/ui/views/AddressImport/ImportPager.tsx +++ b/src/ui/views/AddressImport/ImportPager.tsx @@ -102,23 +102,17 @@ const ImportPager = ({ }; const handleImport = async (accountKey?: any) => { - console.log('account key ', accountKey); - if (accountKey.length > 1) { - setAccounts(accountKey); - setImport(true); + setAccounts(accountKey); + const result = await wallet.openapi.checkImport(accountKey[0].pubK); + console.log('result ', result); + if (result.status === 409) { + signIn(accountKey); } else { - setAccounts(accountKey); - const result = await wallet.openapi.checkImport(accountKey[0].pubK); - console.log('result ', result); - if (result.status === 409) { - signIn(accountKey); - } else { - if (!accountKey[0].address) { - handleNotFoundPopup(); - return; - } - handleClick(); + if (!accountKey[0].address) { + handleNotFoundPopup(); + return; } + handleClick(); } }; const setmnemonic = (mnemonic) => { @@ -221,15 +215,6 @@ const ImportPager = ({ isGoback={true} /> )} - - {isImport && ( - - )} ); }; diff --git a/src/ui/views/AddressImport/PickUsername.tsx b/src/ui/views/AddressImport/PickUsername.tsx index 3bbf384b..04e2178c 100644 --- a/src/ui/views/AddressImport/PickUsername.tsx +++ b/src/ui/views/AddressImport/PickUsername.tsx @@ -1,16 +1,24 @@ -import React, { useEffect, useState } from 'react'; +import { + CircularProgress, + IconButton, + Button, + Typography, + FormControl, + Input, + InputAdornment, +} from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { useWallet } from 'ui/utils'; + import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import theme from '../../style/LLTheme'; +import CancelIcon from '../../../components/iconfont/IconClose'; import EmailIcon from '../../assets/alternate-email.svg'; -import { Presets } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import { CircularProgress, IconButton } from '@mui/material'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_theme) => ({ customInputLabel: { '& legend': { visibility: 'visible', @@ -31,67 +39,95 @@ const useStyles = makeStyles((theme) => ({ }, })); +const UsernameError = ({ errorMsg }: { errorMsg: string }) => ( + + + + {errorMsg} + {errorMsg.startsWith('This username is reserved') && ( + + hi@lilico.app + {chrome.i18n.getMessage('for__any__inquiry')} + + )} + + +); + +const usernameCorrect = () => ( + + + + {chrome.i18n.getMessage('Sounds_good')} + + +); +const usernameLoading = () => ( + + + {chrome.i18n.getMessage('Checking')} + +); + const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const classes = useStyles(); const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const [usernameValid, setUsernameValid] = useState(false); - const usernameError = (errorMsg) => ( - - - - {errorMsg} - {errorMsg.startsWith('This username is reserved') && ( - - hi@lilico.app - {chrome.i18n.getMessage('for__any__inquiry')} - - )} - - - ); - const usernameCorrect = ( - - - - {chrome.i18n.getMessage('Sounds_good')} - - - ); - const usernameLoading = () => ( - - - {chrome.i18n.getMessage('Checking')} - - ); - const [username, setUsername] = useState(savedUsername || ''); const [helperText, setHelperText] = useState(
); - const regex = /^[A-Za-z0-9]{3,15}$/; + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setUsernameValid(false); + setHelperText(); + }, + [setLoading, setUsernameValid, setHelperText] + ); - const setErrorMessage = (message: string) => { - setLoading(false); - setUsernameValid(false); - setHelperText(usernameError(message)); - }; + const runCheckUsername = useCallback( + (username) => { + wallet.openapi + .checkUsername(username.toLowerCase()) + .then((response) => { + setLoading(false); + if (response.data.username !== username.toLowerCase()) { + setLoading(false); + return; + } + if (response.data.unique) { + setUsernameValid(true); + setHelperText(usernameCorrect); + } else { + if (response.message === 'Username is reserved') { + setErrorMessage( + chrome.i18n.getMessage('This__username__is__reserved__Please__contact') + ); + } else { + setErrorMessage(chrome.i18n.getMessage('This__name__is__taken')); + } + } + }) + .catch(() => { + setErrorMessage(chrome.i18n.getMessage('Oops__unexpected__error')); + }); + }, + [setErrorMessage, setUsernameValid, setHelperText, wallet.openapi] + ); useEffect(() => { setUsernameValid(false); @@ -100,44 +136,26 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const delayDebounceFn = setTimeout(() => { if (username.length < 3) { setErrorMessage(chrome.i18n.getMessage('Too__short')); + setLoading(false); return; } if (username.length > 15) { setErrorMessage(chrome.i18n.getMessage('Too__long')); + setLoading(false); return; } + const regex = /^[A-Za-z0-9]{3,15}$/; if (!regex.test(username)) { setErrorMessage( chrome.i18n.getMessage('Your__username__can__only__contain__letters__and__numbers') ); + setLoading(false); return; } - wallet.openapi - .checkUsername(username.toLowerCase()) - .then((response) => { - setLoading(false); - if (response.data.username != username.toLowerCase()) { - setLoading(false); - return; - } - if (response.data.unique) { - setUsernameValid(true); - setHelperText(usernameCorrect); - } else { - if (response.message == 'Username is reserved') { - setErrorMessage( - chrome.i18n.getMessage('This__username__is__reserved__Please__contact') - ); - } else { - setErrorMessage(chrome.i18n.getMessage('This__name__is__taken')); - } - } - }) - .catch((error) => { - setErrorMessage(chrome.i18n.getMessage('Oops__unexpected__error')); - }); + + runCheckUsername(username); }, 500); return () => clearTimeout(delayDebounceFn); @@ -151,8 +169,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { }; return ( - - + <> {chrome.i18n.getMessage('Pick__Your')} @@ -196,20 +213,18 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { } /> - - {username && ( - - {helperText} - - )} - + + + {helperText} + + @@ -233,7 +248,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { - + ); }; diff --git a/src/ui/views/AddressImport/RecoverPassword.tsx b/src/ui/views/AddressImport/RecoverPassword.tsx index daa6a9ff..fea14940 100644 --- a/src/ui/views/AddressImport/RecoverPassword.tsx +++ b/src/ui/views/AddressImport/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,18 +10,19 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { storage } from 'background/webapi'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -65,32 +65,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -241,8 +215,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, goEnd }) => { }, [confirmPassword, password]); return ( - - + <> {chrome.i18n.getMessage('Welcome__Back')} @@ -289,7 +262,9 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, goEnd }) => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + @@ -377,7 +352,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, goEnd }) => { {errorMessage} - + ); }; diff --git a/src/ui/views/AddressImport/SetPassword.tsx b/src/ui/views/AddressImport/SetPassword.tsx index 395640e5..21442b3e 100644 --- a/src/ui/views/AddressImport/SetPassword.tsx +++ b/src/ui/views/AddressImport/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -12,21 +11,24 @@ import { InputAdornment, FormGroup, LinearProgress, - CssBaseline, } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; -import { useWallet, getHashAlgo, getSignAlgo, saveIndex } from 'ui/utils'; + +import { storage } from '@/background/webapi'; +import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { AccountKey } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; -import { storage } from '@/background/webapi'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; +import { BpUncheked, BpCheckedIcon } from '../../FRWAssets/icons/CustomCheckboxIcons'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -62,32 +64,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -273,8 +249,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, setExPassword, accou }, [confirmPassword, password]); return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -321,9 +296,9 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, setExPassword, accou } /> - - {password && helperText} - + + {helperText} + } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + } + icon={} checkedIcon={} onChange={(event) => setCheck(event.target.checked)} /> @@ -411,7 +386,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username, setExPassword, accou {errMessage} - + ); }; diff --git a/src/ui/views/AddressImport/index.tsx b/src/ui/views/AddressImport/index.tsx index 45ce3389..196a5968 100644 --- a/src/ui/views/AddressImport/index.tsx +++ b/src/ui/views/AddressImport/index.tsx @@ -1,22 +1,21 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import { LLPinAlert } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../components/iconfont/IconBackButton'; -import IconGoogleDrive from '../../../components/iconfont/IconGoogleDrive'; -import theme from '../../style/LLTheme'; -import RegisterHeader from '../Register/RegisterHeader'; import AllSet from '../Register/AllSet'; -import SeedPhrase from './importComponent/SeedPhrase'; +import RegisterHeader from '../Register/RegisterHeader'; + +import ImportPager from './ImportPager'; import PickUsername from './PickUsername'; -import SetPassword from './SetPassword'; -import GoogleBackup from './GoogleBackup'; import RecoverPassword from './RecoverPassword'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; -import ImportPager from './ImportPager'; +import SetPassword from './SetPassword'; enum Direction { Right, @@ -30,19 +29,17 @@ const AddressImport = () => { const [mnemonic, setMnemonic] = useState(''); const [pk, setPk] = useState(null); const [username, setUsername] = useState(''); - const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); - const [showError, setShowError] = useState(false); + const [, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); + const [, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); - const [password, setPassword] = useState(null); + const [, setPassword] = useState(null); const [accounts, setAccounts] = useState([]); - const [isImport, setImport] = useState(false); const getUsername = (username: string) => { setUsername(username.toLowerCase()); }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -54,7 +51,8 @@ const AddressImport = () => { .catch(() => { return; }); - }; + }, [wallet, history]); + const goNext = () => { setDirection(Direction.Right); if (activeIndex < 4) { @@ -138,12 +136,11 @@ const AddressImport = () => { }; useEffect(() => { - console.log('wallet'); loadView(); - }, []); + }, [loadView]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 4 && ( - - )} + {activeIndex === 4 && } - + {/* height why not use auto */} @@ -210,30 +202,67 @@ const AddressImport = () => { - + + + + + + + + + + + + - {page(activeIndex)} - + + - + ); }; diff --git a/src/ui/views/Approval/components/Confimation.tsx b/src/ui/views/Approval/components/Confirmation.tsx similarity index 71% rename from src/ui/views/Approval/components/Confimation.tsx rename to src/ui/views/Approval/components/Confirmation.tsx index e957c487..bee1241b 100644 --- a/src/ui/views/Approval/components/Confimation.tsx +++ b/src/ui/views/Approval/components/Confirmation.tsx @@ -1,33 +1,23 @@ -import React, { useEffect, useState } from 'react'; +import { Stack, Box } from '@mui/material'; +import * as fcl from '@onflow/fcl'; +import dedent from 'dedent'; +import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; + +import { + LLPrimaryButton, + LLSecondaryButton, + LLConnectLoading, + LLLinkingLoading, +} from '@/ui/FRWComponent'; +import { type UserInfoResponse } from 'background/service/networkModel'; import { useApproval, useWallet } from 'ui/utils'; // import { CHAINS_ENUM } from 'consts'; -import { ThemeProvider } from '@mui/system'; -import { - Stack, - Box, - Typography, - Divider, - Accordion, - AccordionSummary, - AccordionDetails, -} from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import theme from 'ui/style/LLTheme'; -import * as fcl from '@onflow/fcl'; -import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; -import Highlight from 'react-highlight'; + import './github-dark-dimmed.css'; -import * as secp from '@noble/secp256k1'; -import { SHA3 } from 'sha3'; -import IconFlow from '../../../../components/iconfont/IconFlow'; + import { DefaultBlock } from './DefaultBlock'; import { LinkingBlock } from './LinkingBlock'; -import { LLConnectLoading, LLLinkingLoading } from '@/ui/FRWComponent'; -import { UserInfoResponse } from 'background/service/networkModel'; -import dedent from 'dedent'; -import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; -import { Presets } from 'react-component-transition'; interface ConnectProps { params: any; @@ -35,7 +25,7 @@ interface ConnectProps { // defaultChain: CHAINS_ENUM; } -const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => { +const Confirmation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => { const [, resolveApproval, rejectApproval, linkningConfirm] = useApproval(); const { t } = useTranslation(); const wallet = useWallet(); @@ -85,10 +75,10 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => sig: string | null; } - const getUserInfo = async () => { + const getUserInfo = useCallback(async () => { const userResult = await wallet.getUserInfo(false); await setUserInfo(userResult); - }; + }, [wallet]); // useEffect(() => { // getUserInfo(); @@ -100,17 +90,20 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => // } // }, [accountArgs]) - const fetchTxInfo = async (cadence: string) => { - // const account = await wallet.getCurrentAccount(); - const network = await wallet.getNetwork(); - const result = await wallet.openapi.getTransactionTemplate(cadence, network); - if (result != null) { - setAuditor(result); - setExpanded(false); - } - }; + const fetchTxInfo = useCallback( + async (cadence: string) => { + // const account = await wallet.getCurrentAccount(); + const network = await wallet.getNetwork(); + const result = await wallet.openapi.getTransactionTemplate(cadence, network); + if (result !== null) { + setAuditor(result); + setExpanded(false); + } + }, + [wallet] + ); - const handleCancel = () => { + const handleCancel = useCallback(() => { if (opener) { if (windowId) { chrome.windows.update(windowId, { focused: true }); @@ -126,28 +119,33 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => setApproval(false); rejectApproval('User rejected the request.'); } - }; - - const fclCallback = (data) => { - if (typeof data != 'object') return; - if (data.type !== 'FCL:VIEW:READY:RESPONSE') return; - const newSignable: Signable = data.body; - const hostname = data.config?.client?.hostname; - hostname && setHost(hostname); - setImage(data.config.app.icon); - setAccountTitle(data.config.app.title); - const firstLine = newSignable.cadence.trim().split('\n')[0]; - - const isAccountLinking = firstLine.includes('#allowAccountLinking'); - setAccountLinking(isAccountLinking); - if (isAccountLinking) { - setAccountArgs(newSignable['args']); - } - setSignable(newSignable); - getUserInfo(); + }, [opener, windowId, rejectApproval]); + + const fclCallback = useCallback( + (data) => { + if (typeof data !== 'object') return; + if (data.type !== 'FCL:VIEW:READY:RESPONSE') return; + const newSignable: Signable = data.body; + const hostname = data.config?.client?.hostname; + if (hostname) { + setHost(hostname); + } + setImage(data.config.app.icon); + setAccountTitle(data.config.app.title); + const firstLine = newSignable.cadence.trim().split('\n')[0]; + + const isAccountLinking = firstLine.includes('#allowAccountLinking'); + setAccountLinking(isAccountLinking); + if (isAccountLinking) { + setAccountArgs(newSignable['args']); + } + setSignable(newSignable); + getUserInfo(); - fetchTxInfo(newSignable.cadence); - }; + fetchTxInfo(newSignable.cadence); + }, + [fetchTxInfo, getUserInfo] + ); const sendAuthzToFCL = async () => { console.log('sendAuthzToFCL ==>', signable); @@ -188,82 +186,92 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => } }; - const sendSignature = (signable, signedMessage) => { - if (opener) { - chrome.tabs.sendMessage(opener, { - f_type: 'PollingResponse', - f_vsn: '1.0.0', - status: 'APPROVED', - reason: null, - data: new fcl.WalletUtils.CompositeSignature(signable.addr, signable.keyId, signedMessage), - }); - } - }; + const sendSignature = useCallback( + (signable, signedMessage) => { + if (opener) { + chrome.tabs.sendMessage(opener, { + f_type: 'PollingResponse', + f_vsn: '1.0.0', + status: 'APPROVED', + reason: null, + data: new fcl.WalletUtils.CompositeSignature( + signable.addr, + signable.keyId, + signedMessage + ), + }); + } + }, + [opener] + ); - const signPayer = async (signable) => { - setIsLoading(true); - const value = await sessionStorage.getItem('pendingRefBlockId'); + const signPayer = useCallback( + async (signable) => { + setIsLoading(true); + const value = await sessionStorage.getItem('pendingRefBlockId'); - console.log('signPayer ->', signable.voucher.refBlock, value, signable.roles.payer); + console.log('signPayer ->', signable.voucher.refBlock, value, signable.roles.payer); - if (signable.roles.payer !== true) { - return; - } + if (signable.roles.payer !== true) { + return; + } - if (signable.voucher.refBlock !== value) { - return; - } + if (signable.voucher.refBlock !== value) { + return; + } - try { - const signedMessage = await wallet.signPayer(signable); - sendSignature(signable, signedMessage); - setApproval(true); - // if (accountLinking) { - // await linkningConfirm(); - // } else { - // resolveApproval(); - // setIsLoading(false); - // } - resolveApproval(); - setIsLoading(false); - } catch (err) { - setIsLoading(false); - handleCancel(); - } - }; + try { + const signedMessage = await wallet.signPayer(signable); + sendSignature(signable, signedMessage); + setApproval(true); + // if (accountLinking) { + // await linkningConfirm(); + // } else { + // resolveApproval(); + // setIsLoading(false); + // } + resolveApproval(); + setIsLoading(false); + } catch (err) { + setIsLoading(false); + handleCancel(); + } + }, + [wallet, sendSignature, resolveApproval, handleCancel, setIsLoading] + ); - const loadPayer = async () => { + const loadPayer = useCallback(async () => { const isEnabled = await wallet.allowLilicoPay(); setLilicoEnabled(isEnabled); - }; + }, [wallet]); useEffect(() => { loadPayer(); return () => { sessionStorage.removeItem('pendingRefBlockId'); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore chrome.storage.session?.remove('pendingRefBlockId'); }; - }, []); + }, [loadPayer]); useEffect(() => { console.log('pendingRefBlockId ->', lilicoEnabled, signable, approval); if (lilicoEnabled && signable && signable.message && approval) { signPayer(signable); } - }, [signable]); + }, [approval, lilicoEnabled, signPayer, signable]); useEffect(() => { - chrome.tabs && + if (chrome.tabs) { chrome.tabs .query({ active: true, currentWindow: false, }) .then((tabs) => { - const targetTab = tabs.filter((item) => item.id == tabId); + const targetTab = tabs.filter((item) => item.id === tabId); let host = ''; if (targetTab[0].url) { @@ -276,6 +284,7 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => setOpener(targetTab[0].id); chrome.tabs.sendMessage(targetTab[0].id || 0, { type: 'FCL:VIEW:READY' }); }); + } const extMessageHandler = (msg, sender, sendResponse) => { // console.log('extMessageHandler -->', msg); @@ -283,14 +292,18 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => if (msg.type === 'FCL:VIEW:READY:RESPONSE') { console.log('extMessageHandler -->', msg.type, msg); - msg.host && setHost(msg.host); + if (msg.host) { + setHost(msg.host); + } if (msg.config?.app?.title) { setTitle(msg.config.app.title); } if (msg.config?.app?.icon) { setLogo(msg.config.app.icon); } - setCadenceScript(msg.body.cadence); + if (msg.body?.cadence) { + setCadenceScript(msg.body.cadence); + } if (msg.body?.args?.length > 0) { setCadenceArguments(msg.body.args); } @@ -318,7 +331,7 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => console.log('removeListener'); }); }; - }, []); + }, [fclCallback, tabId]); window.onbeforeunload = () => { if (!approval) { @@ -327,7 +340,7 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => }; return ( - + <> {isLoading ? ( {accountLinking ? ( @@ -387,8 +400,8 @@ const Confimation = ({ params: { icon, origin, tabId, type } }: ConnectProps) => )} - + ); }; -export default Confimation; +export default Confirmation; diff --git a/src/ui/views/Approval/components/Connect.tsx b/src/ui/views/Approval/components/Connect.tsx index 6eae4ff5..c8baa075 100644 --- a/src/ui/views/Approval/components/Connect.tsx +++ b/src/ui/views/Approval/components/Connect.tsx @@ -1,5 +1,4 @@ import { Stack, Box, Typography, Divider, CardMedia } from '@mui/material'; -import { ThemeProvider } from '@mui/system'; import { WalletUtils } from '@onflow/fcl'; import React, { useCallback, useEffect, useState } from 'react'; @@ -12,7 +11,6 @@ import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; import mainnetsvg from 'ui/FRWAssets/svg/mainnet.svg'; import testnetsvg from 'ui/FRWAssets/svg/testnet.svg'; import { LLPrimaryButton, LLSecondaryButton, LLConnectLoading } from 'ui/FRWComponent'; -import theme from 'ui/style/LLTheme'; import { useApproval, useWallet } from 'ui/utils'; // import { CHAINS_ENUM } from 'consts'; @@ -401,7 +399,7 @@ const Connect = ({ params: { /*icon, origin,*/ tabId } }: ConnectProps) => { ); return ( - + <> {showSwitch ? ( { ) : ( {renderContent()} )} - + ); }; diff --git a/src/ui/views/Approval/components/DefaultBlock.tsx b/src/ui/views/Approval/components/DefaultBlock.tsx index 95cb631e..9ac5e6c9 100644 --- a/src/ui/views/Approval/components/DefaultBlock.tsx +++ b/src/ui/views/Approval/components/DefaultBlock.tsx @@ -1,4 +1,5 @@ -import React from 'react'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; import { Stack, Box, @@ -8,12 +9,12 @@ import { AccordionSummary, AccordionDetails, } from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; -import { Presets } from 'react-component-transition'; -import IconFlow from '../../../../components/iconfont/IconFlow'; +import Fade from '@mui/material/Fade'; +import React from 'react'; import Highlight from 'react-highlight'; +import IconFlow from '../../../../components/iconfont/IconFlow'; + export const DefaultBlock = ({ title, host, @@ -71,8 +72,8 @@ export const DefaultBlock = ({ - - {auditor && ( + + {auditor ? ( + ) : ( + )} - + { }); }; - const loadPayer = async () => { + const loadPayer = useCallback(async () => { const isEnabled = await usewallet.allowLilicoPay(); setLilicoEnabled(isEnabled); - }; + }, [usewallet]); const checkCoa = async () => { setLoading(true); @@ -138,10 +123,10 @@ const EthConfirm = ({ params }: ConnectProps) => { loadPayer(); extractData(params); } - }, []); + }, [loadPayer, params]); return ( - + <> {isLoading ? ( {accountLinking ? ( @@ -215,7 +200,7 @@ const EthConfirm = ({ params }: ConnectProps) => { )} - + ); }; diff --git a/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx b/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx index b6b6c613..05650d38 100644 --- a/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx @@ -1,17 +1,18 @@ -import React, { useEffect, useState } from 'react'; -import { useLocation, useHistory } from 'react-router-dom'; +import { Stack, Box, Typography, Divider, CardMedia, Card } from '@mui/material'; +import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; +import { useLocation, useHistory } from 'react-router-dom'; + +import { isValidEthereumAddress } from '@/shared/utils/address'; import enableBg from 'ui/FRWAssets/image/enableBg.png'; -import { ThemeProvider } from '@mui/system'; -import { Stack, Box, Typography, Divider, CardMedia, Card } from '@mui/material'; -import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; +import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; +import { LLPrimaryButton, LLSecondaryButton, LLSpinner, LLConnectLoading } from 'ui/FRWComponent'; +import { useApproval, useWallet, formatAddress } from 'ui/utils'; + import CheckCircleIcon from '../../../../../../components/iconfont/IconCheckmark'; -import theme from 'ui/style/LLTheme'; + // import EthMove from '../EthMove'; -import { LLPrimaryButton, LLSecondaryButton, LLSpinner, LLConnectLoading } from 'ui/FRWComponent'; interface ConnectProps { params: any; @@ -42,7 +43,7 @@ const EthConnect = ({ params: { icon, name, origin } }: ConnectProps) => { // TODO: replace default logo const [logo, setLogo] = useState(''); const [evmAddress, setEvmAddress] = useState(''); - const init = async () => { + const init = useCallback(async () => { const network = await usewallet.getNetwork(); setCurrent(network); let currentWallet; @@ -72,7 +73,7 @@ const EthConnect = ({ params: { icon, name, origin } }: ConnectProps) => { setDefaultChain(defaultChain); setIsLoading(false); - }; + }, [usewallet, icon, currentNetwork]); const createCoa = async () => { setIsLoading(true); @@ -95,23 +96,26 @@ const EthConnect = ({ params: { icon, name, origin } }: ConnectProps) => { }); }; - const transactionDoneHanlder = async (request) => { - if (request.msg === 'transactionDone') { - const currentWallet = await usewallet.getCurrentWallet(); - const res = await usewallet.queryEvmAddress(currentWallet.address); - setEvmAddress(res!); - setIsEvm(isValidEthereumAddress(res)); - } - return true; - }; + const transactionDoneHandler = useCallback( + async (request) => { + if (request.msg === 'transactionDone') { + const currentWallet = await usewallet.getCurrentWallet(); + const res = await usewallet.queryEvmAddress(currentWallet.address); + setEvmAddress(res!); + setIsEvm(isValidEthereumAddress(res)); + } + return true; + }, + [usewallet] + ); useEffect(() => { - chrome.runtime.onMessage.addListener(transactionDoneHanlder); + chrome.runtime.onMessage.addListener(transactionDoneHandler); return () => { - chrome.runtime.onMessage.removeListener(transactionDoneHanlder); + chrome.runtime.onMessage.removeListener(transactionDoneHandler); }; - }, []); + }, [transactionDoneHandler]); const handleCancel = () => { rejectApproval('User rejected the request.'); @@ -126,7 +130,7 @@ const EthConnect = ({ params: { icon, name, origin } }: ConnectProps) => { useEffect(() => { init(); - }, []); + }, [init]); const renderContent = () => ( @@ -356,9 +360,9 @@ const EthConnect = ({ params: { icon, name, origin } }: ConnectProps) => { ); return ( - + <> {renderContent()} - + ); }; diff --git a/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx b/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx index b2221775..26ef2447 100644 --- a/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx @@ -1,16 +1,15 @@ -import React, { useEffect, useState } from 'react'; -import { useLocation, useHistory } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; -// import { CHAINS_ENUM } from 'consts'; -import { ThemeProvider } from '@mui/system'; import { Stack, Box, Typography, Divider, CardMedia, Card } from '@mui/material'; -import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; -import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useHistory } from 'react-router-dom'; + +import { isValidEthereumAddress } from '@/shared/utils/address'; import enableBg from 'ui/FRWAssets/image/enableBg.png'; -import theme from 'ui/style/LLTheme'; +import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; +import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; import { LLPrimaryButton, LLSecondaryButton, LLSpinner, LLConnectLoading } from 'ui/FRWComponent'; +import { useApproval, useWallet, formatAddress } from 'ui/utils'; +// import { CHAINS_ENUM } from 'consts'; interface ConnectProps { params: any; @@ -42,7 +41,7 @@ const EthEnable = ({ params: { icon, name, origin } }: ConnectProps) => { // TODO: replace default logo const [logo, setLogo] = useState(''); const [evmAddress, setEvmAddress] = useState(''); - const init = async () => { + const init = useCallback(async () => { setLogo(icon); const site = await wallet.getSite(origin); const collectList: { name: string; logo_url: string }[] = []; @@ -53,7 +52,7 @@ const EthEnable = ({ params: { icon, name, origin } }: ConnectProps) => { setDefaultChain(defaultChain); setIsLoading(false); - }; + }, [wallet, origin, icon]); const handleCancel = () => { rejectApproval('User rejected the request.'); @@ -68,7 +67,7 @@ const EthEnable = ({ params: { icon, name, origin } }: ConnectProps) => { useEffect(() => { init(); - }, []); + }, [init]); const renderContent = () => ( @@ -132,9 +131,9 @@ const EthEnable = ({ params: { icon, name, origin } }: ConnectProps) => { ); return ( - + <> {renderContent()} - + ); }; diff --git a/src/ui/views/Approval/components/EthApproval/EthSignType/DefaultBlock.tsx b/src/ui/views/Approval/components/EthApproval/EthSignType/DefaultBlock.tsx index 49275ac7..bd34ba9f 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSignType/DefaultBlock.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSignType/DefaultBlock.tsx @@ -1,4 +1,5 @@ -import React, { useState, useEffect } from 'react'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; import { Stack, Box, @@ -8,15 +9,15 @@ import { AccordionSummary, AccordionDetails, } from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; -import { useHistory } from 'react-router-dom'; -import { Presets } from 'react-component-transition'; -import IconFlow from '../../../../../../components/iconfont/IconFlow'; +import React, { useState, useEffect } from 'react'; import Highlight from 'react-highlight'; +import { useHistory } from 'react-router-dom'; + import { getScripts } from 'background/utils'; import placeholder from 'ui/FRWAssets/image/placeholder.png'; +import IconFlow from '../../../../../../components/iconfont/IconFlow'; + export const DefaultBlock = ({ title, host, diff --git a/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx index 4ea16664..478b94be 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx @@ -1,16 +1,14 @@ -import React, { useEffect, useState } from 'react'; +import { Stack, Box, Typography, CardMedia } from '@mui/material'; +import * as fcl from '@onflow/fcl'; +import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet } from 'ui/utils'; + // import { CHAINS_ENUM } from 'consts'; -import { ThemeProvider } from '@mui/system'; -import { Stack, Box, Typography, CardMedia } from '@mui/material'; -import theme from 'ui/style/LLTheme'; -import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLConnectLoading, LLLinkingLoading } from '@/ui/FRWComponent'; -import { UserInfoResponse } from 'background/service/networkModel'; -import { isValidEthereumAddress } from 'ui/utils/address'; -import { formatAddress } from 'ui/utils'; -import * as fcl from '@onflow/fcl'; +import { type UserInfoResponse } from 'background/service/networkModel'; +import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; +import { useApproval, useWallet, formatAddress } from 'ui/utils'; interface ConnectProps { params: any; @@ -62,7 +60,7 @@ const EthSignType = ({ params }: ConnectProps) => { sig: string | null; } - const extractData = () => { + const extractData = useCallback(() => { console.log('obj ', params); let data = ''; let address = ''; @@ -77,7 +75,7 @@ const EthSignType = ({ params }: ConnectProps) => { const jsonObject = JSON.parse(data); setMessages(jsonObject); console.log('data, ', data); - }; + }, [params]); const handleCancel = () => { rejectApproval('User rejected the request.'); @@ -113,7 +111,7 @@ const EthSignType = ({ params }: ConnectProps) => { if (params) { extractData(); } - }, []); + }, [extractData, params]); const JsonRenderer = ({ data }) => { // Recursive function to render objects, including arrays and nested objects @@ -245,7 +243,7 @@ const EthSignType = ({ params }: ConnectProps) => { }; return ( - + <> {isLoading ? ( {accountLinking ? ( @@ -323,7 +321,7 @@ const EthSignType = ({ params }: ConnectProps) => { )} - + ); }; diff --git a/src/ui/views/Approval/components/EthApproval/EthSignV1/DefaultBlock.tsx b/src/ui/views/Approval/components/EthApproval/EthSignV1/DefaultBlock.tsx index 49275ac7..bd34ba9f 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSignV1/DefaultBlock.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSignV1/DefaultBlock.tsx @@ -1,4 +1,5 @@ -import React, { useState, useEffect } from 'react'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; import { Stack, Box, @@ -8,15 +9,15 @@ import { AccordionSummary, AccordionDetails, } from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import GppGoodRoundedIcon from '@mui/icons-material/GppGoodRounded'; -import { useHistory } from 'react-router-dom'; -import { Presets } from 'react-component-transition'; -import IconFlow from '../../../../../../components/iconfont/IconFlow'; +import React, { useState, useEffect } from 'react'; import Highlight from 'react-highlight'; +import { useHistory } from 'react-router-dom'; + import { getScripts } from 'background/utils'; import placeholder from 'ui/FRWAssets/image/placeholder.png'; +import IconFlow from '../../../../../../components/iconfont/IconFlow'; + export const DefaultBlock = ({ title, host, diff --git a/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx index da4b6ca1..66f1f088 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx @@ -1,16 +1,14 @@ -import React, { useEffect, useState } from 'react'; +import { Stack, Box, Typography, CardMedia } from '@mui/material'; +import * as fcl from '@onflow/fcl'; +import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet } from 'ui/utils'; + // import { CHAINS_ENUM } from 'consts'; -import { ThemeProvider } from '@mui/system'; -import { Stack, Box, Typography, CardMedia } from '@mui/material'; -import theme from 'ui/style/LLTheme'; -import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLConnectLoading, LLLinkingLoading } from '@/ui/FRWComponent'; -import { UserInfoResponse } from 'background/service/networkModel'; -import { isValidEthereumAddress } from 'ui/utils/address'; -import { formatAddress } from 'ui/utils'; -import * as fcl from '@onflow/fcl'; +import { type UserInfoResponse } from 'background/service/networkModel'; +import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; +import { useApproval, useWallet } from 'ui/utils'; interface ConnectProps { params: any; @@ -62,7 +60,7 @@ const EthSignV1 = ({ params }: ConnectProps) => { sig: string | null; } - const extractData = () => { + const extractData = useCallback(() => { console.log('obj ', params); let data = ''; let address = ''; @@ -76,7 +74,7 @@ const EthSignV1 = ({ params }: ConnectProps) => { } setMessages(data); console.log('data, ', data); - }; + }, [params]); const handleCancel = () => { rejectApproval('User rejected the request.'); @@ -112,7 +110,7 @@ const EthSignV1 = ({ params }: ConnectProps) => { if (params) { extractData(); } - }, []); + }, [extractData, params]); const JsonRenderer = ({ data }) => { return ( @@ -146,7 +144,7 @@ const EthSignV1 = ({ params }: ConnectProps) => { }; return ( - + <> {isLoading ? ( {accountLinking ? ( @@ -224,7 +222,7 @@ const EthSignV1 = ({ params }: ConnectProps) => { )} - + ); }; diff --git a/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx index 1428a066..c5d58e1f 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx @@ -1,16 +1,15 @@ -import React, { useEffect, useState } from 'react'; -import { useLocation } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; -import { ThemeProvider } from '@mui/system'; import { Stack, Box, Typography, Divider, CardMedia } from '@mui/material'; -import theme from 'ui/style/LLTheme'; -// import EthMove from '../EthMove'; -import { LLPrimaryButton, LLSecondaryButton, LLConnectLoading } from 'ui/FRWComponent'; import { Contract, ethers } from 'ethers'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation } from 'react-router-dom'; + import { storage } from '@/background/webapi'; +import { withPrefix } from '@/shared/utils/address'; import { EVM_ENDPOINT } from 'consts'; +import { LLPrimaryButton, LLSecondaryButton, LLConnectLoading } from 'ui/FRWComponent'; +import { useApproval, useWallet } from 'ui/utils'; +// import EthMove from '../EthMove'; const EthSuggest = (data) => { const { state } = useLocation<{ @@ -26,74 +25,77 @@ const EthSuggest = (data) => { const [isValidatingAddress, setIsValidatingAddress] = useState(false); const [validationError, setValidationError] = useState(false); const [coinInfo, setCoinInfo] = useState({}); - const init = async () => { - console.log('suggest data ', data); - const contractAddress = data.params.data.params.options.address; - addCustom(contractAddress); - }; - const addCustom = async (address) => { - setLoading(true); - const contractAddress = withPrefix(address)!.toLowerCase(); - const network = await usewallet.getNetwork(); - const provider = new ethers.JsonRpcProvider(EVM_ENDPOINT[network]); - const evmAddress = await usewallet.getEvmAddress(); - const ftContract = new Contract( - contractAddress!, - [ - 'function name() view returns (string)', - 'function symbol() view returns (string)', - 'function totalSupply() view returns (uint256)', - 'function decimals() view returns (uint8)', - 'function balanceOf(address) view returns (uint)', - ], - provider - ); + const addCustom = useCallback( + async (address) => { + setLoading(true); + const contractAddress = withPrefix(address)!.toLowerCase(); + const network = await usewallet.getNetwork(); + const provider = new ethers.JsonRpcProvider(EVM_ENDPOINT[network]); + const evmAddress = await usewallet.getEvmAddress(); + const ftContract = new Contract( + contractAddress!, + [ + 'function name() view returns (string)', + 'function symbol() view returns (string)', + 'function totalSupply() view returns (uint256)', + 'function decimals() view returns (uint8)', + 'function balanceOf(address) view returns (uint)', + ], + provider + ); - // Helper function to handle contract calls - async function getContractData(contract, method, ...args) { - try { - const result = await contract[method](...args); - if (!result || result === '0x') { - console.error(`No data returned for method: ${method}`); + // Helper function to handle contract calls + async function getContractData(contract, method, ...args) { + try { + const result = await contract[method](...args); + if (!result || result === '0x') { + console.error(`No data returned for method: ${method}`); + return null; + } + return result; + } catch (error) { + console.error(`Error calling ${method}:`, error); return null; } - return result; - } catch (error) { - console.error(`Error calling ${method}:`, error); - return null; } - } - const decimals = await getContractData(ftContract, 'decimals'); - const name = await getContractData(ftContract, 'name'); - const symbol = await getContractData(ftContract, 'symbol'); - const balance = await ftContract.balanceOf(evmAddress); - console.log('balance ', evmAddress, balance); + const decimals = await getContractData(ftContract, 'decimals'); + const name = await getContractData(ftContract, 'name'); + const symbol = await getContractData(ftContract, 'symbol'); + const balance = await ftContract.balanceOf(evmAddress); + console.log('balance ', evmAddress, balance); - if (decimals !== null && name !== null && symbol !== null) { - const info = { - coin: name, - unit: symbol, - icon: '', - price: 0, - change24h: 0, - total: Number(balance) / Math.pow(10, Number(decimals)), - address: contractAddress?.toLowerCase(), - decimals: Number(decimals), - }; + if (decimals !== null && name !== null && symbol !== null) { + const info = { + coin: name, + unit: symbol, + icon: '', + price: 0, + change24h: 0, + total: Number(balance) / Math.pow(10, Number(decimals)), + address: contractAddress?.toLowerCase(), + decimals: Number(decimals), + }; - const flowId = await usewallet.getAssociatedFlowIdentifier(contractAddress); - info['flowIdentifier'] = flowId; - setCoinInfo(info); - setLoading(false); - } else { - console.error('Failed to retrieve all required data for the token.'); - setIsValidatingAddress(false); - setValidationError(true); - setLoading(false); - } - }; + const flowId = await usewallet.getAssociatedFlowIdentifier(contractAddress); + info['flowIdentifier'] = flowId; + setCoinInfo(info); + setLoading(false); + } else { + console.error('Failed to retrieve all required data for the token.'); + setIsValidatingAddress(false); + setValidationError(true); + setLoading(false); + } + }, + [usewallet] + ); + const init = useCallback(async () => { + console.log('suggest data ', data); + const contractAddress = data.params.data.params.options.address; + addCustom(contractAddress); + }, [addCustom, data]); const importCustom = async () => { setLoading(true); @@ -130,7 +132,7 @@ const EthSuggest = (data) => { useEffect(() => { init(); - }, []); + }, [init]); const renderContent = () => ( @@ -250,9 +252,9 @@ const EthSuggest = (data) => { ); return ( - + <> {renderContent()} - + ); }; diff --git a/src/ui/views/Approval/components/EthApproval/EthSwitch/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSwitch/index.tsx index bb5d44a7..4df14d72 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSwitch/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSwitch/index.tsx @@ -1,21 +1,19 @@ -import React, { useEffect, useState } from 'react'; -import { useLocation, useHistory } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet, formatAddress } from 'ui/utils'; -// import { CHAINS_ENUM } from 'consts'; -import { ThemeProvider } from '@mui/system'; import { Stack, Box, Typography, Divider, CardMedia } from '@mui/material'; -import { authnServiceDefinition, serviceDefinition } from 'background/controller/serviceDefinition'; -import theme from 'ui/style/LLTheme'; -import { LLPrimaryButton, LLSecondaryButton, LLConnectLoading } from 'ui/FRWComponent'; import { WalletUtils } from '@onflow/fcl'; -import Link from 'ui/FRWAssets/svg/link.svg'; -import testnetsvg from 'ui/FRWAssets/svg/testnet.svg'; -import mainnetsvg from 'ui/FRWAssets/svg/mainnet.svg'; -import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; -import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useHistory } from 'react-router-dom'; import { storage } from '@/background/webapi'; +import { authnServiceDefinition, serviceDefinition } from 'background/controller/serviceDefinition'; +import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; +import Link from 'ui/FRWAssets/svg/link.svg'; +import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; +import mainnetsvg from 'ui/FRWAssets/svg/mainnet.svg'; +import testnetsvg from 'ui/FRWAssets/svg/testnet.svg'; +import { LLPrimaryButton, LLSecondaryButton, LLConnectLoading } from 'ui/FRWComponent'; +import { useApproval, useWallet, formatAddress } from 'ui/utils'; +// import { CHAINS_ENUM } from 'consts'; interface ConnectProps { params: any; @@ -66,7 +64,7 @@ const EthSwitch = ({ params: { origin, target } }: ConnectProps) => { }); }; - const checkNetwork = async () => { + const checkNetwork = useCallback(async () => { console.log('target ', target); const network = await wallet.getNetwork(); @@ -78,11 +76,11 @@ const EthSwitch = ({ params: { origin, target } }: ConnectProps) => { } const address = await wallet.getCurrentAddress(); setCurrentAddress(address!); - }; + }, [wallet, target]); useEffect(() => { checkNetwork(); - }, [currentNetwork]); + }, [checkNetwork, currentNetwork]); const networkColor = (network: string) => { switch (network) { @@ -96,7 +94,7 @@ const EthSwitch = ({ params: { origin, target } }: ConnectProps) => { }; return ( - + <> { /> - + ); }; diff --git a/src/ui/views/Approval/components/LinkingBlock.tsx b/src/ui/views/Approval/components/LinkingBlock.tsx index f3b78e7d..7786fa0d 100644 --- a/src/ui/views/Approval/components/LinkingBlock.tsx +++ b/src/ui/views/Approval/components/LinkingBlock.tsx @@ -1,4 +1,3 @@ -import React, { useEffect, useState } from 'react'; import { Stack, Box, @@ -9,10 +8,12 @@ import { AccordionDetails, } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { useWallet } from 'ui/utils'; +import React, { useEffect, useState } from 'react'; + import { UserInfoResponse } from 'background/service/networkModel'; import IconCheck from 'ui/assets/check.svg'; import Link from 'ui/FRWAssets/svg/link.svg'; +import { useWallet } from 'ui/utils'; const useStyles = makeStyles({ IconCheck: { diff --git a/src/ui/views/Approval/components/SignMessage.tsx b/src/ui/views/Approval/components/SignMessage.tsx index c65a71b0..0981da35 100644 --- a/src/ui/views/Approval/components/SignMessage.tsx +++ b/src/ui/views/Approval/components/SignMessage.tsx @@ -1,8 +1,4 @@ -import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useApproval, useWallet } from 'ui/utils'; -// import { CHAINS_ENUM } from 'consts'; -import { ThemeProvider } from '@mui/system'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { Stack, Box, @@ -12,13 +8,15 @@ import { AccordionSummary, AccordionDetails, } from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import theme from 'ui/style/LLTheme'; import * as fcl from '@onflow/fcl'; -import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; -import './github-dark-dimmed.css'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { storage } from '@/background/webapi'; +import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; +import { useApproval, useWallet } from 'ui/utils'; + +import './github-dark-dimmed.css'; interface ConnectProps { params: any; @@ -103,7 +101,9 @@ const SignMessage = ({ params: { icon, origin, tabId, type } }: ConnectProps) => const extMessageHandler = (msg, sender, sendResponse) => { if (msg.type === 'FCL:VIEW:READY:RESPONSE') { - msg.host && setHost(msg.host); + if (msg.host) { + setHost(msg.host); + } if (msg.config.app.title) { setTitle(msg.config.app.title); } @@ -119,14 +119,14 @@ const SignMessage = ({ params: { icon, origin, tabId, type } }: ConnectProps) => }; useEffect(() => { - chrome.tabs && + if (chrome.tabs) { chrome.tabs .query({ active: true, currentWindow: false, }) .then((tabs) => { - const targetTab = tabs.filter((item) => item.id == tabId); + const targetTab = tabs.filter((item) => item.id === tabId); let host = ''; if (targetTab[0].url) { @@ -139,6 +139,7 @@ const SignMessage = ({ params: { icon, origin, tabId, type } }: ConnectProps) => setOpener(targetTab[0].id); chrome.tabs.sendMessage(targetTab[0].id || 0, { type: 'FCL:VIEW:READY' }); }); + } chrome.runtime?.onMessage.addListener(extMessageHandler); @@ -147,7 +148,7 @@ const SignMessage = ({ params: { icon, origin, tabId, type } }: ConnectProps) => console.log('removeListener'); }); }; - }, []); + }, [tabId]); window.onbeforeunload = () => { if (!approval) { @@ -167,7 +168,7 @@ const SignMessage = ({ params: { icon, origin, tabId, type } }: ConnectProps) => // } return ( - + <> /> - + ); }; diff --git a/src/ui/views/Approval/components/index.ts b/src/ui/views/Approval/components/index.ts index dceb1885..5c4194d5 100644 --- a/src/ui/views/Approval/components/index.ts +++ b/src/ui/views/Approval/components/index.ts @@ -1,5 +1,5 @@ export { default as Connect } from './Connect'; -export { default as Confimation } from './Confimation'; +export { default as Confirmation } from './Confirmation'; export { default as SignMessage } from './SignMessage'; export { default as EthConnect } from './EthApproval/EthConnect'; diff --git a/src/ui/views/Dashboard/Components/MenuDrawer.tsx b/src/ui/views/Dashboard/Components/MenuDrawer.tsx index 82b4e556..344ac007 100644 --- a/src/ui/views/Dashboard/Components/MenuDrawer.tsx +++ b/src/ui/views/Dashboard/Components/MenuDrawer.tsx @@ -17,11 +17,11 @@ import { makeStyles } from '@mui/styles'; import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import type { UserInfoResponse } from 'background/service/networkModel'; import importIcon from 'ui/FRWAssets/svg/importIcon.svg'; import popLock from 'ui/FRWAssets/svg/popLock.svg'; import { useWallet } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; import rightarrow from '../../../FRWAssets/svg/rightarrow.svg'; import sideMore from '../../../FRWAssets/svg/sideMore.svg'; @@ -54,8 +54,7 @@ interface MenuDrawerProps { createWalletList: any; setWallets: any; currentNetwork: string; - evmAddress: string; - emojis: any; + evmWallet: any; networkColor: any; evmLoading: boolean; modeOn: boolean; @@ -117,13 +116,12 @@ const MenuDrawer = (props: MenuDrawerProps) => { }, [usewallet]); const getEvmAddress = useCallback(async () => { - console.log(props.evmAddress); - if (isValidEthereumAddress(props.evmAddress)) { - const result = await usewallet.getBalance(props.evmAddress); + if (isValidEthereumAddress(props.evmWallet.address)) { + const result = await usewallet.getBalance(props.evmWallet.address); const readBalance = parseFloat(result) / 1e18; setEvmBalance(readBalance); } - }, [props.evmAddress, usewallet]); + }, [props.evmWallet, usewallet]); const hasChildAccounts = props.childAccounts && Object.keys(props.childAccounts).length > 0; @@ -133,7 +131,7 @@ const MenuDrawer = (props: MenuDrawerProps) => { useEffect(() => { getEvmAddress(); - }, [getEvmAddress, props.evmAddress]); + }, [getEvmAddress, props.evmWallet]); return ( { - {/* {props.otherAccounts && props.otherAccounts.map((account, index) => ( - props.switchAccount(account)}> - {`Avatar - - ))} */} @@ -188,7 +181,7 @@ const MenuDrawer = (props: MenuDrawerProps) => { )} - {evmMode && !props.evmLoading && !isValidEthereumAddress(props.evmAddress) && ( + {evmMode && !props.evmLoading && !isValidEthereumAddress(props.evmWallet.address) && ( { - {props.walletList.length > 0 && props.walletList.map(props.createWalletList)} - {(isValidEthereumAddress(props.evmAddress) || hasChildAccounts) && ( - - {chrome.i18n.getMessage('Linked_Account')} - - )} - - {isValidEthereumAddress(props.evmAddress) && ( - - props.setWallets( - { - name: 'evm', - address: props.evmAddress, - chain_id: props.currentNetwork, - coins: ['flow'], - id: 1, - }, - 'evm' - ) - } + + {props.walletList.length > 0 && + props.walletList + .slice() + .sort((a, b) => + a.address === props.current.address + ? -1 + : b.address === props.current.address + ? 1 + : 0 + ) + .map(props.createWalletList)} + {(isValidEthereumAddress(props.evmWallet.address) || hasChildAccounts) && ( + - - - - {props.emojis[1].emoji} - - - - - - {props.emojis[1].name} - - - - EVM - - {isEvm && ( - - - - )} - - - - - + {chrome.i18n.getMessage('Linked_Account')} + )} - - {props.childAccounts && - Object.keys(props.childAccounts).map((key, index) => ( + + {isValidEthereumAddress(props.evmWallet.address) && ( props.setWallets( { - name: props.childAccounts[key]?.name ?? key, - address: key, + name: 'evm', + address: props.evmWallet.address, chain_id: props.currentNetwork, coins: ['flow'], id: 1, }, - key + 'evm' ) } > - + > + + {props.evmWallet.icon} + + + + {props.evmWallet.name} + + - {props.childAccounts[key]?.name ?? key} + EVM - {props.current['address'] === key && ( - + {isEvm && ( + { )} - - {key} - + - ))} + )} + + {props.childAccounts && + Object.keys(props.childAccounts).map((key, index) => ( + + props.setWallets( + { + name: props.childAccounts[key]?.name ?? key, + address: key, + chain_id: props.currentNetwork, + coins: ['flow'], + id: 1, + }, + key + ) + } + > + + + + + + {props.childAccounts[key]?.name ?? key} + + {props.current['address'] === key && ( + + + + )} + + + {key} + + + + + ))} + {/* { diff --git a/src/ui/views/Dashboard/Components/NetworkList.tsx b/src/ui/views/Dashboard/Components/NetworkList.tsx index 9dc98b66..004e2a83 100644 --- a/src/ui/views/Dashboard/Components/NetworkList.tsx +++ b/src/ui/views/Dashboard/Components/NetworkList.tsx @@ -1,10 +1,12 @@ -import React, { useState, useEffect, useRef } from 'react'; import { Box, ListItemButton, Typography, ListItem, ListItemIcon, CardMedia } from '@mui/material'; +import React, { useState, useEffect, useRef } from 'react'; +import { useHistory } from 'react-router-dom'; + import { useWallet } from 'ui/utils'; + import mainnetIndicator from '../../../FRWAssets/svg/mainnetArrow.svg'; -import testnetIndicator from '../../../FRWAssets/svg/testnetArrow.svg'; import networkLink from '../../../FRWAssets/svg/networkLink.svg'; -import { useHistory } from 'react-router-dom'; +import testnetIndicator from '../../../FRWAssets/svg/testnetArrow.svg'; const NetworkList = ({ networkColor, currentNetwork }) => { const usewallet = useWallet(); diff --git a/src/ui/views/Dashboard/Components/WalletFunction.tsx b/src/ui/views/Dashboard/Components/WalletFunction.tsx new file mode 100644 index 00000000..cedf90be --- /dev/null +++ b/src/ui/views/Dashboard/Components/WalletFunction.tsx @@ -0,0 +1,129 @@ +import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord'; +import { ListItem, ListItemButton, ListItemIcon, Typography, Box } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; + +import { useWallet } from 'ui/utils'; + +import IconEnd from '../../../../components/iconfont/IconAVector11Stroke'; + +const WalletFunction = (props) => { + const usewallet = useWallet(); + const [currentBalance, setCurrentBalance] = useState(null); + + const walletFlowBalance = useCallback( + async (address) => { + const balance = await usewallet.getFlowBalance(address); + return balance || 0; + }, + [usewallet] + ); + + const toggleExpand = () => { + props.setExpandAccount((prev) => !prev); + }; + + useEffect(() => { + const fetchBalance = async () => { + try { + const balance = await walletFlowBalance(props.address); + setCurrentBalance(balance); + } catch (error) { + console.error('Error fetching balance:', error); + } + }; + + fetchBalance(); + }, [props.address, walletFlowBalance]); + + return props.address === props.mainAddress || props.expandAccount ? ( + { + if (props.address === props.current['address']) { + toggleExpand(); // Toggle the list if the current address is clicked + } else { + props.setWallets(props, null, props.props_id); // Set the wallet if it's a different address + } + }} + sx={{ mb: 0, padding: '0', cursor: 'pointer' }} + > + + {props.icon && ( + + {props.icon} + + )} + + + {props.name} + {props.address === props.current['address'] && ( + + + + )} + + + {currentBalance !== null + ? `${(Number(currentBalance) / 100000000).toFixed(3)} FLOW` + : 'Loading...'} + + + + {props.address === props.current['address'] && props.walletList.length > 1 && ( + + )} + + + ) : null; +}; + +export default WalletFunction; diff --git a/src/ui/views/Dashboard/Header.tsx b/src/ui/views/Dashboard/Header.tsx index 13fc8a90..15354674 100644 --- a/src/ui/views/Dashboard/Header.tsx +++ b/src/ui/views/Dashboard/Header.tsx @@ -25,12 +25,11 @@ import { useHistory } from 'react-router-dom'; import { storage } from '@/background/webapi'; import eventBus from '@/eventBus'; +import { withPrefix, ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; -import { withPrefix, ensureEvmAddressPrefix } from '@/ui/utils/address'; import { useNews } from '@/ui/utils/NewsContext'; import type { UserInfoResponse, WalletResponse } from 'background/service/networkModel'; import { useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; import IconCopy from '../../../components/iconfont/IconCopy'; import EyeOff from '../../FRWAssets/svg/EyeOff.svg'; @@ -38,6 +37,7 @@ import EyeOff from '../../FRWAssets/svg/EyeOff.svg'; import MenuDrawer from './Components/MenuDrawer'; import NewsView from './Components/NewsView'; import Popup from './Components/Popup'; +import WalletFunction from './Components/WalletFunction'; const useStyles = makeStyles(() => ({ appBar: { @@ -62,20 +62,7 @@ type ChildAccount = { }; }; -const tempEmoji = [ - { - emoji: '🥥', - name: 'Coconut', - bgcolor: '#FFE4C4', - }, - { - emoji: '🥑', - name: 'Avocado', - bgcolor: '#98FB98', - }, -]; - -const Header = ({ loading }) => { +const Header = ({ loading = false }) => { const usewallet = useWallet(); const classes = useStyles(); const history = useHistory(); @@ -88,9 +75,17 @@ const Header = ({ loading }) => { const [drawer, setDrawer] = useState(false); const [userWallet, setWallet] = useState(null); const [currentWallet, setCurrentWallet] = useState(0); + const [evmWallet, setEvmWallet] = useState({ + name: '', + icon: '', + address: '', + chain_id: 'evm', + id: 1, + coins: ['flow'], + color: '', + }); const [current, setCurrent] = useState({}); const [currentNetwork, setNetwork] = useState('mainnet'); - const [emojis, setEmojis] = useState(tempEmoji); const [isSandbox, setIsSandbox] = useState(false); const [userInfo, setUserInfo] = useState(null); @@ -104,8 +99,7 @@ const Header = ({ loading }) => { const [mainnetAvailable, setMainnetAvailable] = useState(true); const [testnetAvailable, setTestnetAvailable] = useState(true); const [evmAddress, setEvmAddress] = useState(''); - - const [flowBalance, setFlowBalance] = useState(0); + const [mainAddress, setMainAddress] = useState(''); const [modeAnonymous, setModeAnonymous] = useState(false); @@ -116,8 +110,9 @@ const Header = ({ loading }) => { const [initialStart, setInitial] = useState(true); const [switchLoading, setSwitchLoading] = useState(false); + const [expandAccount, setExpandAccount] = useState(false); - const [errorMessage, setErrorMessage] = useState(''); + const [, setErrorMessage] = useState(''); const [errorCode, setErrorCode] = useState(null); // const { unreadCount } = useNotificationStore(); // TODO: add notification count @@ -159,9 +154,11 @@ const Header = ({ loading }) => { return (filteredData || []).map((wallet, index) => { return { id: index, - name: walletName, + name: wallet.name || 'Wallet', address: withPrefix(wallet.blockchain[0].address), key: index, + icon: wallet.icon || '', + color: wallet.color || '', }; }); }, @@ -206,9 +203,12 @@ const Header = ({ loading }) => { const keys = await usewallet.getAccount(); const pubKTuple = await usewallet.getPubKey(); if (mainAddress) { + setMainAddress(mainAddress); try { const res = await usewallet.queryEvmAddress(mainAddress); + const evmWallet = await usewallet.getEvmWallet(); setEvmAddress(res!); + setEvmWallet(evmWallet); } catch (err) { console.error('queryEvmAddress err', err); } finally { @@ -225,32 +225,13 @@ const Header = ({ loading }) => { walletData, isChild ); - if (!isChild) { - setFlowBalance(keys.balance); - } else { - usewallet.getUserWallets().then((res) => { - const address = res[0].blockchain[0].address; - usewallet.getFlowBalance(address).then((balance) => { - setFlowBalance(balance); - }); - }); - } + await setOtherAccounts(otherAccounts); await setUserInfo(wallet); await setLoggedIn(loggedInAccounts); - - // usewallet.checkUserDomain(wallet.username); }, [usewallet]); const fetchUserWallet = useCallback(async () => { - const userInfo = await usewallet.getUserInfo(false); - await setUserInfo(userInfo); - if (userInfo.private === 1) { - setModeAnonymous(false); - } else { - setModeAnonymous(true); - } - freshUserWallet(); freshUserInfo(); const childresp: ChildAccount = await usewallet.checkUserChildAccount(); @@ -258,29 +239,32 @@ const Header = ({ loading }) => { usewallet.setChildWallet(childresp); }, [freshUserInfo, freshUserWallet, usewallet]); - const switchAccount = async (account) => { - setSwitchLoading(true); - try { - const switchingTo = process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet'; - await storage.set('currentAccountIndex', account.indexInLoggedInAccounts); - if (account.id) { - await storage.set('currentId', account.id); - } else { - await storage.set('currentId', ''); + const switchAccount = useCallback( + async (account) => { + setSwitchLoading(true); + try { + const switchingTo = process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet'; + await storage.set('currentAccountIndex', account.indexInLoggedInAccounts); + if (account.id) { + await storage.set('currentId', account.id); + } else { + await storage.set('currentId', ''); + } + + await usewallet.lockWallet(); + await usewallet.clearWallet(); + await usewallet.switchNetwork(switchingTo); + + history.push('/switchunlock'); + } catch (error) { + console.error('Error during account switch:', error); + // Handle any additional error reporting or user feedback here if needed + } finally { + setSwitchLoading(false); } - - await usewallet.lockWallet(); - await usewallet.clearWallet(); - await usewallet.switchNetwork(switchingTo); - - history.push('/switchunlock'); - } catch (error) { - console.error('Error during account switch:', error); - // Handle any additional error reporting or user feedback here if needed - } finally { - setSwitchLoading(false); - } - }; + }, + [usewallet, history] + ); const loadNetwork = useCallback(async () => { const network = await usewallet.getNetwork(); @@ -290,38 +274,6 @@ const Header = ({ loading }) => { await setNetwork(network); }, [usewallet]); - // const loadInbox = async () => { - - // const giftBoxHistory = await usewallet.getHistory(); - // const resp = await usewallet.fetchFlownsInbox(); - // let tempRead = 0; - // let nftRead = 0; - // Object.keys(resp.vaultBalances).map(() => { - // tempRead += 1; - // }); - // Object.keys(resp.collections).map((k) => { - // nftRead += resp.collections[k].length; - // }); - - // giftBoxHistory.token.map((token) => { - // const key = Object.keys(token)[0]; - // if (parseFloat(token[key]) === parseFloat(resp.vaultBalances[key])) { - // tempRead -= 1; - // } - // }); - - // Object.keys(giftBoxHistory.nft).map((k) => { - // const arr = giftBoxHistory.nft[k]; - // arr.map((v) => { - // if (resp.collections[k].includes(v)) { - // nftRead -= 1; - // } - // }) - // }); - // const totalUnread = nftRead + tempRead; - // setUnread(totalUnread); - - // } const loadDeveloperMode = async () => { const developerMode = await storage.get('developerMode'); if (developerMode) { @@ -329,17 +281,8 @@ const Header = ({ loading }) => { } }; - // const goToInbox = () => { - // if (domain) { - // history.push('/dashboard/inbox'); - // } else { - // history.push('/dashboard/flowns'); - // } - // } - - const setWallets = async (walletInfo, key) => { - await usewallet.setActiveWallet(walletInfo, key); - + const setWallets = async (walletInfo, key, index = null) => { + await usewallet.setActiveWallet(walletInfo, key, index); setMainLoading(false); // Clear collections @@ -352,7 +295,6 @@ const Header = ({ loading }) => { // Navigate if needed history.push('/dashboard'); - //eslint-disable-next-line no-restricted-globals window.location.reload(); }; @@ -368,7 +310,7 @@ const Header = ({ loading }) => { } // The header should handle transactionError events if (request.msg === 'transactionError') { - console.log('transactionError', request.errorMessage, request.errorCode); + console.warn('transactionError', request.errorMessage, request.errorCode); // The error message is not used anywhere else for now setErrorMessage(request.errorMessage); setErrorCode(request.errorCode); @@ -417,28 +359,18 @@ const Header = ({ loading }) => { await usewallet.checkNetwork(); }, [usewallet]); - const fetchProfile = useCallback(async () => { - const emojires = await usewallet.getEmoji(); - setEmojis(emojires); - }, [usewallet]); - useEffect(() => { loadNetwork(); fetchUserWallet(); loadDeveloperMode(); checkPendingTx(); checkAuthStatus(); - fetchProfile(); const addressDone = () => { fetchUserWallet(); }; - const changeEmoji = () => { - fetchProfile(); - }; - - const networkChanged = (/* network */) => { + const networkChanged = (network) => { loadNetwork(); }; @@ -447,15 +379,13 @@ const Header = ({ loading }) => { * Fired when a message is sent from either an extension process or a content script. */ eventBus.addEventListener('addressDone', addressDone); - eventBus.addEventListener('profileChanged', changeEmoji); eventBus.addEventListener('switchNetwork', networkChanged); return () => { eventBus.removeEventListener('addressDone', addressDone); eventBus.removeEventListener('switchNetwork', networkChanged); - eventBus.removeEventListener('profileChanged', changeEmoji); chrome.runtime.onMessage.removeListener(transactionHandler); }; - }, [checkAuthStatus, checkPendingTx, currentNetwork, fetchProfile, fetchUserWallet, loadNetwork]); + }, [checkAuthStatus, checkPendingTx, currentNetwork, fetchUserWallet, loadNetwork]); useEffect(() => { const list = wallets(userWallet); @@ -501,87 +431,6 @@ const Header = ({ loading }) => { [usewallet, fetchUserWallet, loadNetwork, toggleUsernameDrawer, history] ); - const WalletFunction = (props) => { - return ( - { - setWallets(null, null); - }} - sx={{ mb: 0, paddingX: '0', cursor: 'pointer' }} - > - - {emojis && ( - - - {emojis[0].emoji} - - - )} - - - {emojis[0].name} - {props.address === current['address'] && ( - - - - )} - - - {/* {' '} */} - {(flowBalance / 100000000).toFixed(3)} FLOW - - - - {/* */} - - - ); - }; - const AccountFunction = (props) => { return ( { const createWalletList = (props) => { return ( - - + + ); }; @@ -981,8 +843,7 @@ const Header = ({ loading }) => { createWalletList={createWalletList} setWallets={setWallets} currentNetwork={currentNetwork} - evmAddress={evmAddress} - emojis={emojis} + evmWallet={evmWallet} networkColor={networkColor} evmLoading={evmLoading} modeOn={modeOn} diff --git a/src/ui/views/Dashboard/index.tsx b/src/ui/views/Dashboard/index.tsx index 0cc2b6ba..eb5a4ffa 100644 --- a/src/ui/views/Dashboard/index.tsx +++ b/src/ui/views/Dashboard/index.tsx @@ -2,7 +2,7 @@ import Box from '@mui/material/Box'; import { useTheme } from '@mui/material/styles'; import { getApp, initializeApp } from 'firebase/app'; import { fetchAndActivate, getRemoteConfig } from 'firebase/remote-config'; -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { useLocation, useHistory } from 'react-router-dom'; import SwipeableViews from 'react-swipeable-views'; @@ -49,7 +49,7 @@ const Dashboard = ({ value, setValue }) => { setValue(index); }; - const fetchAll = async () => { + const fetchAll = useCallback(async () => { setLoading(true); //todo fix cadence loading await wallet.getCadenceScripts(); @@ -83,11 +83,11 @@ const Dashboard = ({ value, setValue }) => { setNetwork(network); setDomain(userDomain); setLoading(false); - }; + }, [wallet]); useEffect(() => { fetchAll(); - }, [wallet]); + }, [fetchAll, wallet]); return (
@@ -101,7 +101,6 @@ const Dashboard = ({ value, setValue }) => { > {currentNetwork === 'testnet' && value === 0 && } {/*
*/} - { return ( diff --git a/src/ui/views/Deposit/index.tsx b/src/ui/views/Deposit/index.tsx index 445a2447..49df50c8 100644 --- a/src/ui/views/Deposit/index.tsx +++ b/src/ui/views/Deposit/index.tsx @@ -1,17 +1,17 @@ -import React, { useState, useEffect, useRef } from 'react'; -import { Box, MenuItem, Select, Typography, Tooltip, Button } from '@mui/material'; +import { MenuItem, Select, Typography, Tooltip, Button } from '@mui/material'; +import { useTheme, styled, StyledEngineProvider } from '@mui/material/styles'; +import { makeStyles } from '@mui/styles'; import QRCodeStyling from 'qr-code-styling'; -import { useWallet } from 'ui/utils'; -import { useTheme, styled } from '@mui/material/styles'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import React, { useState, useEffect, useRef, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { makeStyles } from '@mui/styles'; -import { StyledEngineProvider } from '@mui/material/styles'; + +import { withPrefix } from '@/shared/utils/address'; +import { LLTestnetIndicator, LLHeader } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import IconCopy from '../../../components/iconfont/IconCopy'; -import { LLTestnetIndicator } from 'ui/FRWComponent'; + import TestnetWarning from './TestnetWarning'; -import { withPrefix } from '@/ui/utils/address'; -import { LLHeader } from 'ui/FRWComponent'; const useStyles = makeStyles((theme) => ({ page: { @@ -114,7 +114,7 @@ const Deposit = () => { const classes = useStyles(); const theme = useTheme(); const history = useHistory(); - const wallet = useWallet(); + const usewallet = useWallet(); const ref = useRef(null); const [currentWallet, setCurrentWallet] = useState(0); @@ -123,11 +123,11 @@ const Deposit = () => { const [userInfo, setUserInfo] = useState(null); const [active, setIsActive] = useState(false); - const fetch = async () => { - const isChild = await wallet.getActiveWallet(); + const fetchStuff = useCallback(async () => { + const isChild = await usewallet.getActiveWallet(); let childresp = {}; try { - childresp = await wallet.checkUserChildAccount(); + childresp = await usewallet.checkUserChildAccount(); // Handle the response when there is no error } catch (error) { // Handle the error here @@ -135,7 +135,7 @@ const Deposit = () => { } if (isChild === 'evm') { setIsActive(true); - const wallets = await wallet.getEvmWallet(); + const wallets = await usewallet.getEvmWallet(); const result = [ { id: 0, @@ -164,22 +164,22 @@ const Deposit = () => { ); } else { setIsActive(true); - const wallets = await wallet.getUserWallets(); - setUserWallets( - wallets.map((ele, idx) => ({ - id: idx, - name: chrome.i18n.getMessage('Wallet'), - address: withPrefix(ele.blockchain[0].address), - })) - ); + const cw = await usewallet.getCurrentWallet(); + setUserWallets([ + { + id: 0, + name: cw.name, + address: cw.address, + }, + ]); } - await wallet.setDashIndex(0); - const network = await wallet.getNetwork(); + await usewallet.setDashIndex(0); + const network = await usewallet.getNetwork(); setNetwork(network); - const user = await wallet.getUserInfo(false); + const user = await usewallet.getUserInfo(false); setUserInfo(user); - }; + }, [currentNetwork, usewallet]); useEffect(() => { if (userWallets && userInfo) { @@ -191,8 +191,8 @@ const Deposit = () => { }, [userWallets, currentWallet, userInfo]); useEffect(() => { - fetch(); - }, []); + fetchStuff(); + }, [fetchStuff]); useEffect(() => { if (ref.current) { diff --git a/src/ui/views/EvmMove/MoveFromChild/MoveToken.tsx b/src/ui/views/EvmMove/MoveFromChild/MoveToken.tsx index d3cb1e16..3ea0b7a5 100644 --- a/src/ui/views/EvmMove/MoveFromChild/MoveToken.tsx +++ b/src/ui/views/EvmMove/MoveFromChild/MoveToken.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; import { Box, Typography, @@ -13,14 +13,16 @@ import { Chip, Tooltip, } from '@mui/material'; +import { StyledEngineProvider } from '@mui/material/styles'; import { makeStyles } from '@mui/styles'; +import BN from 'bignumber.js'; +import React, { useState, useEffect, useCallback } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + +import CancelIcon from '../../../../components/iconfont/IconClose'; import IconFlow from '../../../../components/iconfont/IconFlow'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; -import { StyledEngineProvider } from '@mui/material/styles'; -import BN from 'bignumber.js'; -import { Presets } from 'react-component-transition'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -142,13 +144,13 @@ const MoveToken = ({ setCoinType(!coinType); }; - const currentCoinType = () => { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [currentCoinType]); useEffect(() => { if (coinType) { @@ -165,7 +167,7 @@ const MoveToken = ({ setAmount(parseFloat(value.toFixed(3))); } } - }, [secondAmount]); + }, [coinInfo.balance, coinInfo.price, coinType, secondAmount, setAmount, setExceed]); useEffect(() => { if (!coinType) { @@ -182,7 +184,7 @@ const MoveToken = ({ setSecondAmount(value); } } - }, [amount, coin]); + }, [amount, coin, coinInfo, coinInfo.price, coinInfo.unit, coinType, setExceed, setSecondAmount]); return ( @@ -265,33 +267,31 @@ const MoveToken = ({ {coinInfo.balance} - - {exceed && ( - + + + - - - {chrome.i18n.getMessage('Insufficient_balance') + - (coin === 'flow' - ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') - : '')} - - - )} - + {chrome.i18n.getMessage('Insufficient_balance') + + (coin === 'flow' + ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') + : '')} + + + ); diff --git a/src/ui/views/EvmMove/MoveFromChild/index.tsx b/src/ui/views/EvmMove/MoveFromChild/index.tsx index 1e08292a..04a9d720 100644 --- a/src/ui/views/EvmMove/MoveFromChild/index.tsx +++ b/src/ui/views/EvmMove/MoveFromChild/index.tsx @@ -1,17 +1,16 @@ import CloseIcon from '@mui/icons-material/Close'; import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; @@ -27,6 +26,27 @@ interface TransferConfirmationProps { handleCancelBtnClicked: () => void; handleAddBtnClicked: () => void; } +const USER_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; + +const CHILD_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; const MoveFromChild = (props: TransferConfirmationProps) => { enum ENV { @@ -43,27 +63,6 @@ const MoveFromChild = (props: TransferConfirmationProps) => { // Static = 'Static', // CDN = 'CDN' // } - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const childContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; const empty: CoinItem = { coin: '', @@ -83,8 +82,8 @@ const MoveFromChild = (props: TransferConfirmationProps) => { // const [exceed, setExceed] = useState(false); const [amount, setAmount] = useState(''); // const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); - const [childUserInfo, setChildUser] = useState(childContact); + const [userInfo, setUser] = useState(USER_CONTACT); + const [childUserInfo, setChildUser] = useState(CHILD_CONTACT); const [network, setNetwork] = useState('mainnet'); const [childAddress, setChildAddress] = useState(''); const [coinInfo, setCoinInfo] = useState(empty); @@ -95,13 +94,14 @@ const MoveFromChild = (props: TransferConfirmationProps) => { const [minAmount, setMinAmount] = useState(0.001); const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount: Number(amount) || 0, + coin: currentCoin, movingBetweenEVMAndFlow: true, }); const isLowStorage = isSufficient !== undefined && !isSufficient; // isSufficient is undefined when the storage check is not yet completed const isLowStorageAfterAction = sufficientAfterAction !== undefined && !sufficientAfterAction; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const token = await usewallet.getCurrentCoin(); @@ -119,38 +119,40 @@ const MoveFromChild = (props: TransferConfirmationProps) => { setCoinInfo(coinInfo!); const info = await usewallet.getUserInfo(false); - userContact.address = withPrefix(wallet) || ''; - userContact.avatar = info.avatar; - userContact.contact_name = info.username; - setUser(userContact); + + const walletAddress = withPrefix(wallet) || ''; + setUser({ + ...USER_CONTACT, + address: walletAddress, + avatar: info.avatar, + contact_name: info.username, + }); const childResp = await usewallet.checkUserChildAccount(); const cwallet = childResp[currentAddress!]; - childContact.address = withPrefix(currentAddress!) || ''; - childContact.avatar = cwallet.thumbnail.url; - childContact.contact_name = cwallet.name; - - setUserMinAmount(); - - setChildUser(childContact); - // const result = await usewallet.openapi.fetchTokenList(network); - setLoading(false); - return; - }; - const setUserMinAmount = async () => { try { // Try fetching the min amount from the API - const minAmount = await usewallet.openapi.getAccountMinFlow(userContact.address); + const minAmount = await usewallet.openapi.getAccountMinFlow(walletAddress); setMinAmount(minAmount); } catch (error) { // If there's an error, set the min amount to 0.001 console.error('Error fetching min amount:', error); setMinAmount(0.001); } - }; - const moveToken = async () => { + setChildUser({ + ...CHILD_CONTACT, + address: withPrefix(currentAddress!) || '', + avatar: cwallet.thumbnail.url, + contact_name: cwallet.name, + }); + // const result = await usewallet.openapi.fetchTokenList(network); + setLoading(false); + return; + }, [usewallet]); + + const moveToken = useCallback(async () => { setLoading(true); const tokenResult = await wallet.openapi.getTokenInfo(currentCoin, network); usewallet @@ -171,28 +173,28 @@ const MoveFromChild = (props: TransferConfirmationProps) => { console.log(err); setLoading(false); }); - }; + }, [currentCoin, network, usewallet, childUserInfo, amount, userWallet, history, props]); const handleMove = async () => { moveToken(); }; - const handleCoinInfo = async () => { + const handleCoinInfo = useCallback(async () => { if (coinList.length > 0) { const coinInfo = coinList.find( (coin) => coin.unit.toLowerCase() === currentCoin.toLowerCase() ); setCoinInfo(coinInfo!); } - }; + }, [coinList, currentCoin]); useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); useEffect(() => { handleCoinInfo(); - }, [currentCoin]); + }, [currentCoin, handleCoinInfo]); return ( ({ customInputLabel: { @@ -141,13 +140,13 @@ const MoveToken = ({ setCoinType(!coinType); }; - const currentCoinType = () => { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [coinInfo.unit, currentCoinType]); useEffect(() => { if (coinType) { @@ -164,7 +163,7 @@ const MoveToken = ({ setAmount(parseFloat(value.toFixed(3))); } } - }, [secondAmount]); + }, [coinInfo.balance, coinInfo.price, coinType, secondAmount, setAmount, setExceed]); useEffect(() => { if (!coinType) { @@ -181,7 +180,7 @@ const MoveToken = ({ setSecondAmount(value); } } - }, [amount, coin]); + }, [amount, coin, coinInfo, coinType, setExceed, setSecondAmount]); return ( @@ -264,33 +263,31 @@ const MoveToken = ({ {coinInfo.balance} - - {exceed && ( - + + + - - - {chrome.i18n.getMessage('Insufficient_balance') + - (coin === 'flow' - ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') - : '')} - - - )} - + {chrome.i18n.getMessage('Insufficient_balance') + + (coin === 'flow' + ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') + : '')} + + + ); diff --git a/src/ui/views/EvmMove/MoveFromEvm/index.tsx b/src/ui/views/EvmMove/MoveFromEvm/index.tsx index cc2191fd..af8a3b04 100644 --- a/src/ui/views/EvmMove/MoveFromEvm/index.tsx +++ b/src/ui/views/EvmMove/MoveFromEvm/index.tsx @@ -1,17 +1,16 @@ import CloseIcon from '@mui/icons-material/Close'; import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; @@ -27,40 +26,39 @@ interface TransferConfirmationProps { handleCancelBtnClicked: () => void; handleAddBtnClicked: () => void; } +const USER_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; -const MoveFromEvm = (props: TransferConfirmationProps) => { - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const evmContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; +const EVM_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; +const MoveFromEvm = (props: TransferConfirmationProps) => { const usewallet = useWallet(); const history = useHistory(); const [userWallet, setWallet] = useState(null); @@ -69,11 +67,11 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { // const [exceed, setExceed] = useState(false); const [amount, setAmount] = useState(''); // const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); - const [evmUserInfo, setEvmUser] = useState(evmContact); + const [userInfo, setUser] = useState(USER_CONTACT); + const [evmUserInfo, setEvmUser] = useState(EVM_CONTACT); const [network, setNetwork] = useState('mainnet'); const [evmAddress, setEvmAddress] = useState(''); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [secondAmount, setSecondAmount] = useState('0.0'); const [isLoading, setLoading] = useState(false); const [exceed, setExceed] = useState(false); @@ -81,13 +79,14 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount: Number(amount) || 0, + coin: currentCoin, movingBetweenEVMAndFlow: true, }); const isLowStorage = isSufficient !== undefined && !isSufficient; // isSufficient is undefined when the storage check is not yet completed const isLowStorageAfterAction = sufficientAfterAction !== undefined && !sufficientAfterAction; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const wallet = await usewallet.getMainWallet(); @@ -101,30 +100,30 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { setEvmAddress(evmWallet.address); const coinList = await usewallet.getCoinList(); setCoinList(coinList); - const tokenResult = await usewallet.openapi.getTokenInfo(token, network); + const tokenResult = await usewallet.openapi.getEvmTokenInfo(token, network); const coinInfo = coinList.find( (coin) => coin && coin.unit.toLowerCase() === tokenResult!.symbol.toLowerCase() ); setCoinInfo(coinInfo!); const info = await usewallet.getUserInfo(false); - userContact.address = withPrefix(wallet) || ''; - userContact.avatar = info.avatar; - userContact.contact_name = info.username; + + const userContact = { + ...USER_CONTACT, + address: withPrefix(wallet) || '', + avatar: info.avatar, + contact_name: info.username, + }; setUser(userContact); - evmContact.address = withPrefix(evmWallet.address) || ''; - evmContact.avatar = evmWallet.icon; - evmContact.contact_name = evmWallet.name; + const evmContact = { + ...EVM_CONTACT, + address: withPrefix(evmWallet.address) || '', + avatar: evmWallet.icon, + contact_name: evmWallet.name, + }; setEvmUser(evmContact); - setUserMinAmount(); - - // const result = await usewallet.openapi.fetchTokenList(network); - setLoading(false); - return; - }; - const setUserMinAmount = async () => { try { // Try fetching the min amount from the API const minAmount = await usewallet.openapi.getAccountMinFlow(userContact.address); @@ -134,7 +133,10 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { console.error('Error fetching min amount:', error); setMinAmount(0.001); } - }; + // const result = await usewallet.openapi.fetchTokenList(network); + setLoading(false); + return; + }, [usewallet]); const moveToken = async () => { setLoading(true); @@ -160,7 +162,7 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { const bridgeToken = async () => { setLoading(true); - const tokenResult = await wallet.openapi.getTokenInfo(currentCoin, network); + const tokenResult = await wallet.openapi.getEvmTokenInfo(currentCoin, network); let flowId = tokenResult!['flowIdentifier']; @@ -192,14 +194,14 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { }); }; - const handleCoinInfo = async () => { + const handleCoinInfo = useCallback(async () => { if (coinList.length > 0) { const coinInfo = coinList.find( (coin) => coin.unit.toLowerCase() === currentCoin.toLowerCase() ); setCoinInfo(coinInfo!); } - }; + }, [coinList, currentCoin]); const handleMove = async () => { if (currentCoin.toLowerCase() === 'flow') { @@ -211,11 +213,11 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); useEffect(() => { handleCoinInfo(); - }, [currentCoin]); + }, [currentCoin, handleCoinInfo]); return ( { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [currentCoinType]); useEffect(() => { if (coinType) { @@ -168,7 +168,7 @@ const MoveToken = ({ setAmount(parseFloat(value.toFixed(3))); } } - }, [secondAmount]); + }, [coinInfo.balance, coinInfo.price, coinType, secondAmount, setAmount, setExceed]); useEffect(() => { if (!coinType) { @@ -185,7 +185,7 @@ const MoveToken = ({ setSecondAmount(value); } } - }, [amount, coin]); + }, [amount, coin, coinInfo, coinType, setExceed, setSecondAmount]); return ( @@ -268,33 +268,31 @@ const MoveToken = ({ {coinInfo.balance} - - {exceed && ( - + + + - - - {chrome.i18n.getMessage('Insufficient_balance') + - (coin === 'flow' - ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') - : '')} - - - )} - + {chrome.i18n.getMessage('Insufficient_balance') + + (coin === 'flow' + ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') + : '')} + + + ); diff --git a/src/ui/views/EvmMove/MoveFromFlow/index.tsx b/src/ui/views/EvmMove/MoveFromFlow/index.tsx index ded75524..2a832969 100644 --- a/src/ui/views/EvmMove/MoveFromFlow/index.tsx +++ b/src/ui/views/EvmMove/MoveFromFlow/index.tsx @@ -1,17 +1,16 @@ import CloseIcon from '@mui/icons-material/Close'; import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix, isValidEthereumAddress } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; @@ -27,6 +26,37 @@ interface TransferConfirmationProps { handleCancelBtnClicked: () => void; handleAddBtnClicked: () => void; } +const USER_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; + +const EVM_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; + +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; const MoveFromFlow = (props: TransferConfirmationProps) => { enum ENV { @@ -43,37 +73,6 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { // Static = 'Static', // CDN = 'CDN' // } - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const evmContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; const usewallet = useWallet(); const history = useHistory(); @@ -83,11 +82,11 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { // const [exceed, setExceed] = useState(false); const [amount, setAmount] = useState(''); // const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); - const [evmUserInfo, setEvmUser] = useState(evmContact); + const [userInfo, setUser] = useState(USER_CONTACT); + const [evmUserInfo, setEvmUser] = useState(EVM_CONTACT); const [network, setNetwork] = useState('mainnet'); const [evmAddress, setEvmAddress] = useState(''); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [secondAmount, setSecondAmount] = useState('0.0'); const [isLoading, setLoading] = useState(false); const [errorType, setErrorType] = useState(null); @@ -96,13 +95,14 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount: Number(amount) || 0, + coin: currentCoin, movingBetweenEVMAndFlow: true, }); const isLowStorage = isSufficient !== undefined && !isSufficient; // isSufficient is undefined when the storage check is not yet completed const isLowStorageAfterAction = sufficientAfterAction !== undefined && !sufficientAfterAction; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const token = await usewallet.getCurrentCoin(); @@ -122,22 +122,24 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { setCoinInfo(coinInfo!); const info = await usewallet.getUserInfo(false); - userContact.address = withPrefix(wallet) || ''; - userContact.avatar = info.avatar; - userContact.contact_name = info.username; + const userContact = { + ...USER_CONTACT, + address: withPrefix(wallet) || '', + avatar: info.avatar, + contact_name: info.username, + }; setUser(userContact); - evmContact.address = withPrefix(evmWallet.address) || ''; - evmContact.avatar = evmWallet.icon; - evmContact.contact_name = evmWallet.name; + const evmContact = { + ...EVM_CONTACT, + address: withPrefix(evmWallet.address) || '', + avatar: evmWallet.icon, + contact_name: evmWallet.name, + }; setEvmUser(evmContact); // const result = await usewallet.openapi.fetchTokenList(network); setLoading(false); - setUserMinAmount(); - return; - }; - const setUserMinAmount = async () => { try { // Try fetching the min amount from the API const minAmount = await usewallet.openapi.getAccountMinFlow(userContact.address); @@ -147,7 +149,8 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { console.error('Error fetching min amount:', error); setMinAmount(0.001); } - }; + return; + }, [usewallet]); const moveToken = async () => { setLoading(true); @@ -213,22 +216,22 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { } }; - const handleCoinInfo = async () => { + const handleCoinInfo = useCallback(async () => { if (coinList.length > 0) { const coinInfo = coinList.find( (coin) => coin.unit.toLowerCase() === currentCoin.toLowerCase() ); setCoinInfo(coinInfo!); } - }; + }, [coinList, currentCoin]); useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); useEffect(() => { handleCoinInfo(); - }, [currentCoin]); + }, [currentCoin, handleCoinInfo]); return ( ({ customInputLabel: { @@ -142,13 +144,13 @@ const MoveToken = ({ setCoinType(!coinType); }; - const currentCoinType = () => { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [currentCoinType]); useEffect(() => { if (coinType) { @@ -165,7 +167,7 @@ const MoveToken = ({ setAmount(parseFloat(value.toFixed(3))); } } - }, [secondAmount]); + }, [coinInfo.balance, coinInfo.price, coinType, secondAmount, setAmount, setExceed]); useEffect(() => { if (!coinType) { @@ -182,7 +184,7 @@ const MoveToken = ({ setSecondAmount(value); } } - }, [amount, coin]); + }, [amount, coin, coinInfo, coinType, setExceed, setSecondAmount]); return ( @@ -265,33 +267,31 @@ const MoveToken = ({ {coinInfo.balance} - - {exceed && ( - + + + - - - {chrome.i18n.getMessage('Insufficient_balance') + - (coin === 'flow' - ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') - : '')} - - - )} - + {chrome.i18n.getMessage('Insufficient_balance') + + (coin === 'flow' + ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') + : '')} + + + ); diff --git a/src/ui/views/EvmMove/MoveFromParent/index.tsx b/src/ui/views/EvmMove/MoveFromParent/index.tsx index 00a110bd..da0eaacb 100644 --- a/src/ui/views/EvmMove/MoveFromParent/index.tsx +++ b/src/ui/views/EvmMove/MoveFromParent/index.tsx @@ -1,17 +1,17 @@ import CloseIcon from '@mui/icons-material/Close'; import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material'; import { ThemeProvider } from '@mui/material/styles'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; -import type { CoinItem } from 'background/service/coinList'; +import { type CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; @@ -27,6 +27,37 @@ interface TransferConfirmationProps { handleCancelBtnClicked: () => void; handleAddBtnClicked: () => void; } +const USER_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; + +const CHILD_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; + +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; const MoveFromParent = (props: TransferConfirmationProps) => { enum ENV { @@ -43,37 +74,6 @@ const MoveFromParent = (props: TransferConfirmationProps) => { // Static = 'Static', // CDN = 'CDN' // } - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const childContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; const usewallet = useWallet(); const history = useHistory(); @@ -83,11 +83,11 @@ const MoveFromParent = (props: TransferConfirmationProps) => { // const [exceed, setExceed] = useState(false); const [amount, setAmount] = useState(''); // const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); - const [childUserInfo, setChildUser] = useState(childContact); + const [userInfo, setUser] = useState(USER_CONTACT); + const [childUserInfo, setChildUser] = useState(CHILD_CONTACT); const [network, setNetwork] = useState('mainnet'); const [childAddress, setChildAddress] = useState(''); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [secondAmount, setSecondAmount] = useState('0.0'); const [isLoading, setLoading] = useState(false); const [errorType, setErrorType] = useState(null); @@ -95,13 +95,14 @@ const MoveFromParent = (props: TransferConfirmationProps) => { const [minAmount, setMinAmount] = useState(0.001); const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount: Number(amount) || 0, + coin: currentCoin, movingBetweenEVMAndFlow: true, }); const isLowStorage = isSufficient !== undefined && !isSufficient; // isSufficient is undefined when the storage check is not yet completed const isLowStorageAfterAction = sufficientAfterAction !== undefined && !sufficientAfterAction; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const token = await usewallet.getCurrentCoin(); @@ -120,25 +121,26 @@ const MoveFromParent = (props: TransferConfirmationProps) => { setCoinInfo(coinInfo!); const info = await usewallet.getUserInfo(false); - userContact.address = withPrefix(wallet) || ''; - userContact.avatar = info.avatar; - userContact.contact_name = info.username; + const userContact = { + ...USER_CONTACT, + address: withPrefix(wallet) || '', + avatar: info.avatar, + contact_name: info.username, + }; setUser(userContact); const childResp = await usewallet.checkUserChildAccount(); const cwallet = childResp[currentAddress!]; - childContact.address = withPrefix(currentAddress!) || ''; - childContact.avatar = cwallet.thumbnail.url; - childContact.contact_name = cwallet.name; + const childContact = { + ...CHILD_CONTACT, + address: withPrefix(currentAddress!) || '', + avatar: cwallet.thumbnail.url, + contact_name: cwallet.name, + }; setChildUser(childContact); // const result = await usewallet.openapi.fetchTokenList(network); setLoading(false); - setUserMinAmount(); - return; - }; - - const setUserMinAmount = async () => { try { // Try fetching the min amount from the API const minAmount = await usewallet.openapi.getAccountMinFlow(userContact.address); @@ -148,7 +150,11 @@ const MoveFromParent = (props: TransferConfirmationProps) => { console.error('Error fetching min amount:', error); setMinAmount(0.001); } - }; + + return; + }, [usewallet]); + + const setUserMinAmount = async () => {}; const moveToken = async () => { setLoading(true); @@ -179,22 +185,22 @@ const MoveFromParent = (props: TransferConfirmationProps) => { moveToken(); }; - const handleCoinInfo = async () => { + const handleCoinInfo = useCallback(async () => { if (coinList.length > 0) { const coinInfo = coinList.find( (coin) => coin.unit.toLowerCase() === currentCoin.toLowerCase() ); setCoinInfo(coinInfo!); } - }; + }, [coinList, currentCoin]); useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); useEffect(() => { handleCoinInfo(); - }, [currentCoin]); + }, [currentCoin, handleCoinInfo]); return ( { const [emoji, setEmoji] = useState(tempEmoji); const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); - setEmoji(emojiList[0]); + const currentWallet = await usewallet.getCurrentWallet(); + const emojiObject = tempEmoji; + emojiObject.emoji = currentWallet.icon; + emojiObject.name = currentWallet.name; + emojiObject.bgcolor = currentWallet.color; + emojiObject['type'] = 'parent'; + setEmoji(emojiObject); }; useEffect(() => { getEmoji(); + console.log('userInfo ', wallet, userInfo); }, [userInfo]); return ( diff --git a/src/ui/views/EvmMove/TransferTo.tsx b/src/ui/views/EvmMove/TransferTo.tsx index f76419d3..9a61fdeb 100644 --- a/src/ui/views/EvmMove/TransferTo.tsx +++ b/src/ui/views/EvmMove/TransferTo.tsx @@ -15,11 +15,23 @@ const TransferTo = ({ wallet, userInfo }) => { const [emoji, setEmoji] = useState(tempEmoji); const getEmoji = async () => { - const emojiList = await usewallet.getEmoji(); - setEmoji(emojiList[1]); + console.log('isEvm ', emoji); + if (!emoji['type']) { + const currentWallet = await usewallet.getEvmWallet(); + console.log('getEvmWallet ', currentWallet); + const emojiObject = tempEmoji; + emojiObject.emoji = currentWallet.icon; + emojiObject.name = currentWallet.name; + emojiObject.bgcolor = currentWallet.color; + emojiObject['type'] = 'evm'; + setEmoji(emojiObject); + } + + console.log('emoji ', emoji); }; useEffect(() => { + console.log('transfer to ', wallet, userInfo); getEmoji(); }, [userInfo]); diff --git a/src/ui/views/Forgot/Recover/RecoverPage.tsx b/src/ui/views/Forgot/Recover/RecoverPage.tsx index 05692950..35d2bb28 100644 --- a/src/ui/views/Forgot/Recover/RecoverPage.tsx +++ b/src/ui/views/Forgot/Recover/RecoverPage.tsx @@ -1,12 +1,13 @@ -import React, { useEffect, useRef, useState } from 'react'; // import { useTranslation } from 'react-i18next'; -import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; -import { Typography, Box, FormControl, List, ListItem, ListItemText } from '@mui/material'; +import { Typography, Box, FormControl, Input } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import React, { useEffect, useRef, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { LLPrimaryButton, CredentialBox, LLSecondaryButton } from 'ui/FRWComponent'; -import { Input } from '@mui/material'; -import { Presets } from 'react-component-transition'; +import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; + import CancelIcon from '../../../../components/iconfont/IconClose'; -import { makeStyles } from '@mui/styles'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -149,20 +150,18 @@ const RecoverPage = ({ dataArray, setArray, goNext }) => { onKeyDown={handleKeyDown} /> - - {showError && ( - - {usernameError()} - - )} - + + + {usernameError()} + + { const usewallet = useWallet(); @@ -36,8 +36,7 @@ const ShowKey = ({ handleClick, mnemonic }) => { }; return ( - - + <> {chrome.i18n.getMessage('Save_your_Private_Key')} @@ -221,7 +220,7 @@ const ShowKey = ({ handleClick, mnemonic }) => { errorMessage={chrome.i18n.getMessage('This_action_will_remove')} /> )} - + ); }; diff --git a/src/ui/views/Forgot/Recover/index.tsx b/src/ui/views/Forgot/Recover/index.tsx index ad87674a..dc4f83f9 100644 --- a/src/ui/views/Forgot/Recover/index.tsx +++ b/src/ui/views/Forgot/Recover/index.tsx @@ -1,17 +1,18 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton, Snackbar, Alert } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { storage } from 'background/webapi'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + +import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; +import RegisterHeader from '../../Register/RegisterHeader'; + import RecoverPage from './RecoverPage'; import ShowKey from './ShowKey'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../../Register/RegisterHeader'; -import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; enum Direction { Right, @@ -22,22 +23,12 @@ const Recover = () => { const history = useHistory(); const wallet = useWallet(); const [activeIndex, onChange] = useState(0); - const [mnemonic, setMnemonic] = useState(''); - const [pk, setPk] = useState(null); - const [username, setUsername] = useState(''); - const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); + const [errMessage] = useState(chrome.i18n.getMessage('No__backup__found')); const [showError, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); - const [password, setPassword] = useState(null); - const [accounts, setAccounts] = useState([]); - const [isImport, setImport] = useState(false); + const [, setPassword] = useState(null); const [dataArray, setArray] = useState([]); - const getUsername = (username: string) => { - setUsername(username.toLowerCase()); - }; - const loadTempPassword = async () => { const temp = await storage.get('tempPassword'); if (temp) { @@ -45,7 +36,7 @@ const Recover = () => { } }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -57,7 +48,7 @@ const Recover = () => { .catch(() => { return; }); - }; + }, [history, wallet]); const goNext = () => { setDirection(Direction.Right); if (activeIndex < 5) { @@ -66,10 +57,6 @@ const Recover = () => { window.close(); } }; - const goEnd = () => { - setDirection(Direction.Right); - onChange(5); - }; const goBack = () => { setDirection(Direction.Left); @@ -103,12 +90,11 @@ const Recover = () => { }; useEffect(() => { - console.log('wallet'); loadView(); - }, []); + }, [loadView]); return ( - + <> {
- + {page(activeIndex)} - +
@@ -186,7 +156,7 @@ const Recover = () => { - + ); }; diff --git a/src/ui/views/Forgot/Reset/ResetPage.tsx b/src/ui/views/Forgot/Reset/ResetPage.tsx index 05556591..a524fec9 100644 --- a/src/ui/views/Forgot/Reset/ResetPage.tsx +++ b/src/ui/views/Forgot/Reset/ResetPage.tsx @@ -1,8 +1,10 @@ +import { Typography, Box, Drawer, Stack } from '@mui/material'; import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { Typography, Box, Drawer, Stack } from '@mui/material'; + import { LLPrimaryButton, LLSecondaryButton, LLWarningButton } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; + import ResetModal from '../../../FRWComponent/PopupModal/resetModal'; import StepBox from '../stepBox'; diff --git a/src/ui/views/Forgot/Reset/index.tsx b/src/ui/views/Forgot/Reset/index.tsx index c769daa7..6c179e23 100644 --- a/src/ui/views/Forgot/Reset/index.tsx +++ b/src/ui/views/Forgot/Reset/index.tsx @@ -1,16 +1,17 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton, Snackbar, Alert } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { storage } from 'background/webapi'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import ResetPage from './ResetPage'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../../Register/RegisterHeader'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; +import RegisterHeader from '../../Register/RegisterHeader'; + +import ResetPage from './ResetPage'; enum Direction { Right, @@ -21,20 +22,10 @@ const Reset = () => { const history = useHistory(); const wallet = useWallet(); const [activeIndex, onChange] = useState(0); - const [mnemonic, setMnemonic] = useState(''); - const [pk, setPk] = useState(null); - const [username, setUsername] = useState(''); - const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); + const [errMessage] = useState(chrome.i18n.getMessage('No__backup__found')); const [showError, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); - const [password, setPassword] = useState(null); - const [accounts, setAccounts] = useState([]); - const [isImport, setImport] = useState(false); - - const getUsername = (username: string) => { - setUsername(username.toLowerCase()); - }; + const [, setPassword] = useState(null); const loadTempPassword = async () => { const temp = await storage.get('tempPassword'); @@ -43,7 +34,7 @@ const Reset = () => { } }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -55,7 +46,7 @@ const Reset = () => { .catch(() => { return; }); - }; + }, [history, wallet]); const goNext = () => { setDirection(Direction.Right); if (activeIndex < 5) { @@ -64,18 +55,6 @@ const Reset = () => { window.close(); } }; - const goPassword = () => { - setDirection(Direction.Right); - onChange(3); - }; - const goGoogle = () => { - setDirection(Direction.Right); - onChange(4); - }; - const goEnd = () => { - setDirection(Direction.Right); - onChange(5); - }; const goBack = () => { setDirection(Direction.Left); @@ -117,10 +96,10 @@ const Reset = () => { useEffect(() => { loadView(); - }, []); + }, [loadView]); return ( - + <> {
- + {page(activeIndex)} - + @@ -198,7 +161,7 @@ const Reset = () => { -
+ ); }; diff --git a/src/ui/views/Forgot/index.tsx b/src/ui/views/Forgot/index.tsx index 1073fd28..ac8c01c2 100644 --- a/src/ui/views/Forgot/index.tsx +++ b/src/ui/views/Forgot/index.tsx @@ -1,20 +1,19 @@ +import { Typography, Button, CardMedia } from '@mui/material'; +import { Box } from '@mui/system'; import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Typography, Button, CssBaseline, CardMedia } from '@mui/material'; -import theme from '../../style/LLTheme'; -import RegisterHeader from '../Register/RegisterHeader'; +import { Link } from 'react-router-dom'; + +import IconFlow from '../../../components/iconfont/IconFlow'; import appicon from '../../FRWAssets/image/appicon.png'; import create from '../../FRWAssets/svg/create.svg'; import importPng from '../../FRWAssets/svg/import.svg'; import recover from '../../FRWAssets/svg/recover.svg'; import reset from '../../FRWAssets/svg/resetarrow.svg'; -import { Link } from 'react-router-dom'; -import IconFlow from '../../../components/iconfont/IconFlow'; +import RegisterHeader from '../Register/RegisterHeader'; const Forgot = () => { return ( - - + <> { - + ); }; diff --git a/src/ui/views/Forgot/stepBox.tsx b/src/ui/views/Forgot/stepBox.tsx index 8396ca75..22f3e5fd 100644 --- a/src/ui/views/Forgot/stepBox.tsx +++ b/src/ui/views/Forgot/stepBox.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Box, Dialog, @@ -10,6 +9,7 @@ import { Select, Typography, } from '@mui/material'; +import React from 'react'; const stepBox = () => { return ( diff --git a/src/ui/views/Import/GoogleImport/DecryptWallet.tsx b/src/ui/views/Import/GoogleImport/DecryptWallet.tsx index 85d3d3cb..53660340 100644 --- a/src/ui/views/Import/GoogleImport/DecryptWallet.tsx +++ b/src/ui/views/Import/GoogleImport/DecryptWallet.tsx @@ -1,22 +1,15 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { - Button, - Typography, - IconButton, - Input, - InputAdornment, - FormGroup, - CssBaseline, -} from '@mui/material'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; -import theme from '../../../style/LLTheme'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import { Button, Typography, IconButton, Input, InputAdornment, FormGroup } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet } from 'ui/utils'; +import CancelIcon from '../../../../components/iconfont/IconClose'; + // const helperTextStyles = makeStyles(() => ({ // root: { // size: '16px', @@ -124,8 +117,7 @@ const DecryptWallet = ({ handleClick, setMnemonic, username, setNextPassword }) }, [password]); return ( - - + <> {chrome.i18n.getMessage('Welcome__Back')} @@ -169,7 +161,9 @@ const DecryptWallet = ({ handleClick, setMnemonic, username, setNextPassword }) } /> - {password && helperText} + + {helperText} + @@ -193,7 +187,7 @@ const DecryptWallet = ({ handleClick, setMnemonic, username, setNextPassword }) - + ); }; diff --git a/src/ui/views/Import/GoogleImport/GoogleAccounts.tsx b/src/ui/views/Import/GoogleImport/GoogleAccounts.tsx index 76cc4e6f..ae3c991f 100644 --- a/src/ui/views/Import/GoogleImport/GoogleAccounts.tsx +++ b/src/ui/views/Import/GoogleImport/GoogleAccounts.tsx @@ -1,5 +1,4 @@ -import React, { useState, useEffect } from 'react'; -import { ThemeProvider } from '@mui/system'; +import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded'; import { Typography, Avatar, @@ -10,10 +9,9 @@ import { ListItemText, IconButton, ListItem, - CssBaseline, } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import ArrowForwardRoundedIcon from '@mui/icons-material/ArrowForwardRounded'; +import React, { useState, useEffect, useCallback } from 'react'; + import { useWallet } from 'ui/utils'; const FetchAvatar = ({ username }) => { @@ -22,17 +20,20 @@ const FetchAvatar = ({ username }) => { ); const wallet = useWallet(); - const fetchUserAvatar = async (username) => { - const { data } = await wallet.openapi.searchUser(username); - const users = data.users; - if (users.length > 0 && users[0].avatar) { - setAvatar(users[0].avatar); - } - }; + const fetchUserAvatar = useCallback( + async (username) => { + const { data } = await wallet.openapi.searchUser(username); + const users = data.users; + if (users.length > 0 && users[0].avatar) { + setAvatar(users[0].avatar); + } + }, + [wallet] + ); useEffect(() => { fetchUserAvatar(username); - }, []); + }, [fetchUserAvatar, username]); return ; }; @@ -41,8 +42,7 @@ const GoogleAccounts = ({ handleClick, accounts, setUsername }) => { const [canGoNext, setCanGoNext] = useState(true); return ( - - + <> {chrome.i18n.getMessage('We__ve__found') + ' '} @@ -104,7 +104,7 @@ const GoogleAccounts = ({ handleClick, accounts, setUsername }) => { - + ); }; diff --git a/src/ui/views/Import/GoogleImport/RecoverPassword.tsx b/src/ui/views/Import/GoogleImport/RecoverPassword.tsx index 9beb9f08..c935ee3c 100644 --- a/src/ui/views/Import/GoogleImport/RecoverPassword.tsx +++ b/src/ui/views/Import/GoogleImport/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,22 +10,21 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; - -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../../style/LLTheme'; + +import { LLSpinner, LLNotFound } from '@/ui/FRWComponent'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet, saveIndex } from 'ui/utils'; -import { LLNotFound } from 'ui/FRWComponent'; -import { storage } from '@/background/webapi'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../../components/iconfont/IconClose'; +import theme from '../../../style/LLTheme'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -254,11 +252,10 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { setPassword(''); setConfirmPassword(''); } - }, [isCheck]); + }, [isCheck, lastPassword]); return ( - - + <> {!showDialog ? ( @@ -306,7 +303,9 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + @@ -384,7 +383,7 @@ const SetPassword = ({ handleClick, mnemonic, username, lastPassword }) => { {errorMessage} - + ); }; diff --git a/src/ui/views/Import/GoogleImport/RecoveryPhrase.tsx b/src/ui/views/Import/GoogleImport/RecoveryPhrase.tsx index c9e2a32f..55ec2c12 100644 --- a/src/ui/views/Import/GoogleImport/RecoveryPhrase.tsx +++ b/src/ui/views/Import/GoogleImport/RecoveryPhrase.tsx @@ -1,20 +1,20 @@ -import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, IconButton, CssBaseline } from '@mui/material'; -import theme from '../../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import InfoIcon from '@mui/icons-material/Info'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography, IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import IconCopy from '../../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; -import InfoIcon from '@mui/icons-material/Info'; const RecoveryPhrase = ({ handleClick, mnemonic }) => { const [canGoNext, setCanGoNext] = useState(true); const [isCoverBlur, coverBlur] = useState(false); return ( - - + <> {chrome.i18n.getMessage('Review') + ' '} @@ -191,7 +191,7 @@ const RecoveryPhrase = ({ handleClick, mnemonic }) => { marginBottom: '8px', }} > - + { )} - + - + ); }; diff --git a/src/ui/views/Import/GoogleImport/index.tsx b/src/ui/views/Import/GoogleImport/index.tsx index c06add63..7cd96471 100644 --- a/src/ui/views/Import/GoogleImport/index.tsx +++ b/src/ui/views/Import/GoogleImport/index.tsx @@ -1,19 +1,21 @@ -import React, { useEffect, useState } from 'react'; -import { useHistory, useLocation } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; import { IconButton, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; + +import { LLPinAlert } from '@/ui/FRWComponent'; +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import BackButtonIcon from '../../../../components/iconfont/IconBackButton'; -import theme from '../../../style/LLTheme'; -import RegisterHeader from '../../Register/RegisterHeader'; import AllSet from '../../Register/AllSet'; +import RegisterHeader from '../../Register/RegisterHeader'; + import DecryptWallet from './DecryptWallet'; -import RecoveryPhrase from './RecoveryPhrase'; import GoogleAccounts from './GoogleAccounts'; import RecoveryPassword from './RecoverPassword'; -import Particles from 'react-tsparticles'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { LLPinAlert } from '@/ui/FRWComponent'; -import options from '../options'; +import RecoveryPhrase from './RecoveryPhrase'; enum Direction { Right, @@ -52,16 +54,16 @@ const GoogleImport = () => { } }; - const getGoogleAccounts = async () => { + const getGoogleAccounts = useCallback(async () => { // const backupFile = await storage.get('googleBackup'); // await setBackup(backupFile); const users = location.state.accounts; setAccounts(users); - }; + }, [location.state.accounts]); useEffect(() => { getGoogleAccounts(); - }, []); + }, [getGoogleAccounts]); const page = (index) => { switch (index) { @@ -99,7 +101,7 @@ const GoogleImport = () => { const heights = [500, 500, 600, 600, 500]; return ( - + <> { alignItems: 'center', }} > - {activeIndex == 4 && ( - - )} - + {activeIndex === 4 && } + { - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/Import/ImportComponent/PrivateKey.tsx b/src/ui/views/Import/ImportComponent/PrivateKey.tsx index e3a5fab3..57c3f213 100644 --- a/src/ui/views/Import/ImportComponent/PrivateKey.tsx +++ b/src/ui/views/Import/ImportComponent/PrivateKey.tsx @@ -1,7 +1,7 @@ -import { useEffect, useState, useContext } from 'react'; -import React from 'react'; import { Typography, FormControl, Input, Box } from '@mui/material'; -import { Presets } from 'react-component-transition'; +import React from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; const PrivateKey = ({ helperText, msgBgColor, pk, setpk }) => { return ( @@ -39,20 +39,18 @@ const PrivateKey = ({ helperText, msgBgColor, pk, setpk }) => { }, }} /> - - {pk && ( - - {helperText} - - )} - + + + {helperText} + + diff --git a/src/ui/views/Import/ImportComponent/SeedPhrase.tsx b/src/ui/views/Import/ImportComponent/SeedPhrase.tsx index cfa2383e..ac2adc82 100644 --- a/src/ui/views/Import/ImportComponent/SeedPhrase.tsx +++ b/src/ui/views/Import/ImportComponent/SeedPhrase.tsx @@ -1,7 +1,7 @@ -import { useEffect, useState, useContext } from 'react'; -import React from 'react'; import { Typography, FormControl, Input, Box } from '@mui/material'; -import { Presets } from 'react-component-transition'; +import React from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; const SeedPhrase = ({ helperText, msgBgColor, mnemonic, setmnemonic }) => { return ( @@ -42,20 +42,18 @@ const SeedPhrase = ({ helperText, msgBgColor, mnemonic, setmnemonic }) => { }, }} /> - - {mnemonic && ( - - {helperText} - - )} - + + + {helperText} + + diff --git a/src/ui/views/Import/ImportPager.tsx b/src/ui/views/Import/ImportPager.tsx index 10073583..04cd73f4 100644 --- a/src/ui/views/Import/ImportPager.tsx +++ b/src/ui/views/Import/ImportPager.tsx @@ -1,19 +1,21 @@ +import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; +import { Box } from '@mui/system'; import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../components/iconfont/IconBackButton'; import IconGoogleDrive from '../../../components/iconfont/IconGoogleDrive'; -import theme from '../../style/LLTheme'; +import AllSet from '../Register/AllSet'; import RegisterHeader from '../Register/RegisterHeader'; + import ImportRecoveryPhrase from './ImportRecoveryPhrase'; -import AllSet from '../Register/AllSet'; import RecoverPassword from './RecoverPassword'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import options from './options'; enum Direction { Right, @@ -68,7 +70,7 @@ const ImportPager = () => { } setLoading(false); } catch (e) { - console.log(e); + console.error(e); setShowError(true); setErrorMessage(chrome.i18n.getMessage('Something__is__wrong')); setLoading(false); @@ -105,7 +107,7 @@ const ImportPager = () => { }; return ( - + <> { alignItems: 'center', }} > - {activeIndex == 2 && ( - - )} + {activeIndex === 2 && } - + @@ -169,25 +166,9 @@ const ImportPager = () => { - + {page(activeIndex)} - + {activeIndex === 0 && ( @@ -225,7 +206,7 @@ const ImportPager = () => { - + ); }; diff --git a/src/ui/views/Import/ImportRecoveryPhrase.tsx b/src/ui/views/Import/ImportRecoveryPhrase.tsx index 32f383c1..e1e77104 100644 --- a/src/ui/views/Import/ImportRecoveryPhrase.tsx +++ b/src/ui/views/Import/ImportRecoveryPhrase.tsx @@ -1,26 +1,18 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; +import { Typography, Tabs, Tab, CircularProgress, Button, Snackbar, Alert } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { - Typography, - Tabs, - Tab, - CircularProgress, - Button, - Snackbar, - Alert, - CssBaseline, -} from '@mui/material'; -import theme from '../../style/LLTheme'; -import { Presets } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import { Box } from '@mui/system'; import * as bip39 from 'bip39'; -import { LLNotFound, LLSpinner } from 'ui/FRWComponent'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + import { storage } from '@/background/webapi'; -import SeedPhrase from './ImportComponent/SeedPhrase'; +import { LLNotFound, LLSpinner } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; + import PrivateKey from './ImportComponent/PrivateKey'; +import SeedPhrase from './ImportComponent/SeedPhrase'; function TabPanel(props) { const { children, value, index, ...other } = props; @@ -70,6 +62,58 @@ const useStyles = makeStyles((theme) => ({ }, })); +const mnemonicError = (errorMsg) => ( + + + + {errorMsg} + + +); + +const MnemonicCorrect: React.FC = () => ( + + + + {chrome.i18n.getMessage('Recovery__phrase__valid')} + + +); + +const PrivateCorrect: React.FC = () => ( + + + + {chrome.i18n.getMessage('Private__key_valid')} + + +); + +const MnemonicLoading: React.FC = () => ( + + + {chrome.i18n.getMessage('Checking')} + +); + const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUsername }) => { const classes = useStyles(); const wallet = useWallet(); @@ -85,7 +129,7 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser const [showDialog, setShowDialog] = useState(false); const [showError, setShowError] = useState(false); - const [helperText, setHelperText] = useState(
); + const [helperText, setHelperText] = useState(
); const [selectedTab, setSelectedTab] = useState(0); const signIn = async () => { @@ -134,91 +178,22 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser } }; - const mnemonicError = (errorMsg) => ( - - - - {errorMsg} - - - ); - - const mnemonicCorrect = ( - - - - {chrome.i18n.getMessage('Recovery__phrase__valid')} - - - ); - - const privateCorrect = ( - - - - {chrome.i18n.getMessage('Private__key_valid')} - - - ); - - const mnemonicLoading = () => ( - - - {chrome.i18n.getMessage('Checking')} - + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setMnemonicValid(false); + setHelperText(mnemonicError(message)); + }, + [setLoading, setMnemonicValid, setHelperText] ); - - const renderSnackBar = () => { - return ( - setShowError(false)} - > - { - setShowError(false); - }} - > - Something went wrong, please try again later - - - ); - }; - useEffect(() => { setMnemonicValid(false); - setHelperText(mnemonicLoading); + setHelperText(); setLoading(true); const delayDebounceFn = setTimeout(() => { setLoading(false); const length = mnemonic.trim().split(/\s+/g).length; - if (!(length == 12 || length == 24)) { + if (!(length === 12 || length === 24)) { setErrorMessage( chrome.i18n.getMessage('Recovery__phrases__word__count__must__be__12__or__24__words') ); @@ -232,17 +207,17 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser } setMnemonicValid(true); - setHelperText(mnemonicCorrect); + setHelperText(); storage.set('premnemonic', formatted); setMnemonic(formatted); }, 500); return () => clearTimeout(delayDebounceFn); - }, [mnemonic]); + }, [mnemonic, setErrorMessage]); useEffect(() => { setMnemonicValid(false); - setHelperText(mnemonicLoading); + setHelperText(); setLoading(true); const delayDebounceFn = setTimeout(() => { setLoading(false); @@ -250,7 +225,7 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser const isvalid = hexRegex.test(pk); if (isvalid) { setMnemonicValid(true); - setHelperText(privateCorrect); + setHelperText(); return; } else { setErrorMessage(chrome.i18n.getMessage('Private__is__invalid')); @@ -259,13 +234,7 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser }, 500); return () => clearTimeout(delayDebounceFn); - }, [pk]); - - const setErrorMessage = (message: string) => { - setLoading(false); - setMnemonicValid(false); - setHelperText(mnemonicError(message)); - }; + }, [pk, setErrorMessage]); const msgBgColor = () => { if (isLoading) { @@ -279,8 +248,7 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser }; return ( - - + <> {!showDialog ? ( @@ -333,12 +301,27 @@ const ImportRecoveryPhrase = ({ handleClick, confirmMnemonic, confirmPk, setUser - {renderSnackBar()} + setShowError(false)} + > + { + setShowError(false); + }} + > + Something went wrong, please try again later + + ) : ( )} - + ); }; diff --git a/src/ui/views/Import/RecoverPassword.tsx b/src/ui/views/Import/RecoverPassword.tsx index 05936d56..c1764991 100644 --- a/src/ui/views/Import/RecoverPassword.tsx +++ b/src/ui/views/Import/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,18 +10,19 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; + // const helperTextStyles = makeStyles(() => ({ // root: { // size: '16px', @@ -239,8 +239,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username }) => { }, [confirmPassword, password]); return ( - - + <> {chrome.i18n.getMessage('Welcome__Back')} @@ -287,7 +286,9 @@ const SetPassword = ({ handleClick, mnemonic, pk, username }) => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + @@ -375,7 +376,7 @@ const SetPassword = ({ handleClick, mnemonic, pk, username }) => { {errorMessage} - + ); }; diff --git a/src/ui/views/Import/options.ts b/src/ui/views/Import/options.ts deleted file mode 100644 index 9f7a97b7..00000000 --- a/src/ui/views/Import/options.ts +++ /dev/null @@ -1,125 +0,0 @@ -const Options = { - fullScreen: true, - fpsLimit: 120, - detectRetina: true, - emitters: { - direction: 'bottom', - startCount: 0, - position: { x: 50, y: 0 }, - size: { - width: 20, - height: 0, - }, - rate: { - delay: 0, - quantity: 2, - }, - life: { - count: 200, - duration: 0.01, - // delay:0.6, - }, - }, - particles: { - number: { - value: 250, - }, - color: { - value: ['#9146FF', '#FFAAA8', '#8FFFD2', '#FFD37A', '#FF38DB'], - }, - shape: { - type: ['square', 'circle', 'heart'], - }, - opacity: { - value: 1, - animation: { - enable: true, - minimumValue: 0, - speed: 0.5, - startValue: 'max', - destroy: 'min', - }, - }, - size: { - value: 5, - }, - links: { - enable: false, - }, - life: { - duration: { - sync: true, - value: 10, - }, - count: 1, - }, - move: { - angle: { - value: 45, - offset: 0, - }, - drift: { - min: -0, - max: 0, - }, - enable: true, - gravity: { - enable: true, - acceleration: 20, - }, - speed: 90, - decay: 1 - 0.9, - direction: -90, - random: true, - straight: false, - outModes: { - default: 'none', - bottom: 'destroy', - }, - }, - rotate: { - value: { - min: 0, - max: 360, - }, - direction: 'random', - animation: { - enable: true, - speed: 60, - }, - }, - tilt: { - direction: 'random', - enable: true, - value: { - min: 0, - max: 360, - }, - animation: { - enable: true, - speed: 60, - }, - }, - roll: { - darken: { - enable: true, - value: 25, - }, - enable: true, - speed: { - min: 15, - max: 25, - }, - }, - wobble: { - distance: 20, - enable: true, - speed: { - min: -15, - max: 15, - }, - }, - }, -}; - -export default Options; diff --git a/src/ui/views/Inbox/Nft.tsx b/src/ui/views/Inbox/Nft.tsx index 1d1e60ae..f0555e0d 100644 --- a/src/ui/views/Inbox/Nft.tsx +++ b/src/ui/views/Inbox/Nft.tsx @@ -1,8 +1,3 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { useHistory } from 'react-router-dom'; -import theme from '../../style/LLTheme'; -import { useWallet } from 'ui/utils'; import { Typography, ListItem, @@ -14,9 +9,14 @@ import { List, CardMedia, } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; + +import fallback from 'ui/FRWAssets/image/errorImage.png'; import activity from 'ui/FRWAssets/svg/activity.svg'; import { LLPrimaryButton, LLSpinner } from 'ui/FRWComponent'; -import fallback from 'ui/FRWAssets/image/errorImage.png'; +import { useWallet } from 'ui/utils'; const Nft = ({ data }) => { const wallet = useWallet(); @@ -70,7 +70,7 @@ const Nft = ({ data }) => { }, [data]); return ( - + <> {!isLoading ? ( @@ -156,7 +156,7 @@ const Nft = ({ data }) => { alignItems: 'center', }} > - {ids == ibx ? ( + {ids === ibx ? ( { }) )} - + ); }; diff --git a/src/ui/views/Inbox/Token.tsx b/src/ui/views/Inbox/Token.tsx index bce01e4a..7fb8ed96 100644 --- a/src/ui/views/Inbox/Token.tsx +++ b/src/ui/views/Inbox/Token.tsx @@ -1,8 +1,3 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { useHistory } from 'react-router-dom'; -import theme from '../../style/LLTheme'; -import { useWallet } from 'ui/utils'; import { Typography, ListItem, @@ -14,11 +9,16 @@ import { List, CardMedia, } from '@mui/material'; -import activity from 'ui/FRWAssets/svg/activity.svg'; -import { LLPrimaryButton, LLSpinner } from 'ui/FRWComponent'; +import { Box } from '@mui/system'; import { setDefaultWordlist } from 'bip39'; import { reject } from 'lodash'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; + import { TokenModel } from 'background/service/networkModel'; +import activity from 'ui/FRWAssets/svg/activity.svg'; +import { LLPrimaryButton, LLSpinner } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; const Token = ({ data }) => { const wallet = useWallet(); @@ -61,11 +61,11 @@ const Token = ({ data }) => { }); }; - const getToken = () => { + const getToken = useCallback(() => { wallet.openapi.getAllToken().then((res) => { setTokens(res); }); - }; + }, [setTokens, wallet.openapi]); useEffect(() => { setLoading(data === null); @@ -75,10 +75,10 @@ const Token = ({ data }) => { checkEmpty(data); setLoading(false); } - }, [data]); + }, [data, getToken]); return ( - + <> {!isLoading ? ( @@ -87,7 +87,7 @@ const Token = ({ data }) => { {(Object.keys(inbox['vaultBalances']) || []).map((ibx: any, v: any) => { const contractName = ibx.split('.')[2]; const token = tokens.find( - (item) => item.contract_name.toLowerCase() == contractName.toLowerCase() + (item) => item.contract_name.toLowerCase() === contractName.toLowerCase() ); let tokenIcon = 'https://lilico.app/placeholder-2.0.png'; if (token) { @@ -270,7 +270,7 @@ const Token = ({ data }) => { }) )} - + ); }; diff --git a/src/ui/views/InnerRoute.tsx b/src/ui/views/InnerRoute.tsx index fc0c7002..9605a13d 100644 --- a/src/ui/views/InnerRoute.tsx +++ b/src/ui/views/InnerRoute.tsx @@ -1,57 +1,57 @@ -import React, { useState, useEffect } from 'react'; import { makeStyles } from '@mui/styles'; -import Settingone from './Setting/Settingone'; -import Switchaccount from './Setting/Switchaccount'; -import Security from './Setting/Security'; -import PrivateKeyPassword from './Setting/privatekey/Privatekeypassword'; -import Recoveryphrasepassword from './Setting/recoveryphase/Recoveryphrasepassword'; -import KeyList from './Setting/KeyList/KeyList'; -import Keydetail from './Setting/privatekey/Keydetail'; -import RecoveryPhasesDetail from './Setting/recoveryphase/Recoveryphasedetail'; -import Resetpwd from './Setting/Resetpwd'; -import './MainRoute.css'; -import { withRouter } from 'react-router-dom'; -import Header from './Dashboard/Header'; -import Dashboard from './Dashboard'; -import CollectionDetail from './NFT/CollectionDetail'; -import EvmCollectionDetail from './NftEvm/CollectionDetail'; -import Detail from './NFT/Detail'; -import NftEvmDetail from './NftEvm/Detail'; +import React, { useState, useEffect, useCallback } from 'react'; +import { Switch, withRouter, type RouteComponentProps } from 'react-router-dom'; + import { PrivateRoute } from 'ui/component'; import { useWallet } from 'ui/utils'; + +import Deposit from '../views/Deposit'; import Enable from '../views/Enable'; import Send from '../views/Send'; import Swap from '../views/Swap'; -import Deposit from '../views/Deposit'; -import AddressBook from './Setting/AddressBook'; -import SendAmount from './Send/SendAmount'; -import SendEth from './Send/SendEth'; -import TokenDetail from './TokenDetail'; -import TokenList from './TokenList'; -import AddCustomEvmToken from './Wallet/AddCustom/AddCustomEvmToken'; -import Inbox from './Inbox'; -import StakingPage from './Staking/StakingPage'; -import UnstakePage from './Staking/UnstakePage'; -import NodeDetail from './Staking/NodeDetail'; + +import Dashboard from './Dashboard'; +import Header from './Dashboard/Header'; import Flowns from './Flowns'; +import Inbox from './Inbox'; +import CollectionDetail from './NFT/CollectionDetail'; +import Detail from './NFT/Detail'; import AddList from './NFT/NFTList/AddList'; +import SendToAddress from './NFT/SendNFT/SendToAddress'; +import EvmCollectionDetail from './NftEvm/CollectionDetail'; +import NftEvmDetail from './NftEvm/Detail'; +import SendNftEvm from './NftEvm/SendNFT/SendToAddress'; +import SendAmount from './Send/SendAmount'; +import SendEth from './Send/SendEth'; import About from './Setting/About/About'; -import Linked from './Setting/Linked'; -import LinkedDetail from './Setting/Linked/LinkedDetail'; -import LinkedCollection from './Setting/Linked/LinkedCollection'; -import LinkedNftDetail from './Setting/Linked/LinkedNftDetail'; import Account from './Setting/Account'; +import AddressBook from './Setting/AddressBook'; +import ManageBackups from './Setting/Backups'; import DeveloperMode from './Setting/DeveloperMode/DeveloperMode'; -import Devices from './Setting/Devices/Devices'; import DeviceInfo from './Setting/Devices/DeviceInfo'; +import KeyList from './Setting/KeyList/KeyList'; +import Linked from './Setting/Linked'; +import LinkedCollection from './Setting/Linked/LinkedCollection'; +import LinkedDetail from './Setting/Linked/LinkedDetail'; +import LinkedNftDetail from './Setting/Linked/LinkedNftDetail'; +import Keydetail from './Setting/privatekey/Keydetail'; +import PrivateKeyPassword from './Setting/privatekey/Privatekeypassword'; +import RecoveryPhasesDetail from './Setting/recoveryphase/Recoveryphasedetail'; +import Recoveryphrasepassword from './Setting/recoveryphase/Recoveryphrasepassword'; +import Resetpwd from './Setting/Resetpwd'; +import Security from './Setting/Security'; +import Settingone from './Setting/Settingone'; +import Switchaccount from './Setting/Switchaccount'; +import './MainRoute.css'; import WalletList from './Setting/Wallet'; -import WalletDetail from './Setting/Wallet/WalletDetail'; import RemoveWallet from './Setting/Wallet/RemoveWallet'; -import ManageBackups from './Setting/Backups'; -import SendToAddress from './NFT/SendNFT/SendToAddress'; -import SendNftEvm from './NftEvm/SendNFT/SendToAddress'; -import { spring, AnimatedSwitch } from 'react-router-transition'; -// import OnRampList from './Wallet/OnRampList'; +import WalletDetail from './Setting/Wallet/WalletDetail'; +import NodeDetail from './Staking/NodeDetail'; +import StakingPage from './Staking/StakingPage'; +import UnstakePage from './Staking/UnstakePage'; +import TokenDetail from './TokenDetail'; +import TokenList from './TokenList'; +import AddCustomEvmToken from './Wallet/AddCustom/AddCustomEvmToken'; const useStyles = makeStyles(() => ({ innerWrapper: { @@ -67,45 +67,13 @@ const useStyles = makeStyles(() => ({ }, })); -function zoom(val) { - return spring(val, { - stiffness: 174, - damping: 24, - }); -} - -const switchConfig = { - atEnter: { - opacity: 0, - offset: 50, - }, - atLeave: { - opacity: 0, - offset: zoom(-50), - }, - atActive: { - opacity: 1, - offset: zoom(0), - }, -}; - -function mapStyles(styles) { - return { - opacity: styles.opacity, - transform: `translateX(${styles.offset}px)`, - }; -} - -const Inner = (props) => { +const InnerRoute = (props: RouteComponentProps) => { const classes = useStyles(); - // const location = useLocation(); - // const history = useHistory(); - const [loading, setLoading] = useState(false); const [value, setValue] = useState(0); const wallet = useWallet(); - const fetch = async () => { + const fetch = useCallback(async () => { const dashIndex = await wallet.getDashIndex(); if (dashIndex) { setValue(dashIndex); @@ -113,216 +81,167 @@ const Inner = (props) => { setValue(0); await wallet.setDashIndex(0); } - }; + }, [wallet]); useEffect(() => { fetch(); - }, []); + }, [fetch]); useEffect(() => { wallet.setDashIndex(value); - }, [value]); + }, [value, wallet]); return (
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* - - */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* ======= - - - - - */} - +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
); }; -export default withRouter(Inner); +export default withRouter(InnerRoute); diff --git a/src/ui/views/MainRoute.tsx b/src/ui/views/MainRoute.tsx index 9fc576e8..61cf72d4 100644 --- a/src/ui/views/MainRoute.tsx +++ b/src/ui/views/MainRoute.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { Switch, Route } from 'react-router-dom'; -import { spring, AnimatedSwitch } from 'react-router-transition'; import AddressImport from './AddressImport'; import GoogleImport from './AddressImport/GoogleImport'; @@ -24,74 +23,29 @@ const LogPageView = () => { return null; }; -function mapStyles(styles) { - return { - opacity: styles.opacity, - transform: `scale(${styles.scale})`, - }; -} - -// wrap the `spring` helper to use a bouncy config -function bounce(val) { - return spring(val, { - stiffness: 33, - damping: 22, - }); -} - -// child matches will... -const bounceTransition = { - // start in a transparent, upscaled state - atEnter: { - opacity: 0.5, - // offset: 10, - scale: 1.05, - }, - // leave in a transparent, downscaled state - atLeave: { - opacity: bounce(0.5), - // offset: 10, - scale: bounce(0.95), - }, - // and rest at an opaque, normally-scaled state - atActive: { - opacity: 1, - // offset: 0, - scale: bounce(1), - }, -}; - export const MainRoute: React.FC = () => { return (
- - - - - - - - - {/* */} - - - - - - - - - - - - + + + + + + + + {/* */} + + + + + + + + + + +
); }; diff --git a/src/ui/views/MoveBoard/AccountBox.tsx b/src/ui/views/MoveBoard/AccountBox.tsx index a2023958..005856d5 100644 --- a/src/ui/views/MoveBoard/AccountBox.tsx +++ b/src/ui/views/MoveBoard/AccountBox.tsx @@ -1,33 +1,34 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles } from '@mui/styles'; -import { useWallet, formatAddress } from 'ui/utils'; -import { ensureEvmAddressPrefix, formatString } from 'ui/utils/address'; import { Typography, Box, CardMedia } from '@mui/material'; -import { FRWProfileCard, FWMoveDropdown } from 'ui/FRWComponent'; -import accountMove from 'ui/FRWAssets/svg/accountMove.svg'; -import emoji from 'background/utils/emoji.json'; +import { makeStyles } from '@mui/styles'; +import React, { useCallback, useEffect, useState } from 'react'; + import { storage } from '@/background/webapi'; +import { ensureEvmAddressPrefix, formatString } from '@/shared/utils/address'; +import emoji from 'background/utils/emoji.json'; +import accountMove from 'ui/FRWAssets/svg/accountMove.svg'; +import { FRWProfileCard, FWMoveDropdown } from 'ui/FRWComponent'; +import { useWallet, formatAddress } from 'ui/utils'; + +const USER_CONTACT = { + contact_name: '', + avatar: '', +}; function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = false }) { const usewallet = useWallet(); - const userContact = { - contact_name: '', - avatar: '', - }; const [first, setFirst] = useState(''); const [second, setSecond] = useState(''); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [firstEmoji, setFirstEmoji] = useState(null); - const [secondEmoji, setSecondEmoji] = useState(null); const [childWallets, setChildWallets] = useState({}); - const requestAddress = async () => { + const requestAddress = useCallback(async () => { const parentAddress = await usewallet.getMainAddress(); const address = await usewallet.getCurrentAddress(); const childResp = await usewallet.checkUserChildAccount(); - const emojires = await usewallet.getEmoji(); const eWallet = await usewallet.getEvmWallet(); + const currentWallet = await usewallet.getCurrentWallet(); let evmAddress; if (eWallet.address) { evmAddress = ensureEvmAddressPrefix(eWallet.address); @@ -35,10 +36,10 @@ function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = const newWallet = { [parentAddress!]: { - name: emojires[0].name, - description: emojires[0].name, + name: currentWallet.name, + description: currentWallet.name, thumbnail: { - url: emojires[0].emoji, + url: currentWallet.icon, }, }, }; @@ -49,25 +50,27 @@ function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = const wallet = walletList[firstWalletAddress]; setChildWallets(walletList); - userContact.avatar = wallet.thumbnail.url; - userContact.contact_name = wallet.name; + const userContact = { + avatar: wallet.thumbnail.url, + contact_name: wallet.name, + }; if (firstWalletAddress) { setSelectedChildAccount(walletList[firstWalletAddress]); } + console.log('wallet is here ', eWallet); setUser(userContact); if (isEvm) { setFirst(evmAddress!); - setFirstEmoji(emojires[1]); + setFirstEmoji(eWallet); } else { setFirst(address!); } setSecond(parentAddress!); - setSecondEmoji(emojires[0]); - }; + }, [isEvm, usewallet, setSelectedChildAccount]); useEffect(() => { requestAddress(); - }, []); + }, [requestAddress]); return ( @@ -92,13 +95,13 @@ function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = borderRadius: '32px', justifyContent: 'center', alignItems: 'center', - backgroundColor: firstEmoji ? firstEmoji['bgcolor'] : 'none', + backgroundColor: firstEmoji ? firstEmoji['color'] : 'none', marginRight: '4px', }} > {firstEmoji ? ( - {firstEmoji.emoji} + {firstEmoji.icon} ) : ( (''); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [firstEmoji, setFirstEmoji] = useState(null); const [childWallets, setChildWallets] = useState({}); - const requestAddress = async () => { + const requestAddress = useCallback(async () => { const parentAddress = await usewallet.getMainAddress(); const address = await usewallet.getCurrentAddress(); const childResp = await usewallet.checkUserChildAccount(); - const emojires = await usewallet.getEmoji(); const eWallet = await usewallet.getEvmWallet(); + const currentWallet = await usewallet.getCurrentWallet(); let evmAddress; if (eWallet.address) { evmAddress = ensureEvmAddressPrefix(eWallet.address); @@ -34,10 +36,10 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE if (isChild) { const newWallet = { [parentAddress!]: { - name: emojires[0].name, - description: emojires[0].name, + name: currentWallet.name, + description: currentWallet.name, thumbnail: { - url: emojires[0].emoji, + url: currentWallet.icon, }, }, }; @@ -46,10 +48,10 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE if (evmAddress) { evmWallet = { [evmAddress!]: { - name: emojires[1].name, - description: emojires[1].name, + name: eWallet.name, + description: eWallet.name, thumbnail: { - url: emojires[1].emoji, + url: eWallet.icon, }, }, }; @@ -62,8 +64,10 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE const wallet = childResp[address!]; setChildWallets(walletList); - userContact.avatar = wallet.thumbnail.url; - userContact.contact_name = wallet.name; + const userContact = { + avatar: wallet.thumbnail.url, + contact_name: wallet.name, + }; if (firstWalletAddress) { setSelectedChildAccount(walletList[firstWalletAddress]); } @@ -74,10 +78,10 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE if (evmAddress) { evmWallet = { [evmAddress!]: { - name: emojires[1].name, - description: emojires[1].name, + name: eWallet.name, + description: eWallet.name, thumbnail: { - url: emojires[1].emoji, + url: eWallet.icon, }, }, }; @@ -89,13 +93,13 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE setSelectedChildAccount(walletList[firstWalletAddress]); } setFirst(parentAddress!); - setFirstEmoji(emojires[0]); + setFirstEmoji(currentWallet); } - }; + }, [usewallet, isChild, setSelectedChildAccount]); useEffect(() => { requestAddress(); - }, []); + }, [requestAddress]); return ( @@ -125,8 +129,8 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE }} > {firstEmoji ? ( - - {firstEmoji.emoji} + + {firstEmoji.icon} ) : ( { setShowError(false); }; - const updateCurrentCollection = async () => { + const updateCurrentCollection = useCallback(async () => { if (collectionList && cadenceNft) { const collection = collectionList.find((collection) => collection.id === selectedCollection); @@ -61,9 +61,9 @@ const MoveEvm = (props: MoveBoardProps) => { setCollectionDetail(collection); setCollectionInfo(cadenceResult); } - }; + }, [collectionList, cadenceNft, selectedCollection, usewallet]); - const requestCadenceNft = async () => { + const requestCadenceNft = useCallback(async () => { const cadenceResult = await usewallet.reqeustEvmNft(); const tokensWithNfts = cadenceResult.filter((token) => token.ids && token.ids.length > 0); const filteredData = tokensWithNfts.filter((item) => item.collection.flowIdentifier); @@ -86,7 +86,7 @@ const MoveEvm = (props: MoveBoardProps) => { setCollectionInfo({ nfts: [] }); } setLoading(false); - }; + }, [usewallet]); const toggleSelectNft = async (nftId) => { const tempIdArray = [...nftIdArray]; @@ -175,11 +175,11 @@ const MoveEvm = (props: MoveBoardProps) => { useEffect(() => { requestCadenceNft(); - }, []); + }, [requestCadenceNft]); useEffect(() => { updateCurrentCollection(); - }, [collectionList, cadenceNft, selectedCollection]); + }, [collectionList, cadenceNft, selectedCollection, updateCurrentCollection]); return ( { isLowStorage={isLowStorage} isLowStorageAfterAction={isLowStorageAfterAction} /> - + + ) : ( + <> + {failed ? ( + + {chrome.i18n.getMessage('Transaction__failed')} + + ) : ( + + {chrome.i18n.getMessage('Move')} {nftIdArray.length > 0 && nftIdArray.length} NFT + {nftIdArray.length > 1 && 's'} + + )} + + )} + + {selectCollection && ( void; } +// Utility functions +const extractContractAddress = (collection) => { + return collection.split('.')[2]; +}; + +const checkContractAddressInCollections = (nft, activec) => { + const contractAddressWithout0x = nft.collection.contract_name; + const isActiveCollect = activec.some((collection) => { + const extractedAddress = extractContractAddress(collection); + return extractedAddress === contractAddressWithout0x; + }); + return isActiveCollect; +}; + const MoveFromChild = (props: MoveBoardProps) => { const usewallet = useWallet(); const history = useHistory(); const [isLoading, setIsLoading] = useState(true); - const [cadenceNft, setCadenceNft] = useState(null); const [collectionList, setCollectionList] = useState(null); const [selectedCollection, setSelected] = useState(''); const [collectionDetail, setCollectionDetail] = useState(null); @@ -37,7 +50,6 @@ const MoveFromChild = (props: MoveBoardProps) => { const [failed, setFailed] = useState(false); const [errorOpen, setShowError] = useState(false); const [selectCollection, setSelectCollection] = useState(false); - const [activeCollection, setActiveCollection] = useState([]); const [selectedAccount, setSelectedChildAccount] = useState(null); const [currentCollection, setCurrentCollection] = useState({ CollectionName: '', @@ -64,41 +76,47 @@ const MoveFromChild = (props: MoveBoardProps) => { setShowError(false); }; - const findCollectionByContractName = () => { + const findCollectionByContractName = useCallback(() => { if (collectionList) { const collection = collectionList.find((collection) => collection.id === selectedCollection); setCurrentCollection(collection); } - }; + }, [collectionList, selectedCollection]); - const fetchCollectionCache = async (address: string) => { - try { - const list = await usewallet.getCollectionCache(); - if (list && list.length > 0) { - return list; - } else { - const list = await fetchLatestCollection(address); - return list; + const fetchLatestCollection = useCallback( + async (address: string) => { + try { + const list = await usewallet.refreshCollection(address); + if (list && list.length > 0) { + return list; + } + } catch (err) { + console.log(err); } - } catch { - fetchLatestCollection(address); - } finally { - console.log('done'); - } - }; + }, + [usewallet] + ); - const fetchLatestCollection = async (address: string) => { - try { - const list = await usewallet.refreshCollection(address); - if (list && list.length > 0) { - return list; + const fetchCollectionCache = useCallback( + async (address: string) => { + try { + const list = await usewallet.getCollectionCache(); + if (list && list.length > 0) { + return list; + } else { + const list = await fetchLatestCollection(address); + return list; + } + } catch { + fetchLatestCollection(address); + } finally { + console.log('done'); } - } catch (err) { - console.log(err); - } - }; + }, + [fetchLatestCollection, usewallet] + ); - const requestCadenceNft = async () => { + const requestCadenceNft = useCallback(async () => { setIsLoading(true); try { const address = await usewallet.getCurrentAddress(); @@ -111,7 +129,6 @@ const MoveFromChild = (props: MoveBoardProps) => { ); setSelected(filteredCadenceResult![0].collection.id); - setActiveCollection(activec); const extractedObjects = filteredCadenceResult!.map((obj) => { return { @@ -124,17 +141,15 @@ const MoveFromChild = (props: MoveBoardProps) => { }); setCollectionList(extractedObjects); - setCadenceNft(filteredCadenceResult); } catch (error) { console.error('Error fetching NFT data:', error); setSelected(''); setCollectionList(null); - setCadenceNft(null); setIsLoading(false); } - }; + }, [fetchCollectionCache, usewallet]); - const requestCollectionInfo = async () => { + const requestCollectionInfo = useCallback(async () => { if (selectedCollection) { try { const address = await usewallet.getCurrentAddress(); @@ -147,7 +162,7 @@ const MoveFromChild = (props: MoveBoardProps) => { setIsLoading(false); } } - }; + }, [selectedCollection, usewallet]); const toggleSelectNft = async (nftId) => { const tempIdArray = [...nftIdArray]; @@ -267,33 +282,20 @@ const MoveFromChild = (props: MoveBoardProps) => { }); }; - const extractContractAddress = (collection) => { - return collection.split('.')[2]; - }; - - const checkContractAddressInCollections = (nft, activec) => { - const contractAddressWithout0x = nft.collection.contract_name; - const isActiveCollect = activec.some((collection) => { - const extractedAddress = extractContractAddress(collection); - return extractedAddress === contractAddressWithout0x; - }); - return isActiveCollect; - }; - useEffect(() => { setIsLoading(true); requestCadenceNft(); - }, []); + }, [requestCadenceNft]); useEffect(() => { setIsLoading(true); requestCollectionInfo(); - }, [selectedCollection]); + }, [selectedCollection, requestCollectionInfo]); useEffect(() => { setIsLoading(true); findCollectionByContractName(); - }, [collectionList, selectedCollection]); + }, [collectionList, selectedCollection, findCollectionByContractName]); const replaceIPFS = (url: string | null): string => { if (!url) { @@ -570,47 +572,49 @@ const MoveFromChild = (props: MoveBoardProps) => { isLowStorage={isLowStorage} isLowStorageAfterAction={isLowStorageAfterAction} /> - + + ) : ( + <> + {failed ? ( + + {chrome.i18n.getMessage('Transaction__failed')} + + ) : ( + + {chrome.i18n.getMessage('Move')} {nftIdArray.length > 0 && nftIdArray.length} NFT + {nftIdArray.length > 1 && 's'} + + )} + + )} + + {selectCollection && ( { setShowError(false); }; - const findCollectionByContractName = () => { + const findCollectionByContractName = useCallback(() => { if (collectionList) { const collection = collectionList.find((collection) => collection.id === selectedCollection); console.log('setCurrentCollection ', collection); setCurrentCollection(collection); } - }; + }, [collectionList, selectedCollection]); - const fetchCollectionCache = async (address: string) => { - try { - const list = await usewallet.getCollectionCache(); - if (list && list.length > 0) { - return list; - } else { - const list = await fetchLatestCollection(address); - return list; + const fetchLatestCollection = useCallback( + async (address: string) => { + try { + const list = await usewallet.refreshCollection(address); + if (list && list.length > 0) { + return list; + } + } catch (err) { + console.log(err); } - } catch { - fetchLatestCollection(address); - } finally { - console.log('done'); - } - }; + }, + [usewallet] + ); - const fetchLatestCollection = async (address: string) => { - try { - const list = await usewallet.refreshCollection(address); - if (list && list.length > 0) { - return list; + const fetchCollectionCache = useCallback( + async (address: string) => { + try { + const list = await usewallet.getCollectionCache(); + if (list && list.length > 0) { + return list; + } else { + const list = await fetchLatestCollection(address); + return list; + } + } catch { + fetchLatestCollection(address); + } finally { + console.log('done'); } - } catch (err) { - console.log(err); - } - }; + }, + [fetchLatestCollection, usewallet] + ); - const requestCadenceNft = async () => { + const requestCadenceNft = useCallback(async () => { setIsLoading(true); try { const address = await usewallet.getCurrentAddress(); @@ -125,9 +131,9 @@ const MoveToChild = (props: MoveBoardProps) => { setCadenceNft(null); setIsLoading(false); } - }; + }, [fetchCollectionCache, usewallet]); - const requestCollectionInfo = async () => { + const requestCollectionInfo = useCallback(async () => { if (selectedCollection) { try { const address = await usewallet.getCurrentAddress(); @@ -141,7 +147,7 @@ const MoveToChild = (props: MoveBoardProps) => { setIsLoading(false); } } - }; + }, [selectedCollection, usewallet]); const toggleSelectNft = async (nftId) => { const tempIdArray = [...nftIdArray]; @@ -222,17 +228,17 @@ const MoveToChild = (props: MoveBoardProps) => { useEffect(() => { setIsLoading(true); requestCadenceNft(); - }, []); + }, [requestCadenceNft]); useEffect(() => { setIsLoading(true); requestCollectionInfo(); - }, [selectedCollection]); + }, [requestCollectionInfo, selectedCollection]); useEffect(() => { setIsLoading(true); findCollectionByContractName(); - }, [collectionList, selectedCollection]); + }, [collectionList, findCollectionByContractName, selectedCollection]); const replaceIPFS = (url: string | null): string => { if (!url) { @@ -508,48 +514,49 @@ const MoveToChild = (props: MoveBoardProps) => { isLowStorage={isLowStorage} isLowStorageAfterAction={isLowStorageAfterAction} /> - - + + ) : ( + <> + {failed ? ( + + {chrome.i18n.getMessage('Transaction__failed')} + + ) : ( + + {chrome.i18n.getMessage('Move')} {nftIdArray.length > 0 && nftIdArray.length} NFT + {nftIdArray.length > 1 && 's'} + + )} + + )} + + {selectCollection && ( ({ diff --git a/src/ui/views/NFT/NFTList/AddNFTCard.tsx b/src/ui/views/NFT/NFTList/AddNFTCard.tsx index 4098cc5f..995382b0 100644 --- a/src/ui/views/NFT/NFTList/AddNFTCard.tsx +++ b/src/ui/views/NFT/NFTList/AddNFTCard.tsx @@ -1,4 +1,6 @@ -import React from 'react'; +import AddIcon from '@mui/icons-material/Add'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; +import DoneIcon from '@mui/icons-material/Done'; import { Typography, Box, @@ -8,11 +10,11 @@ import { IconButton, CircularProgress, } from '@mui/material'; -import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; -import AddIcon from '@mui/icons-material/Add'; -import DoneIcon from '@mui/icons-material/Done'; +import React from 'react'; + import IconFlow from '../../../../components/iconfont/IconFlow'; -import { CollectionItem } from './AddList'; + +import { type CollectionItem } from './AddList'; const CollectionCard = ({ item, diff --git a/src/ui/views/NFT/NFTList/AddNFTConfirmation.tsx b/src/ui/views/NFT/NFTList/AddNFTConfirmation.tsx index 504a7ea7..e32ab361 100644 --- a/src/ui/views/NFT/NFTList/AddNFTConfirmation.tsx +++ b/src/ui/views/NFT/NFTList/AddNFTConfirmation.tsx @@ -1,10 +1,11 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router-dom'; -import { Box, Typography, Drawer, Grid, Button, IconButton } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; +import { Box, Typography, Drawer, Grid, Button, IconButton } from '@mui/material'; +import React, { useState } from 'react'; +import { useHistory } from 'react-router-dom'; + +import { type NFTModel } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { NFTModel } from 'background/service/networkModel'; interface AddNFTConfirmationProps { isConfirmationOpen: boolean; @@ -18,7 +19,7 @@ const AddNFTConfirmation = (props: AddNFTConfirmationProps) => { const wallet = useWallet(); const history = useHistory(); const [sending, setSending] = useState(false); - const [tid, setTid] = useState(''); + const [, setTid] = useState(''); const enableStorage = async () => { // TODO: Replace it with real data @@ -43,15 +44,11 @@ const AddNFTConfirmation = (props: AddNFTConfirmationProps) => { } props.handleAddBtnClicked(); } catch (err) { - console.log('err ->', err); + console.error('err ->', err); setSending(false); } }; - useEffect(() => { - console.log(props, props.data); - }, []); - const renderContent = () => ( { size="large" sx={{ height: '50px', + width: '100%', borderRadius: '12px', textTransform: 'capitalize', display: 'flex', diff --git a/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx b/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx index f8fba31e..cea1b70e 100644 --- a/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx +++ b/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx @@ -2,16 +2,16 @@ import CloseIcon from '@mui/icons-material/Close'; import InfoIcon from '@mui/icons-material/Info'; import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; -import { Presets } from 'react-component-transition'; import { useHistory } from 'react-router-dom'; +import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { MatchMediaType } from '@/ui/utils/url'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import { LLSpinner, FRWChildProfile, FRWDropdownProfileCard } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { ensureEvmAddressPrefix, isValidEthereumAddress } from 'ui/utils/address'; import IconFlow from '../../../../components/iconfont/IconFlow'; @@ -176,8 +176,8 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { const getChildResp = useCallback(async () => { const childresp = await usewallet.checkUserChildAccount(); const parentAddress = await usewallet.getMainAddress(); - const emojires = await usewallet.getEmoji(); const eWallet = await usewallet.getEvmWallet(); + const currentWallet = await usewallet.getCurrentWallet(); let evmAddress; if (eWallet.address) { evmAddress = ensureEvmAddressPrefix(eWallet.address); @@ -185,10 +185,10 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { const newWallet = { [parentAddress!]: { - name: emojires[0].name, - description: emojires[0].name, + name: currentWallet.name, + description: currentWallet.name, thumbnail: { - url: emojires[0].emoji, + url: currentWallet.icon, }, }, }; @@ -197,17 +197,18 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { if (evmAddress) { evmWallet = { [evmAddress!]: { - name: emojires[1].name, - description: emojires[1].name, + name: eWallet.name, + description: eWallet.name, thumbnail: { - url: emojires[1].emoji, + url: eWallet.icon, }, }, }; } - + console.log('eWallet ', evmWallet); // Merge usewallet lists const walletList = { ...newWallet, ...childresp, ...evmWallet }; + console.log('eWallet walletList', walletList); setChildWallets(walletList); const firstWalletAddress = Object.keys(walletList)[0]; if (firstWalletAddress) { @@ -370,32 +371,26 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { - {occupied && ( - - - {/* */} - - - {chrome.i18n.getMessage('Your__address__is__currently__processing')} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage('Your__address__is__currently__processing')} + + + - - )} - setIsAddAddressOpen(false)} diff --git a/src/ui/views/NftEvm/EmptyStatus.tsx b/src/ui/views/NftEvm/EmptyStatus.tsx index bb8c04db..2fccc5ca 100644 --- a/src/ui/views/NftEvm/EmptyStatus.tsx +++ b/src/ui/views/NftEvm/EmptyStatus.tsx @@ -1,6 +1,7 @@ -import React from 'react'; -import { makeStyles } from '@mui/styles'; import { Typography, Box } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import React from 'react'; + import empty_status from '../../FRWAssets/image/empty_status.svg'; const useStyles = makeStyles(() => ({ diff --git a/src/ui/views/NftEvm/GridView.tsx b/src/ui/views/NftEvm/GridView.tsx index a65ec19a..275519ae 100644 --- a/src/ui/views/NftEvm/GridView.tsx +++ b/src/ui/views/NftEvm/GridView.tsx @@ -1,6 +1,6 @@ import { Typography, Card, CardActionArea, CardMedia, CardContent, Box } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { Link } from 'react-router-dom'; import type { PostMedia } from '@/ui/utils/url'; @@ -102,7 +102,7 @@ const GridView = ({ const [isAccessible, setAccessible] = useState(true); const [media, setGetMediea] = useState(null); - const fecthMedia = async () => { + const fetchMedia = useCallback(async () => { // const bestMedia = await findBestMedia(data, blockList) setGetMediea(data.postMedia); if (accessible) { @@ -115,7 +115,7 @@ const GridView = ({ } }); } - }; + }, [data, accessible]); const navigateWithState = (data, media, index, ownerAddress, isAccessibleNft) => { const state = { @@ -129,8 +129,8 @@ const GridView = ({ }; useEffect(() => { - fecthMedia(); - }, []); + fetchMedia(); + }, [fetchMedia]); const TilteWordWrapped = (desc) => { if (!desc) return null; diff --git a/src/ui/views/NftEvm/SendNFT/MoveNftConfirmation.tsx b/src/ui/views/NftEvm/SendNFT/MoveNftConfirmation.tsx index 3db0c122..3efb7017 100644 --- a/src/ui/views/NftEvm/SendNFT/MoveNftConfirmation.tsx +++ b/src/ui/views/NftEvm/SendNFT/MoveNftConfirmation.tsx @@ -2,9 +2,9 @@ import CloseIcon from '@mui/icons-material/Close'; import InfoIcon from '@mui/icons-material/Info'; import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; -import { Presets } from 'react-component-transition'; import { useHistory } from 'react-router-dom'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { MatchMediaType } from '@/ui/utils/url'; @@ -108,7 +108,9 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { txID, true, `Move complete`, - `You have moved ${[props.data.nft.id].length} ${props.data.nft.collectionContractName} from evm to your flow address. \nClick to view this transaction.` + `You have moved ${[props.data.nft.id].length} ${ + props.data.nft.collectionContractName + } from evm to your flow address. \nClick to view this transaction.` ); props.handleCloseIconClicked(); await usewallet.setDashIndex(0); @@ -150,13 +152,13 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { const getChildResp = useCallback(async () => { const childresp = await usewallet.checkUserChildAccount(); const parentAddress = await usewallet.getMainAddress(); - const emojires = await usewallet.getEmoji(); + const currentWallet = await usewallet.getCurrentWallet(); const newWallet = { [parentAddress!]: { - name: emojires[0].name, - description: emojires[0].name, + name: currentWallet.name, + description: currentWallet.name, thumbnail: { - url: emojires[0].emoji, + url: currentWallet.icon, }, }, }; @@ -309,32 +311,26 @@ const MoveNftConfirmation = (props: SendNFTConfirmationProps) => { - {occupied && ( - - - {/* */} - - - {chrome.i18n.getMessage('Your__address__is__currently__processing')} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage('Your__address__is__currently__processing')} + + + - + ); }; diff --git a/src/ui/views/RecoverRegister/PickUsername.tsx b/src/ui/views/RecoverRegister/PickUsername.tsx index 1f88f7a0..571500dd 100644 --- a/src/ui/views/RecoverRegister/PickUsername.tsx +++ b/src/ui/views/RecoverRegister/PickUsername.tsx @@ -1,14 +1,22 @@ -import React, { useEffect, useState } from 'react'; +import { + CircularProgress, + IconButton, + Button, + Typography, + FormControl, + Input, + InputAdornment, +} from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { useWallet } from 'ui/utils'; + import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import theme from '../../style/LLTheme'; +import CancelIcon from '../../../components/iconfont/IconClose'; import EmailIcon from '../../assets/alternate-email.svg'; -import { Presets } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import { CircularProgress, IconButton } from '@mui/material'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -30,6 +38,41 @@ const useStyles = makeStyles(() => ({ }, }, })); +const UsernameError = (errorMsg) => ( + + + + {errorMsg} + + +); +const UsernameCorrect = ( + + + + {chrome.i18n.getMessage('Sounds_good')} + + +); +const UsernameLoading = () => ( + + + Checking + {chrome.i18n.getMessage('Flow_Core')} + +); const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const classes = useStyles(); @@ -37,60 +80,21 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const [isLoading, setLoading] = useState(false); const [usernameValid, setUsernameValid] = useState(false); - const usernameError = (errorMsg) => ( - - - - {errorMsg} - - - ); - const usernameCorrect = ( - - - - {chrome.i18n.getMessage('Sounds_good')} - - - ); - const usernameLoading = () => ( - - - Checking - {chrome.i18n.getMessage('Flow_Core')} - - ); - const [username, setUsername] = useState(savedUsername || ''); const [helperText, setHelperText] = useState(
); - const regex = /^[A-Za-z0-9]{3,15}$/; - - const setErrorMessage = (message: string) => { - setLoading(false); - setUsernameValid(false); - setHelperText(usernameError(message)); - }; + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setUsernameValid(false); + setHelperText(UsernameError(message)); + }, + [setLoading, setUsernameValid, setHelperText] + ); useEffect(() => { setUsernameValid(false); - setHelperText(usernameLoading); + setHelperText(UsernameLoading); setLoading(true); const delayDebounceFn = setTimeout(() => { if (username.length < 3) { @@ -102,6 +106,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { setErrorMessage(chrome.i18n.getMessage('Too__long')); return; } + const regex = /^[A-Za-z0-9]{3,15}$/; if (!regex.test(username)) { setErrorMessage( @@ -114,13 +119,13 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { .checkUsername(username.toLowerCase()) .then((response) => { setLoading(false); - if (response.data.username != username.toLowerCase()) { + if (response.data.username !== username.toLowerCase()) { setLoading(false); return; } if (response.data.unique) { setUsernameValid(true); - setHelperText(usernameCorrect); + setHelperText(UsernameCorrect); } else { setErrorMessage(chrome.i18n.getMessage('This__name__has__been__taken')); } @@ -132,7 +137,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { }, 500); return () => clearTimeout(delayDebounceFn); - }, [username]); + }, [setErrorMessage, username, wallet.openapi]); const msgBgColor = () => { if (isLoading) { @@ -142,8 +147,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { }; return ( - - + <> {chrome.i18n.getMessage('Pick__Your') + ' '} @@ -187,20 +191,18 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { } /> - - {username && ( - - {helperText} - - )} - + + + {helperText} + + @@ -224,7 +226,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { - + ); }; diff --git a/src/ui/views/RecoverRegister/RecoveryPhrase.tsx b/src/ui/views/RecoverRegister/RecoveryPhrase.tsx index d548b60b..26fabf20 100644 --- a/src/ui/views/RecoverRegister/RecoveryPhrase.tsx +++ b/src/ui/views/RecoverRegister/RecoveryPhrase.tsx @@ -1,9 +1,9 @@ -import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, IconButton, CssBaseline } from '@mui/material'; -import theme from '../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography, IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState } from 'react'; + import IconCopy from '../../../components/iconfont/IconCopy'; const RecoveryPhrase = ({ handleClick, mnemonic }) => { @@ -11,8 +11,7 @@ const RecoveryPhrase = ({ handleClick, mnemonic }) => { const [isCoverBlur, coverBlur] = useState(false); return ( - - + <> {chrome.i18n.getMessage('Recovery') + ' '} @@ -192,7 +191,7 @@ const RecoveryPhrase = ({ handleClick, mnemonic }) => { - + ); }; diff --git a/src/ui/views/RecoverRegister/RegisterHeader.tsx b/src/ui/views/RecoverRegister/RegisterHeader.tsx index e6ad55e5..ebb9631a 100644 --- a/src/ui/views/RecoverRegister/RegisterHeader.tsx +++ b/src/ui/views/RecoverRegister/RegisterHeader.tsx @@ -1,13 +1,11 @@ -import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button } from '@mui/material'; import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; import PhoneAndroidRoundedIcon from '@mui/icons-material/PhoneAndroidRounded'; -import theme from '../../style/LLTheme'; - +import { Button } from '@mui/material'; +import { Box } from '@mui/system'; +import React from 'react'; const RegisterHeader = () => { return ( - + <> { {chrome.i18n.getMessage('Need__Help')} - + ); }; diff --git a/src/ui/views/RecoverRegister/SetPassword.tsx b/src/ui/views/RecoverRegister/SetPassword.tsx index 8eaf88a9..14d1c945 100644 --- a/src/ui/views/RecoverRegister/SetPassword.tsx +++ b/src/ui/views/RecoverRegister/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -8,26 +7,28 @@ import { Alert, Snackbar, Link, - CssBaseline, Input, InputAdornment, FormGroup, LinearProgress, } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; -import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; -import { AccountKey } from 'background/service/networkModel'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; import HDWallet from 'ethereum-hdwallet'; -import { LLSpinner } from '@/ui/FRWComponent'; +import React, { useEffect, useState } from 'react'; +import zxcvbn from 'zxcvbn'; + import { storage } from '@/background/webapi'; +import { LLSpinner } from '@/ui/FRWComponent'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { type AccountKey } from 'background/service/networkModel'; +import { useWallet, saveIndex, mixpanelBrowserService } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; +import { BpUncheked, BpCheckedIcon } from '../../FRWAssets/icons/CustomCheckboxIcons'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -63,32 +64,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -215,6 +190,9 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { await saveIndex(username); const accountKey = getAccountKey(mnemonic); + + // track the time until account_created is called + mixpanelBrowserService.time('account_created'); wallet.openapi .register(accountKey, username) .then((response) => { @@ -260,8 +238,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { }, [confirmPassword, password]); return ( - - + <> {chrome.i18n.getMessage('Create') + ' '} @@ -308,7 +285,9 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + } + icon={} checkedIcon={} onChange={(event) => setCheck(event.target.checked)} /> @@ -401,7 +380,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { - + ); }; diff --git a/src/ui/views/RecoverRegister/index.tsx b/src/ui/views/RecoverRegister/index.tsx index cd11941d..0cdf98fe 100644 --- a/src/ui/views/RecoverRegister/index.tsx +++ b/src/ui/views/RecoverRegister/index.tsx @@ -1,25 +1,26 @@ -import React, { useState, useEffect } from 'react'; +import ExtensionRoundedIcon from '@mui/icons-material/ExtensionRounded'; +import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; +import { IconButton, Typography, Snackbar, SnackbarContent } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useRef } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Snackbar, SnackbarContent, Slide } from '@mui/material'; + +import { storage } from '@/background/webapi'; +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; + +import lilicoIcon from '../../..//..//_raw/images/icon-48.png'; import BackButtonIcon from '../../../components/iconfont/IconBackButton'; -import theme from '../../style/LLTheme'; + +import AllSet from './AllSet'; import PickUsername from './PickUsername'; import RecoveryPhrase from './RecoveryPhrase'; -import AllSet from './AllSet'; import SetPassword from './SetPassword'; -import Particles from 'react-tsparticles'; -import { storage } from '@/background/webapi'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined'; -import ExtensionRoundedIcon from '@mui/icons-material/ExtensionRounded'; -import lilicoIcon from '../../..//..//_raw/images/icon-48.png'; + enum Direction { Right, Left, } -import options from '../Import/options'; - const RecoverRegister = () => { const history = useHistory(); const [activeIndex, onChange] = useState(0); @@ -27,6 +28,7 @@ const RecoverRegister = () => { const [username, setUsername] = useState(''); const [mnemonic, setMnemonic] = useState(''); + const pageRef = useRef(null); const getUsername = (username: string) => { setUsername(username.toLowerCase()); }; @@ -61,7 +63,7 @@ const RecoverRegister = () => { } }; - const page = (index) => { + const Page = React.forwardRef(({ index }: { index: number }, pageRef) => { switch (index) { case 0: return ( @@ -74,18 +76,12 @@ const RecoverRegister = () => { case 3: return ; default: - return
; + return ; } - }; - - const slideTransition = (props) => { - return ; - }; - - const height = [480, 520, 580, 480, 480]; + }); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 3 && ( - - )} - {/* */} - - + {activeIndex === 3 && } + + { - - {page(activeIndex)} - + + + - + ); }; diff --git a/src/ui/views/Register/AllSet.tsx b/src/ui/views/Register/AllSet.tsx index e92fbd75..d04a6f72 100644 --- a/src/ui/views/Register/AllSet.tsx +++ b/src/ui/views/Register/AllSet.tsx @@ -1,23 +1,35 @@ -import React, { useEffect } from 'react'; -import { useWallet } from 'ui/utils'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline, CardMedia } from '@mui/material'; -import theme from '../../style/LLTheme'; +import { Button, Typography, CardMedia } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect } from 'react'; + import AllSetIcon from 'ui/FRWAssets/svg/allset.svg'; +import { useWallet, mixpanelBrowserService } from 'ui/utils'; const AllSet = ({ handleClick }) => { - const wallets = useWallet(); + const wallet = useWallet(); + + const loadScript = useCallback(async () => { + await wallet.getCadenceScripts(); + }, [wallet]); - const loadScript = async () => { - await wallets.getCadenceScripts(); - }; + const trackAccountRecovered = useCallback(async () => { + // I'm not sure if this is the best way to track this event + // It's hard to know at which point the user recovers the account + mixpanelBrowserService.track('account_recovered', { + address: (await wallet.getMainAddress()) || '', + mechanism: 'multi-backup', + methods: [], + }); + }, [wallet]); useEffect(() => { - loadScript(); - }, []); + loadScript().then(() => { + trackAccountRecovered(); + }); + }, [loadScript, trackAccountRecovered]); + return ( - - + <> { - + ); }; diff --git a/src/ui/views/Register/GoogleBackup.tsx b/src/ui/views/Register/GoogleBackup.tsx index de6cc46f..26911a04 100644 --- a/src/ui/views/Register/GoogleBackup.tsx +++ b/src/ui/views/Register/GoogleBackup.tsx @@ -1,12 +1,13 @@ +import InfoIcon from '@mui/icons-material/Info'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline } from '@mui/material'; -import theme from '../../style/LLTheme'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; + import IconGoogleDrive from '../../../components/iconfont/IconGoogleDrive'; -import { LLSpinner } from 'ui/FRWComponent'; -import InfoIcon from '@mui/icons-material/Info'; -import { Presets } from 'react-component-transition'; const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { const wallets = useWallet(); @@ -33,8 +34,7 @@ const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { } }; return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -94,35 +94,29 @@ const GoogleBackup = ({ handleClick, mnemonic, username, password }) => { - {backupErr && ( - - - {/* */} - - - {chrome.i18n.getMessage( - 'Backup_failed_you_may_still_conduct_backup_inside_extension' - )} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage( + 'Backup_failed_you_may_still_conduct_backup_inside_extension' + )} + + + - + ); }; diff --git a/src/ui/views/Register/PickUsername.tsx b/src/ui/views/Register/PickUsername.tsx index 3bbf384b..49a460bf 100644 --- a/src/ui/views/Register/PickUsername.tsx +++ b/src/ui/views/Register/PickUsername.tsx @@ -1,16 +1,24 @@ -import React, { useEffect, useState } from 'react'; +import { + CircularProgress, + IconButton, + Button, + Typography, + FormControl, + Input, + InputAdornment, +} from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { useWallet } from 'ui/utils'; + import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import theme from '../../style/LLTheme'; +import CancelIcon from '../../../components/iconfont/IconClose'; import EmailIcon from '../../assets/alternate-email.svg'; -import { Presets } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import { CircularProgress, IconButton } from '@mui/material'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_theme) => ({ customInputLabel: { '& legend': { visibility: 'visible', @@ -31,71 +39,68 @@ const useStyles = makeStyles((theme) => ({ }, })); +const UsernameError = (errorMsg) => ( + + + + {errorMsg} + {errorMsg.startsWith('This username is reserved') && ( + + hi@lilico.app + {chrome.i18n.getMessage('for__any__inquiry')} + + )} + + +); +const UsernameCorrect = ( + + + + {chrome.i18n.getMessage('Sounds_good')} + + +); +const UsernameLoading = () => ( + + + {chrome.i18n.getMessage('Checking')} + +); + const PickUsername = ({ handleClick, savedUsername, getUsername }) => { const classes = useStyles(); const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const [usernameValid, setUsernameValid] = useState(false); - const usernameError = (errorMsg) => ( - - - - {errorMsg} - {errorMsg.startsWith('This username is reserved') && ( - - hi@lilico.app - {chrome.i18n.getMessage('for__any__inquiry')} - - )} - - - ); - const usernameCorrect = ( - - - - {chrome.i18n.getMessage('Sounds_good')} - - - ); - const usernameLoading = () => ( - - - {chrome.i18n.getMessage('Checking')} - - ); - const [username, setUsername] = useState(savedUsername || ''); const [helperText, setHelperText] = useState(
); - const regex = /^[A-Za-z0-9]{3,15}$/; - - const setErrorMessage = (message: string) => { - setLoading(false); - setUsernameValid(false); - setHelperText(usernameError(message)); - }; + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setUsernameValid(false); + setHelperText(UsernameError(message)); + }, + [setLoading, setUsernameValid, setHelperText] + ); useEffect(() => { setUsernameValid(false); - setHelperText(usernameLoading); + setHelperText(UsernameLoading); setLoading(true); const delayDebounceFn = setTimeout(() => { if (username.length < 3) { @@ -107,6 +112,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { setErrorMessage(chrome.i18n.getMessage('Too__long')); return; } + const regex = /^[A-Za-z0-9]{3,15}$/; if (!regex.test(username)) { setErrorMessage( @@ -118,15 +124,15 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { .checkUsername(username.toLowerCase()) .then((response) => { setLoading(false); - if (response.data.username != username.toLowerCase()) { + if (response.data.username !== username.toLowerCase()) { setLoading(false); return; } if (response.data.unique) { setUsernameValid(true); - setHelperText(usernameCorrect); + setHelperText(UsernameCorrect); } else { - if (response.message == 'Username is reserved') { + if (response.message === 'Username is reserved') { setErrorMessage( chrome.i18n.getMessage('This__username__is__reserved__Please__contact') ); @@ -141,7 +147,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { }, 500); return () => clearTimeout(delayDebounceFn); - }, [username]); + }, [setErrorMessage, username, wallet.openapi]); const msgBgColor = () => { if (isLoading) { @@ -151,8 +157,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { }; return ( - - + <> {chrome.i18n.getMessage('Pick__Your')} @@ -196,20 +201,18 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { } /> - - {username && ( - - {helperText} - - )} - + + + {helperText} + + @@ -233,7 +236,7 @@ const PickUsername = ({ handleClick, savedUsername, getUsername }) => { - + ); }; diff --git a/src/ui/views/Register/RecoveryPhrase.tsx b/src/ui/views/Register/RecoveryPhrase.tsx index 228afeb1..ecf80ad8 100644 --- a/src/ui/views/Register/RecoveryPhrase.tsx +++ b/src/ui/views/Register/RecoveryPhrase.tsx @@ -1,20 +1,20 @@ -import React, { useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, IconButton, CssBaseline } from '@mui/material'; -import theme from '../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import InfoIcon from '@mui/icons-material/Info'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography, IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import IconCopy from '../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; -import InfoIcon from '@mui/icons-material/Info'; const RecoveryPhrase = ({ handleClick, mnemonic }) => { const [canGoNext, setCanGoNext] = useState(false); const [isCoverBlur, coverBlur] = useState(true); return ( - - + <> {chrome.i18n.getMessage('Recovery')} @@ -189,7 +189,7 @@ const RecoveryPhrase = ({ handleClick, mnemonic }) => { justifyContent: 'flex-end', }} > - + { )} - + - + ); }; diff --git a/src/ui/views/Register/RegisterHeader.tsx b/src/ui/views/Register/RegisterHeader.tsx index 234219ff..fb499d7f 100644 --- a/src/ui/views/Register/RegisterHeader.tsx +++ b/src/ui/views/Register/RegisterHeader.tsx @@ -1,12 +1,11 @@ -import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography } from '@mui/material'; -import theme from '../../style/LLTheme'; import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React from 'react'; const RegisterHeader = () => { return ( - + <> { - + ); }; diff --git a/src/ui/views/Register/RegisterPager.tsx b/src/ui/views/Register/RegisterPager.tsx index 9df50f69..42fc829d 100644 --- a/src/ui/views/Register/RegisterPager.tsx +++ b/src/ui/views/Register/RegisterPager.tsx @@ -1,22 +1,23 @@ -import React, { useEffect, useState } from 'react'; -import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; import { IconButton, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import * as bip39 from 'bip39'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; + +import { LLPinAlert } from '@/ui/FRWComponent'; +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../components/iconfont/IconBackButton'; -import theme from '../../style/LLTheme'; -import RegisterHeader from './RegisterHeader'; + +import AllSet from './AllSet'; +import GoogleBackup from './GoogleBackup'; import PickUsername from './PickUsername'; import RecoveryPhrase from './RecoveryPhrase'; +import RegisterHeader from './RegisterHeader'; import RepeatPhrase from './RepeatPhrase'; -import GoogleBackup from './GoogleBackup'; -import AllSet from './AllSet'; import SetPassword from './SetPassword'; -import Particles from 'react-tsparticles'; -import * as bip39 from 'bip39'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { LLPinAlert } from '@/ui/FRWComponent'; -import options from '../Import/options'; -import { useWallet } from 'ui/utils'; enum Direction { Right, @@ -30,13 +31,13 @@ const RegisterPager = () => { const [direction, setDirection] = useState(Direction.Right); const [username, setUsername] = useState(''); const [password, setPassword] = useState(null); - const [mnemonic, setMnemonic] = useState(bip39.generateMnemonic()); + const [mnemonic] = useState(bip39.generateMnemonic()); const getUsername = (username: string) => { setUsername(username.toLowerCase()); }; - const loadView = async () => { + const loadView = useCallback(async () => { // console.log(wallet); wallet .getCurrentAccount() @@ -48,7 +49,7 @@ const RegisterPager = () => { .catch(() => { return; }); - }; + }, [wallet, history]); const goNext = () => { setDirection(Direction.Right); @@ -104,14 +105,11 @@ const RegisterPager = () => { }; useEffect(() => { - console.log('wallet'); loadView(); - }, []); - - const height = [480, 600, 640, 620, 480, 480]; + }, [loadView]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 5 && ( - - )} + {activeIndex === 5 && } - + {/* height why not use auto */} @@ -180,30 +173,14 @@ const RegisterPager = () => { - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/Register/RepeatPhrase.tsx b/src/ui/views/Register/RepeatPhrase.tsx index 90ae7afd..eaf852d7 100644 --- a/src/ui/views/Register/RepeatPhrase.tsx +++ b/src/ui/views/Register/RepeatPhrase.tsx @@ -1,12 +1,13 @@ -import React, { useState, useEffect } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline } from '@mui/material'; -import theme from '../../style/LLTheme'; -import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import InfoIcon from '@mui/icons-material/Info'; import LockOpenRoundedIcon from '@mui/icons-material/LockOpenRounded'; +import LockRoundedIcon from '@mui/icons-material/LockRounded'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + import IconCopy from '../../../components/iconfont/IconCopy'; -import { Presets } from 'react-component-transition'; -import InfoIcon from '@mui/icons-material/Info'; const randomElement = (list: any[]) => { return list[Math.floor(Math.random() * list.length)]; @@ -40,9 +41,9 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { const checkMatch = () => { const correctMatch = chosenIndex.map((index) => mnemonicArray[index]); if ( - selectedPhrase[0] == correctMatch[0] && - selectedPhrase[1] == correctMatch[1] && - selectedPhrase[2] == correctMatch[2] + selectedPhrase[0] === correctMatch[0] && + selectedPhrase[1] === correctMatch[1] && + selectedPhrase[2] === correctMatch[2] ) { handleClick(); return; @@ -56,7 +57,7 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { }, 5000); }; - const handleRandom = () => { + const handleRandom = useCallback(() => { const arr: number[] = []; // [[0,1,2,3],[4,5,6,7],[8,9,10,11]] const repeatIndex: number[][] = [[], [], []]; @@ -66,7 +67,7 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { positionList.forEach((list, i) => { const picked = randomElement(list); const exclude = fullIndex - .filter((item) => item != picked) + .filter((item) => item !== picked) .sort(() => { return Math.random() - 0.5; }); @@ -79,14 +80,14 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { }); setChosen(arr); setRepeat(repeatMap); - }; + }, [mnemonicArray, positionList]); + useEffect(() => { handleRandom(); - }, []); + }, [handleRandom]); return ( - - + <> {chrome.i18n.getMessage('Verify') + ' '} @@ -153,14 +154,14 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { height: '100%', width: '100%', borderRadius: '8px', - backgroundColor: `${selectedPhrase[i] == v ? '#fff' : 'none'}`, + backgroundColor: `${selectedPhrase[i] === v ? '#fff' : 'none'}`, }} > {v} @@ -185,33 +186,27 @@ const RepeatPhrase = ({ handleClick, mnemonic }) => { justifyContent: 'flex-end', }} > - {incorrect && ( - - - - - {chrome.i18n.getMessage('Incorrect_recovery_phrases_please_try_again')} - - - - )} + + + + + {chrome.i18n.getMessage('Incorrect_recovery_phrases_please_try_again')} + + + - + ); }; diff --git a/src/ui/views/Register/SetPassword.tsx b/src/ui/views/Register/SetPassword.tsx index c3c9a0c7..af1b5184 100644 --- a/src/ui/views/Register/SetPassword.tsx +++ b/src/ui/views/Register/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -12,22 +11,24 @@ import { InputAdornment, FormGroup, LinearProgress, - CssBaseline, } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; -import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; -import { AccountKey } from 'background/service/networkModel'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; import HDWallet from 'ethereum-hdwallet'; -import { LLSpinner } from 'ui/FRWComponent'; +import React, { useEffect, useState } from 'react'; +import zxcvbn from 'zxcvbn'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { type AccountKey } from 'background/service/networkModel'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex, mixpanelBrowserService } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; +import { BpUncheked, BpCheckedIcon } from '../../FRWAssets/icons/CustomCheckboxIcons'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -63,32 +64,6 @@ const useStyles = makeStyles(() => ({ }, })); -const BpIcon = styled('span')(() => ({ - borderRadius: 8, - width: 24, - height: 24, - border: '1px solid #41CC5D', - backgroundColor: 'transparent', -})); - -const BpCheckedIcon = styled(BpIcon)({ - backgroundColor: '#41CC5D', - backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))', - '&:before': { - display: 'block', - width: 21, - height: 21, - backgroundImage: - "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + - " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + - "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")", - content: '""', - }, - 'input:hover ~ &': { - backgroundColor: '#41CC5D', - }, -}); - const PasswordIndicator = (props) => { const score = zxcvbn(props.value).score; const precentage = ((score + 1) / 5) * 100; @@ -217,6 +192,8 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword }) => { await saveIndex(username); const accountKey = getAccountKey(mnemonic); + // track the time until account_created is called + mixpanelBrowserService.time('account_created'); wallet.openapi .register(accountKey, username) .then((response) => { @@ -262,8 +239,7 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword }) => { }, [confirmPassword, password]); return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -310,9 +286,9 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword }) => { } /> - - {password && helperText} - + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + } + icon={} checkedIcon={} onChange={(event) => setCheck(event.target.checked)} /> @@ -400,7 +376,7 @@ const SetPassword = ({ handleClick, mnemonic, username, setExPassword }) => { {errMessage} - + ); }; diff --git a/src/ui/views/Reset/RecoverPassword.tsx b/src/ui/views/Reset/RecoverPassword.tsx index 8a32bd18..4e068406 100644 --- a/src/ui/views/Reset/RecoverPassword.tsx +++ b/src/ui/views/Reset/RecoverPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -12,20 +11,21 @@ import { InputAdornment, FormGroup, LinearProgress, - CssBaseline, } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import FormControlLabel from '@mui/material/FormControlLabel'; import Checkbox from '@mui/material/Checkbox'; -import { Presets } from 'react-component-transition'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; -import { LLSpinner } from 'ui/FRWComponent'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -188,7 +188,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { ); }; - const [helperText, setHelperText] = useState(
); + const [helperText, setHelperText] = useState(
); const [helperMatch, setHelperMatch] = useState(
); const signIn = async () => { @@ -249,8 +249,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { }; return ( - - + <> {chrome.i18n.getMessage('Create')} @@ -298,7 +297,9 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + @@ -382,7 +383,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { {renderSnackBar()} - + ); }; diff --git a/src/ui/views/Reset/ResetRecoveryPhrase.tsx b/src/ui/views/Reset/ResetRecoveryPhrase.tsx index 3359309b..447efa6c 100644 --- a/src/ui/views/Reset/ResetRecoveryPhrase.tsx +++ b/src/ui/views/Reset/ResetRecoveryPhrase.tsx @@ -1,6 +1,3 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { makeStyles } from '@mui/styles'; import { Typography, FormControl, @@ -9,16 +6,19 @@ import { Snackbar, Alert, Button, - CssBaseline, } from '@mui/material'; -import theme from '../../style/LLTheme'; -import { Presets } from 'react-component-transition'; -import { useWallet } from 'ui/utils'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import { makeStyles } from '@mui/styles'; +import { Box } from '@mui/system'; import * as bip39 from 'bip39'; -import { LLNotFound, LLSpinner } from 'ui/FRWComponent'; +import React, { useCallback, useEffect, useState } from 'react'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLNotFound, LLSpinner } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; const useStyles = makeStyles((theme) => ({ customInputLabel: { @@ -43,6 +43,43 @@ const useStyles = makeStyles((theme) => ({ }, })); +const MnemonicError = (errorMsg) => ( + + + + {errorMsg} + + +); + +const MnemonicCorrect = ( + + + + {chrome.i18n.getMessage('Recovery__phrase__valid')} + + +); + +const MnemonicLoading = () => ( + + + {chrome.i18n.getMessage('Checking')} + +); + const ResetRecoveryPhrase = ({ handleClick, confirmMnemonic, setUsername }) => { const classes = useStyles(); const wallet = useWallet(); @@ -77,47 +114,6 @@ const ResetRecoveryPhrase = ({ handleClick, confirmMnemonic, setUsername }) => { } }; - const mnemonicError = (errorMsg) => ( - - - - {errorMsg} - - - ); - - const mnemonicCorrect = ( - - - - {chrome.i18n.getMessage('Recovery__phrase__valid')} - - - ); - - const mnemonicLoading = () => ( - - - {chrome.i18n.getMessage('Checking')} - - ); - const renderSnackBar = () => { return ( { ); }; + const setErrorMessage = useCallback( + (message: string) => { + setLoading(false); + setMnemonicValid(false); + setHelperText(MnemonicError(message)); + }, + [setLoading, setMnemonicValid, setHelperText] + ); useEffect(() => { setMnemonicValid(false); - setHelperText(mnemonicLoading); + setHelperText(MnemonicLoading); setLoading(true); const delayDebounceFn = setTimeout(() => { setLoading(false); const length = mnemonic.trim().split(/\s+/g).length; - if (!(length == 12 || length == 24)) { + if (!(length === 12 || length === 24)) { setErrorMessage( chrome.i18n.getMessage('Recovery_phrases_word_count_must_be_12_or_24_words') ); @@ -160,19 +164,13 @@ const ResetRecoveryPhrase = ({ handleClick, confirmMnemonic, setUsername }) => { } setMnemonicValid(true); - setHelperText(mnemonicCorrect); + setHelperText(MnemonicCorrect); storage.set('premnemonic', formatted); setMnemonic(formatted); }, 500); return () => clearTimeout(delayDebounceFn); - }, [mnemonic]); - - const setErrorMessage = (message: string) => { - setLoading(false); - setMnemonicValid(false); - setHelperText(mnemonicError(message)); - }; + }, [mnemonic, setErrorMessage]); const msgBgColor = () => { if (isLoading) { @@ -182,8 +180,7 @@ const ResetRecoveryPhrase = ({ handleClick, confirmMnemonic, setUsername }) => { }; return ( - - + <> {!showDialog ? ( @@ -216,20 +213,18 @@ const ResetRecoveryPhrase = ({ handleClick, confirmMnemonic, setUsername }) => { setMnemonic(event.target.value); }} /> - - {mnemonic && ( - - {helperText} - - )} - + + + {helperText} + + @@ -262,7 +257,7 @@ const ResetRecoveryPhrase = ({ handleClick, confirmMnemonic, setUsername }) => { ) : ( )} - + ); }; diff --git a/src/ui/views/Reset/index.tsx b/src/ui/views/Reset/index.tsx index 99430ed8..5872e984 100644 --- a/src/ui/views/Reset/index.tsx +++ b/src/ui/views/Reset/index.tsx @@ -1,19 +1,21 @@ +import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; +import { Box } from '@mui/system'; import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../components/iconfont/IconBackButton'; -import theme from '../../style/LLTheme'; -import RegisterHeader from '../Register/RegisterHeader'; -import ResetRecoveryPhrase from './ResetRecoveryPhrase'; +import IconGoogleDrive from '../../../components/iconfont/IconGoogleDrive'; import AllSet from '../Register/AllSet'; +import RegisterHeader from '../Register/RegisterHeader'; + import RecoverPassword from './RecoverPassword'; -import Particles from 'react-tsparticles'; -import { LLSpinner } from 'ui/FRWComponent'; -import IconGoogleDrive from '../../../components/iconfont/IconGoogleDrive'; -import { useWallet } from 'ui/utils'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import options from '../Import/options'; +import ResetRecoveryPhrase from './ResetRecoveryPhrase'; enum Direction { Right, @@ -92,7 +94,7 @@ const Reset = () => { }; return ( - + <> { alignItems: 'center', }} > - {activeIndex == 2 && ( - - )} + {activeIndex === 2 && } + { - + {page(activeIndex)} - + {activeIndex === 0 && ( @@ -212,7 +194,7 @@ const Reset = () => { - + ); }; diff --git a/src/ui/views/RetrievePK/index.tsx b/src/ui/views/RetrievePK/index.tsx index a45dedd1..49b90d24 100644 --- a/src/ui/views/RetrievePK/index.tsx +++ b/src/ui/views/RetrievePK/index.tsx @@ -1,12 +1,13 @@ -import React, { useEffect, useRef, useState } from 'react'; // import { useTranslation } from 'react-i18next'; -import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; -import { Typography, Box, FormControl, List, ListItem, ListItemText } from '@mui/material'; +import { Input, Typography, Box, FormControl, List, ListItem, ListItemText } from '@mui/material'; +import { makeStyles } from '@mui/styles'; +import React, { useEffect, useRef, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { LLPrimaryButton, CredentialBox, LLSecondaryButton } from 'ui/FRWComponent'; -import { Input } from '@mui/material'; -import { Presets } from 'react-component-transition'; +import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; + import CancelIcon from '../../../components/iconfont/IconClose'; -import { makeStyles } from '@mui/styles'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -155,20 +156,18 @@ const RetrievePK = () => { onKeyDown={handleKeyDown} /> - - {showError && ( - - {usernameError()} - - )} - + + + {usernameError()} + + )} diff --git a/src/ui/views/Send/AccountsList.tsx b/src/ui/views/Send/AccountsList.tsx index b32f2290..e9457928 100644 --- a/src/ui/views/Send/AccountsList.tsx +++ b/src/ui/views/Send/AccountsList.tsx @@ -1,11 +1,12 @@ -import React, { useEffect, useState } from 'react'; -import { List, ListSubheader, CardMedia, Typography, ButtonBase, Box } from '@mui/material'; +import { List, ListSubheader, ButtonBase, Box } from '@mui/material'; import { groupBy, isEmpty } from 'lodash'; -import { LLContactCard, LLContactEth, FWContactCard } from '../../FRWComponent'; +import React, { useEffect, useState, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; + +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet } from 'ui/utils'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; -import EmptyAddress from 'ui/assets/EmptyAddress.svg'; + +import { LLContactCard, LLContactEth, FWContactCard } from '../../FRWComponent'; type ChildAccount = { [key: string]: { @@ -20,56 +21,44 @@ type ChildAccount = { const AccountsList = ({ filteredContacts, isLoading, handleClick, isSend = true }) => { const usewallet = useWallet(); - const [grouped, setGrouped] = useState([]); + const [, setGrouped] = useState([]); const [childAccounts, setChildAccount] = useState([]); const [walletList, setWalletList] = useState([]); const [evmAddress, setEvmAddress] = useState([]); - const getWallet = async () => { + const getWallet = useCallback(async () => { const wallet = await usewallet.getUserWallets(); const fData = wallet.filter((item) => item.blockchain !== null); const currentNetwork = await usewallet.getNetwork(); - const emojiList = await usewallet.getEmoji(); let sortData = fData; if (!Array.isArray(sortData)) { sortData = []; } - const filteredData = (sortData || []).filter((wallet, index) => { - return wallet.chain_id == currentNetwork; - }); - const walletData = (filteredData || []).map((wallet, index) => { - return { - id: index, - contact_name: '', - address: withPrefix(wallet.blockchain[0].address), - key: index, - }; - }); - const wdArray = await convertArrayToContactArray(walletData, emojiList); + const wdArray = await convertArrayToContactArray(fData); const childresp: ChildAccount = await usewallet.checkUserChildAccount(); if (childresp) { const cAccountArray = convertObjectToContactArray(childresp); setChildAccount(cAccountArray); } - console.log('childresp ', wdArray); - // putDeviceInfo(fData); + const mainAddress = await usewallet.getMainAddress(); await setWalletList(wdArray); - if (walletData[0].address) { - const evmAddress = await usewallet.queryEvmAddress(walletData[0].address!); - - if (isValidEthereumAddress(evmAddress)) { - const evmWallet = evmAddress; - const evmData = walletData[0]; - evmData.address = evmWallet; - evmData['avatar'] = emojiList[1].emoji; - evmData['contact_name'] = emojiList[1].name; - evmData['bgcolor'] = emojiList[1].bgcolor; + if (mainAddress) { + const evmAddress = await usewallet.queryEvmAddress(mainAddress); + const evmWallet = await usewallet.getEvmWallet(); + console.log(' evm ', evmAddress, evmWallet); + + if (isValidEthereumAddress(evmAddress) && evmWallet) { + const evmData = evmWallet; + evmData['address'] = evmAddress!; + evmData['avatar'] = evmWallet.icon; + evmData['contact_name'] = evmWallet.name; + evmData['bgcolor'] = evmWallet.color; setEvmAddress([evmData]); } } - }; + }, [usewallet]); function convertObjectToContactArray(data) { return Object.keys(data).map((address, index) => ({ @@ -86,20 +75,18 @@ const AccountsList = ({ filteredContacts, isLoading, handleClick, isSend = true })); } - async function convertArrayToContactArray(array, emojiList) { - // Fetch emoji list - - return array.map((item, index) => { + async function convertArrayToContactArray(array) { + return array.map((item) => { return { id: item.id, - contact_name: emojiList[0].name, // Use the corresponding emoji name - username: emojiList[0].name, // Set username from emoji list - avatar: emojiList[0].emoji, // Set avatar from emoji list - address: item.address, // Use the address from the original array - contact_type: 1, // Keep the contact_type constant - bgColor: emojiList[0].bgcolor, // Set background color + contact_name: item.name, + username: item.name, + avatar: item.icon, + address: withPrefix(item.blockchain[0].address), + contact_type: 1, + bgColor: item.color, // Set background color domain: { - domain_type: 0, // Keep domain_type constant + domain_type: 0, value: '', }, }; @@ -119,7 +106,7 @@ const AccountsList = ({ filteredContacts, isLoading, handleClick, isSend = true const group = groupBy(filteredContacts, (contact) => contact.contact_name[0]); setGrouped(group); getWallet(); - }, [filteredContacts]); + }, [filteredContacts, getWallet]); const history = useHistory(); diff --git a/src/ui/views/Send/AddressBookList.tsx b/src/ui/views/Send/AddressBookList.tsx index 49c74260..dd18ad3f 100644 --- a/src/ui/views/Send/AddressBookList.tsx +++ b/src/ui/views/Send/AddressBookList.tsx @@ -1,9 +1,11 @@ -import React, { useEffect, useState } from 'react'; import { List, ListSubheader, CardMedia, Typography, ButtonBase, Box } from '@mui/material'; import { groupBy, isEmpty } from 'lodash'; -import { LLContactCard } from '../../FRWComponent'; +import React, { useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; -import EmptyAddress from 'ui/assets/EmptyAddress.svg'; + +import emptyAddress from 'ui/assets/emptyAddress.svg'; + +import { LLContactCard } from '../../FRWComponent'; const AddressBookList = ({ filteredContacts, isLoading, handleClick }) => { const [grouped, setGrouped] = useState([]); @@ -62,7 +64,7 @@ const AddressBookList = ({ filteredContacts, isLoading, handleClick }) => { > { return ( @@ -39,7 +40,7 @@ const RecentList = ({ filteredContacts, isLoading, handleClick }) => { > { const [grouped, setGrouped] = useState([]); @@ -15,9 +16,7 @@ const SearchList = ({ searchContacts, isLoading, handleClick }) => { const group = groupBy(filterContacts, (contact) => contact.group); setGrouped(group); - }, []); - - const history = useHistory(); + }, [searchContacts]); return ( @@ -65,7 +64,7 @@ const SearchList = ({ searchContacts, isLoading, handleClick }) => { > { - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; +const SendAmount = () => { const history = useHistory(); const location = useLocation(); const usewallet = useWallet(); @@ -52,14 +52,29 @@ const SendAmount = () => { const [amount, setAmount] = useState(undefined); const [secondAmount, setSecondAmount] = useState('0.0'); const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [network, setNetwork] = useState('mainnet'); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [isLoading, setLoading] = useState(false); const [childType, setChildType] = useState(''); const [minAmount, setMinAmount] = useState(0); - const setUserWallet = async () => { + const setUserMinAmount = useCallback( + async (address: string) => { + try { + // Try fetching the min amount from the API + const minAmount = await usewallet.openapi.getAccountMinFlow(address); + setMinAmount(minAmount); + } catch (error) { + // If there's an error, set the min amount to 0.001 + console.error('Error fetching min amount:', error); + setMinAmount(0.001); + } + }, + [usewallet] + ); + + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const token = await usewallet.getCurrentCoin(); @@ -84,6 +99,8 @@ const SendAmount = () => { const info = await usewallet.getUserInfo(false); const isChild = await usewallet.getActiveWallet(); console.log('isChild ', info, isChild); + const userContact = { ...USER_CONTACT }; + if (isChild) { if (isChild !== 'evm') { const childResp = await usewallet.checkUserChildAccount(); @@ -101,23 +118,11 @@ const SendAmount = () => { userContact.avatar = info.avatar; userContact.contact_name = info.username; } - setUserMinAmount(); + setUserMinAmount(userContact.address); setUser(userContact); - }; + }, [childType, setWallet, setCoinList, setCoinInfo, setUser, setUserMinAmount, usewallet]); - const setUserMinAmount = async () => { - try { - // Try fetching the min amount from the API - const minAmount = await usewallet.openapi.getAccountMinFlow(userContact.address); - setMinAmount(minAmount); - } catch (error) { - // If there's an error, set the min amount to 0.001 - console.error('Error fetching min amount:', error); - setMinAmount(0.001); - } - }; - - const checkAddress = async () => { + const checkAddress = useCallback(async () => { const child = await usewallet.getActiveWallet(); setChildType(child); @@ -131,34 +136,34 @@ const SendAmount = () => { setValidated(false); } setLoading(false); - }; + }, [setLoading, setValidated, location?.state?.contact?.address, usewallet]); const numberWithCommas = (x) => { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); }; - const updateCoinInfo = () => { + const updateCoinInfo = useCallback(() => { const coin = coinList.find((coin) => coin.unit.toLowerCase() === currentCoin.toLowerCase()); if (coin) { setCoinInfo(coin); } - }; + }, [coinList, currentCoin, setCoinInfo]); useEffect(() => { checkAddress(); - }, []); + }, [checkAddress]); useEffect(() => { setUserWallet(); - }, [childType]); + }, [childType, setUserWallet]); useEffect(() => { updateCoinInfo(); - }, [currentCoin]); + }, [currentCoin, updateCoinInfo]); return (
- + <> @@ -170,11 +175,11 @@ const SendAmount = () => { isSend={true} /> - - {validated !== null && - (validated ? ( - <> - ) : ( + {validated !== null && + (validated ? ( + <> + ) : ( + { - ))} - + + ))} { /> )} - +
); }; diff --git a/src/ui/views/Send/SendEth/EvmConfirmation.tsx b/src/ui/views/Send/SendEth/EvmConfirmation.tsx index 3b83a433..40d835ca 100644 --- a/src/ui/views/Send/SendEth/EvmConfirmation.tsx +++ b/src/ui/views/Send/SendEth/EvmConfirmation.tsx @@ -3,9 +3,9 @@ import InfoIcon from '@mui/icons-material/Info'; import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } from '@mui/material'; import BN from 'bignumber.js'; import React, { useState, useEffect, useCallback } from 'react'; -import { Presets } from 'react-component-transition'; import { useHistory } from 'react-router-dom'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -38,6 +38,7 @@ const ToEthConfirmation = (props: ToEthConfirmationProps) => { const movingBetweenEVMAndFlow = true; const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount, + coin: props.data?.coinInfo?.coin, movingBetweenEVMAndFlow, }); @@ -223,7 +224,12 @@ const ToEthConfirmation = (props: ToEthConfirmationProps) => { - + { - {occupied && ( - - - {/* */} - - - {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} + + + { size="large" sx={{ height: '50px', + width: '100%', borderRadius: '12px', textTransform: 'capitalize', display: 'flex', diff --git a/src/ui/views/Send/SendEth/ToEthConfirmation.tsx b/src/ui/views/Send/SendEth/ToEthConfirmation.tsx index 7ee61414..c04a33c1 100644 --- a/src/ui/views/Send/SendEth/ToEthConfirmation.tsx +++ b/src/ui/views/Send/SendEth/ToEthConfirmation.tsx @@ -2,14 +2,14 @@ import CloseIcon from '@mui/icons-material/Close'; import InfoIcon from '@mui/icons-material/Info'; import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; -import { Presets } from 'react-component-transition'; import { useHistory } from 'react-router-dom'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import IconNext from 'ui/FRWAssets/svg/next.svg'; -import { LLSpinner, LLProfile, FRWProfile } from 'ui/FRWComponent'; +import { LLSpinner, LLProfile, FRWProfile, FRWTargetProfile } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; interface ToEthConfirmationProps { @@ -33,6 +33,7 @@ const ToEthConfirmation = (props: ToEthConfirmationProps) => { const [count, setCount] = useState(0); const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount: 0, + coin: props.data?.coinInfo?.coin, movingBetweenEVMAndFlow: true, }); @@ -234,10 +235,10 @@ const ToEthConfirmation = (props: ToEthConfirmationProps) => { - {props.data.childType ? ( + {props.data.childType && props.data.childType !== 'evm' ? ( ) : ( - + )} { - {occupied && ( - - - {/* */} - - - {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} + + + { size="large" sx={{ height: '50px', + width: '100%', borderRadius: '12px', textTransform: 'capitalize', display: 'flex', diff --git a/src/ui/views/Send/SendEth/index.tsx b/src/ui/views/Send/SendEth/index.tsx index 847ba546..29c331bb 100644 --- a/src/ui/views/Send/SendEth/index.tsx +++ b/src/ui/views/Send/SendEth/index.tsx @@ -1,50 +1,47 @@ -import React, { useState, useEffect } from 'react'; import { Box, Button, Typography, IconButton, CardMedia } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; +import Web3 from 'web3'; + +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; +import { LLHeader } from '@/ui/FRWComponent'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { type CoinItem } from 'background/service/coinList'; +import { type Contact } from 'background/service/networkModel'; +import erc20ABI from 'background/utils/erc20.abi.json'; import { EVM_ENDPOINT } from 'consts'; -import { CoinItem } from 'background/service/coinList'; -import theme from '../../../style/LLTheme'; -import { ThemeProvider } from '@mui/material/styles'; -import TransferAmount from '../TransferAmount'; -import { useWallet } from 'ui/utils'; -import { withPrefix, isValidEthereumAddress } from 'ui/utils/address'; -import ToEthConfirmation from './ToEthConfirmation'; -import EvmConfirmation from './EvmConfirmation'; import { LLContactCard } from 'ui/FRWComponent'; -import { Contact } from 'background/service/networkModel'; -import { Presets } from 'react-component-transition'; +import { useWallet } from 'ui/utils'; + import CancelIcon from '../../../../components/iconfont/IconClose'; -import { LLHeader } from '@/ui/FRWComponent'; -import Web3 from 'web3'; -import erc20ABI from 'background/utils/erc20.abi.json'; +import TransferAmount from '../TransferAmount'; +import EvmConfirmation from './EvmConfirmation'; +import ToEthConfirmation from './ToEthConfirmation'; interface ContactState { contact: Contact; } +const USER_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; const SendEth = () => { - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; - - const history = useHistory(); const location = useLocation(); const usewallet = useWallet(); const [userWallet, setWallet] = useState(null); @@ -55,16 +52,30 @@ const SendEth = () => { const [amount, setAmount] = useState(undefined); const [secondAmount, setSecondAmount] = useState('0'); const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [network, setNetwork] = useState('mainnet'); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [isLoading, setLoading] = useState(false); const [childType, setChildType] = useState(''); const [minAmount, setMinAmount] = useState(0); const [erc20Contract, setErc20Contract] = useState(null); const [web3, setWeb3] = useState(null); - const setUserWallet = async () => { + const setUserMinAmount = useCallback( + async (address: string) => { + try { + // Try fetching the min amount from the API + const minAmount = await usewallet.openapi.getAccountMinFlow(address); + setMinAmount(minAmount); + } catch (error) { + // If there's an error, set the min amount to 0.001 + console.error('Error fetching min amount:', error); + setMinAmount(0.001); + } + }, + [usewallet] + ); + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const token = await usewallet.getCurrentCoin(); @@ -94,11 +105,24 @@ const SendEth = () => { setCoinList(coinList); const coinInfo = coinList.find((coin) => coin.unit.toLowerCase() === token.toLowerCase()); - coinInfo!.total = coinInfo!.balance * coinInfo!.price; + if ( + coinInfo?.balance && + coinInfo?.price && + !isNaN(coinInfo.balance) && + !isNaN(coinInfo.price) + ) { + coinInfo.total = + parseFloat(coinInfo.balance.toString()) * parseFloat(coinInfo.price.toString()); + } else { + console.error('Invalid balance or price in coinInfo'); + coinInfo!.total = 0; + } setCoinInfo(coinInfo!); const info = await usewallet.getUserInfo(false); const ct = await usewallet.getActiveWallet(); + + const userContact = { ...USER_CONTACT }; if (ct === 'evm') { userContact.address = withPrefix(wallet.address) || ''; } else { @@ -106,23 +130,11 @@ const SendEth = () => { } userContact.avatar = info.avatar; userContact.contact_name = info.username; - setUserMinAmount(); + setUserMinAmount(userContact.address); setUser(userContact); - }; + }, [setUserMinAmount, usewallet]); - const setUserMinAmount = async () => { - try { - // Try fetching the min amount from the API - const minAmount = await usewallet.openapi.getAccountMinFlow(userContact.address); - setMinAmount(minAmount); - } catch (error) { - // If there's an error, set the min amount to 0.001 - console.error('Error fetching min amount:', error); - setMinAmount(0.001); - } - }; - - const checkAddress = async () => { + const checkAddress = useCallback(async () => { const childType = await usewallet.getActiveWallet(); console.log(' childType ', childType); setChildType(childType); @@ -138,31 +150,31 @@ const SendEth = () => { setValidated(false); } setLoading(false); - }; + }, [setLoading, setValidated, location?.state?.contact?.address, usewallet]); const numberWithCommas = (x) => { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); }; - const updateCoinInfo = () => { + const updateCoinInfo = useCallback(() => { const coin = coinList.find((coin) => coin.unit.toLowerCase() === currentCoin.toLowerCase()); if (coin) { setCoinInfo(coin); } - }; + }, [coinList, currentCoin]); useEffect(() => { setUserWallet(); checkAddress(); - }, []); + }, [setUserWallet, checkAddress]); useEffect(() => { updateCoinInfo(); - }, [currentCoin]); + }, [currentCoin, updateCoinInfo]); return (
- + <> @@ -174,35 +186,34 @@ const SendEth = () => { isSend={true} /> - - {validated !== null && - (validated ? ( - <> - ) : ( + + {validated ? ( + <> + ) : ( + - - - - {chrome.i18n.getMessage('Invalid_address_in')} - {` ${network}`} - - + + + {chrome.i18n.getMessage('Invalid_address_in')} + {` ${network}`} + - ))} - + + )} + { /> )} - +
); }; diff --git a/src/ui/views/Send/TransferAmount.tsx b/src/ui/views/Send/TransferAmount.tsx index 348b2941..c98acac8 100644 --- a/src/ui/views/Send/TransferAmount.tsx +++ b/src/ui/views/Send/TransferAmount.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; import { Box, Typography, @@ -13,14 +13,16 @@ import { Chip, Tooltip, } from '@mui/material'; +import { StyledEngineProvider } from '@mui/material/styles'; import { makeStyles } from '@mui/styles'; +import BN from 'bignumber.js'; +import React, { useState, useEffect, useCallback } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; + +import CancelIcon from '../../../components/iconfont/IconClose'; import IconFlow from '../../../components/iconfont/IconFlow'; import IconSwitch from '../../../components/iconfont/IconSwitch'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; -import { StyledEngineProvider } from '@mui/material/styles'; -import BN from 'bignumber.js'; -import { Presets } from 'react-component-transition'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -141,13 +143,13 @@ const TransferAmount = ({ setCoinType(!coinType); }; - const currentCoinType = () => { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [currentCoinType]); useEffect(() => { if (coinType) { @@ -164,7 +166,7 @@ const TransferAmount = ({ setAmount(parseFloat(value.toFixed(3))); } } - }, [secondAmount]); + }, [coinInfo.balance, coinInfo.price, coinType, secondAmount, setAmount, setExceed]); useEffect(() => { if (!coinType) { @@ -183,7 +185,7 @@ const TransferAmount = ({ setSecondAmount(value); } } - }, [amount, coin]); + }, [amount, coin, coinInfo, coinType, setExceed, setSecondAmount]); return ( @@ -335,33 +337,31 @@ const TransferAmount = ({
- - {exceed && ( - + + + - - - {chrome.i18n.getMessage('Insufficient_balance') + - (coin === 'flow' - ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') - : '')} - - - )} - + {chrome.i18n.getMessage('Insufficient_balance') + + (coin === 'flow' + ? chrome.i18n.getMessage('on_Flow_the_balance_cant_less_than_0001_FLOW') + : '')} +
+
+
); diff --git a/src/ui/views/Send/TransferConfirmation.tsx b/src/ui/views/Send/TransferConfirmation.tsx index 4283556c..db42d399 100644 --- a/src/ui/views/Send/TransferConfirmation.tsx +++ b/src/ui/views/Send/TransferConfirmation.tsx @@ -2,14 +2,14 @@ import CloseIcon from '@mui/icons-material/Close'; import InfoIcon from '@mui/icons-material/Info'; import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; -import { Presets } from 'react-component-transition'; import { useHistory } from 'react-router-dom'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import IconNext from 'ui/FRWAssets/svg/next.svg'; -import { LLSpinner, LLProfile, FRWProfile } from 'ui/FRWComponent'; +import { LLSpinner, LLProfile, FRWProfile, FRWTargetProfile } from 'ui/FRWComponent'; import { useWallet, isEmoji } from 'ui/utils'; interface TransferConfirmationProps { @@ -38,6 +38,7 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { const { sufficient: isSufficient, sufficientAfterAction: isSufficientAfterAction } = useStorageCheck({ transferAmount, + coin: props.data?.coinInfo?.coin, movingBetweenEVMAndFlow, }); @@ -52,7 +53,7 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { '#41CC5D', '#41CC5D', ]; - const startCount = () => { + const startCount = useCallback(() => { let count = 0; let intervalId; if (props.data.contact.address) { @@ -66,14 +67,14 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { } else if (!props.data.contact.address) { clearInterval(intervalId); } - }; + }, [props.data.contact.address, setCount]); - const getPending = async () => { + const getPending = useCallback(async () => { const pending = await wallet.getPendingTx(); if (pending.length > 0) { setOccupied(true); } - }; + }, [wallet]); const updateOccupied = useCallback(() => { setOccupied(false); @@ -90,7 +91,6 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { } setSending(true); const amount = parseFloat(props.data.amount).toFixed(8); - // const txID = await wallet.transferTokens(props.data.tokenSymbol, props.data.contact.address, amount); wallet .transferInboxTokens(props.data.tokenSymbol, props.data.contact.address, amount) .then(async (txID) => { @@ -117,7 +117,6 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { const sendFromChild = async () => { const amount = parseFloat(props.data.amount).toFixed(8); - // const txID = await wallet.transferTokens(props.data.tokenSymbol, props.data.contact.address, amount); wallet .sendFTfromChild( props.data.userContact.address, @@ -185,7 +184,7 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { }; const transferFt = async () => { - const tokenResult = await wallet.openapi.getTokenInfo(props.data.tokenSymbol); + const tokenResult = await wallet.openapi.getEvmTokenInfo(props.data.tokenSymbol); console.log('tokenResult ', tokenResult, props.data.amount); wallet @@ -239,7 +238,7 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { return () => { chrome.runtime.onMessage.removeListener(transactionDoneHandler); }; - }, []); + }, [getPending, startCount, transactionDoneHandler]); const renderContent = () => ( { sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', py: '16px' }} > {props.data.childType === 'evm' ? ( - + ) : props.data.childType ? ( ) : ( - + )} { ))} {isEmoji(props.data.contact.avatar) ? ( - + ) : ( )} @@ -364,28 +368,26 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { - {occupied && ( - - - {/* */} - - - {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} + + + { size="large" sx={{ height: '50px', + width: '100%', borderRadius: '12px', textTransform: 'capitalize', display: 'flex', diff --git a/src/ui/views/Send/index.tsx b/src/ui/views/Send/index.tsx index 45fe2e72..c81a1cb3 100644 --- a/src/ui/views/Send/index.tsx +++ b/src/ui/views/Send/index.tsx @@ -1,4 +1,6 @@ -import React, { useState, useEffect } from 'react'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import SearchIcon from '@mui/icons-material/Search'; import { Box, InputBase, @@ -15,24 +17,24 @@ import { IconButton, Tooltip, } from '@mui/material'; -import { useWallet } from 'ui/utils'; -import { useTheme, styled } from '@mui/material/styles'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; -import SearchIcon from '@mui/icons-material/Search'; -import { useHistory } from 'react-router-dom'; -import AddressBookList from './AddressBookList'; -import AccountsList from './AccountsList'; -import SearchList from './SearchList'; -import RecentList from './RecentList'; -import { Contact } from 'background/service/networkModel'; -import { isEmpty } from 'lodash'; +import { useTheme, styled, StyledEngineProvider } from '@mui/material/styles'; import { makeStyles } from '@mui/styles'; -import { StyledEngineProvider } from '@mui/material/styles'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; +import { isEmpty } from 'lodash'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useHistory } from 'react-router-dom'; import SwipeableViews from 'react-swipeable-views'; + +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; +import { type Contact } from 'background/service/networkModel'; +import { useWallet } from 'ui/utils'; + import IconAbout from '../../../components/iconfont/IconAbout'; +import AccountsList from './AccountsList'; +import AddressBookList from './AddressBookList'; +import RecentList from './RecentList'; +import SearchList from './SearchList'; + export enum SendPageTabOptions { Recent = 'Recent', AddressBook = 'AddressBook', @@ -163,7 +165,7 @@ const Send = () => { const [searched, setSearched] = useState(false); const [hasNoFilteredContacts, setHasNoFilteredContacts] = useState(false); - const fetchAddressBook = async () => { + const fetchAddressBook = useCallback(async () => { await wallet.setDashIndex(0); try { const response = await wallet.getAddressBook(); @@ -202,11 +204,11 @@ const Send = () => { } catch (err) { console.log('err: ', err); } - }; + }, [wallet]); useEffect(() => { fetchAddressBook(); - }, []); + }, [fetchAddressBook]); const checkContain = (searchResult: Contact) => { if (sortedContacts.some((e) => e.contact_name === searchResult.username)) { @@ -403,8 +405,6 @@ const Send = () => { }; const handleClick = (eachgroup) => { - const history = useHistory(); - const isEvmAddress = isValidEthereumAddress(eachgroup.address); const pathname = isEvmAddress ? '/dashboard/wallet/sendEth' : '/dashboard/wallet/sendAmount'; diff --git a/src/ui/views/Setting/About/About.tsx b/src/ui/views/Setting/About/About.tsx index 3091ca2f..0babc923 100644 --- a/src/ui/views/Setting/About/About.tsx +++ b/src/ui/views/Setting/About/About.tsx @@ -1,14 +1,15 @@ +import { Typography, Box, CardMedia } from '@mui/material'; +import { makeStyles } from '@mui/styles'; import React from 'react'; import { useHistory } from 'react-router-dom'; -import { makeStyles } from '@mui/styles'; -import { Typography, Box, CardMedia } from '@mui/material'; -import twitter from 'ui/FRWAssets/image/twitter.png'; + +import packageJson from '@/../package.json'; +import { LLHeader } from '@/ui/FRWComponent'; import discord from 'ui/FRWAssets/image/discord.png'; -import X from 'ui/FRWAssets/svg/xLogo.svg'; import lilo from 'ui/FRWAssets/image/lilo.png'; -import { version } from '@/../package.json'; +import X from 'ui/FRWAssets/svg/xLogo.svg'; +const { version } = packageJson; // import '../../Unlock/style.css'; -import { LLHeader } from '@/ui/FRWComponent'; const useStyles = makeStyles(() => ({ arrowback: { @@ -135,7 +136,7 @@ const About = () => { - + ({ zIndex: 1, @@ -75,7 +75,7 @@ const EditAccount = (props: EditAccountProps) => { keepSubmitCount: true, } ); - }, [props.avatar, props.nickname]); + }, [props.avatar, props.nickname, reset]); const renderContent = () => ( { const history = useHistory(); const wallet = useWallet(); - const [claiming, setClaiming] = useState(false); const [username, setUsername] = useState(''); const [nickname, setNickname] = useState(''); const [isEdit, setEdit] = useState(false); const [avatar, setAvatar] = useState(''); const [modeAnonymous, setModeAnonymous] = useState(false); - const [domain, setDomain] = useState(''); - const [showPop, setShowPop] = useState(false); - - const handleClaiming = () => { - setClaiming(true); - }; - const getUsername = async () => { + const getUsername = useCallback(async () => { const userInfo = await wallet.getUserInfo(false); setUsername(userInfo.username); setNickname(userInfo.nickname); setAvatar(userInfo.avatar); - }; - - const updatePreference = async (modeAnonymous) => { - if (modeAnonymous) { - await wallet.updateProfilePreference(2); - } else { - await wallet.updateProfilePreference(1); - } - await getAnonymousMode(); - }; + }, [wallet]); const toggleEdit = () => { setEdit(!isEdit); }; - const getAnonymousMode = async () => { + const getAnonymousMode = useCallback(async () => { // const domain = await wallet.fetchUserDomain(); // if (domain) { // setDomain(domain); @@ -142,21 +121,33 @@ const Flowns = () => { } else { setModeAnonymous(true); } - }; + }, [wallet]); - const refreshUsername = async () => { + const updatePreference = useCallback( + async (modeAnonymous) => { + if (modeAnonymous) { + await wallet.updateProfilePreference(2); + } else { + await wallet.updateProfilePreference(1); + } + await getAnonymousMode(); + }, + [getAnonymousMode, wallet] + ); + + const refreshUsername = useCallback(async () => { const userInfo = await wallet.getUserInfo(true); setUsername(userInfo.username); - }; + }, [wallet]); - const switchAnonymousMode = async () => { + const switchAnonymousMode = useCallback(async () => { await updatePreference(!modeAnonymous); - }; + }, [updatePreference, modeAnonymous]); useEffect(() => { getAnonymousMode(); getUsername(); - }, []); + }, [getAnonymousMode, getUsername]); return (
@@ -263,9 +254,11 @@ const Flowns = () => { )} - { switchAnonymousMode(); }} @@ -286,26 +279,26 @@ const Flowns = () => { {username}.meow - } */} {/* {showPop && - - { {chrome.i18n.getMessage('Claim__for__your')} ({ zIndex: 1, diff --git a/src/ui/views/Setting/DeveloperMode/DeveloperMode.tsx b/src/ui/views/Setting/DeveloperMode/DeveloperMode.tsx index 675c9e8f..8cf99c5f 100644 --- a/src/ui/views/Setting/DeveloperMode/DeveloperMode.tsx +++ b/src/ui/views/Setting/DeveloperMode/DeveloperMode.tsx @@ -1,8 +1,6 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router-dom'; -import { styled } from '@mui/system'; -import SwitchUnstyled, { switchUnstyledClasses } from '@mui/core/SwitchUnstyled'; -import { makeStyles } from '@mui/styles'; +import { Switch, switchClasses } from '@mui/base/Switch'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined'; import { Box, Typography, @@ -10,19 +8,15 @@ import { CardActionArea, Divider, FormControlLabel, - Alert, - Snackbar, - CircularProgress, + Fade, } from '@mui/material'; -import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined'; -import { useWallet } from 'ui/utils'; +import { makeStyles } from '@mui/styles'; +import { styled } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; + import { storage } from '@/background/webapi'; -import { LLHeader, LLPrimaryButton } from '@/ui/FRWComponent'; -import { Presets } from 'react-component-transition'; -import { nanoid } from 'nanoid'; -import { Message } from 'utils'; -import { v4 as uuid } from 'uuid'; +import { LLHeader } from '@/ui/FRWComponent'; +import { useWallet } from 'ui/utils'; const useStyles = makeStyles(() => ({ arrowback: { @@ -114,13 +108,13 @@ const Root = styled('span')( // margin: 0; margin-left: auto; cursor: pointer; - - &.${switchUnstyledClasses.disabled} { + + &.${switchClasses.disabled} { opacity: 0.4; cursor: not-allowed; } - - & .${switchUnstyledClasses.track} { + + & .${switchClasses.track} { background: ${theme.palette.mode === 'dark' ? grey[600] : grey[400]}; border-radius: 10px; display: block; @@ -128,8 +122,8 @@ const Root = styled('span')( width: 100%; position: absolute; } - - & .${switchUnstyledClasses.thumb} { + + & .${switchClasses.thumb} { display: block; width: 14px; height: 14px; @@ -140,25 +134,25 @@ const Root = styled('span')( position: relative; transition: all 200ms ease; } - - &.${switchUnstyledClasses.focusVisible} .${switchUnstyledClasses.thumb} { + + &.${switchClasses.focusVisible} .${switchClasses.thumb} { background-color: ${grey[500]}; box-shadow: 0 0 1px 8px rgba(0, 0, 0, 0.25); } - - &.${switchUnstyledClasses.checked} { - .${switchUnstyledClasses.thumb} { + + &.${switchClasses.checked} { + .${switchClasses.thumb} { left: 22px; top: 3px; background-color: #fff; } - - .${switchUnstyledClasses.track} { + + .${switchClasses.track} { background: ${orange[500]}; } } - - & .${switchUnstyledClasses.input} { + + & .${switchClasses.input} { cursor: inherit; position: absolute; width: 100%; @@ -175,18 +169,11 @@ const Root = styled('span')( const DeveloperMode = () => { const usewallet = useWallet(); const classes = useStyles(); - const history = useHistory(); const [modeOn, setModeOn] = useState(false); - const [scriptElement, setScriptElement] = useState(null); - const [injectMode, setInjectMode] = useState(false); const [currentNetwork, setNetwork] = useState('mainnet'); const [currentMonitor, setMonitor] = useState('flowscan'); - const [loading, setLoading] = useState(false); - - const [showError, setShowError] = useState(false); - - const loadNetwork = async () => { + const loadNetwork = useCallback(async () => { const network = await usewallet.getNetwork(); // const crescendo = await usewallet.checkCrescendo(); // if (crescendo.length > 0) { @@ -194,12 +181,12 @@ const DeveloperMode = () => { // } setNetwork(network); - }; + }, [usewallet]); - const loadMonitor = async () => { + const loadMonitor = useCallback(async () => { const monitor = await usewallet.getMonitor(); setMonitor(monitor); - }; + }, [usewallet]); const loadDeveloperMode = async () => { const developerMode = await storage.get('developerMode'); @@ -212,7 +199,7 @@ const DeveloperMode = () => { loadDeveloperMode(); loadNetwork(); loadMonitor(); - }, []); + }, [loadMonitor, loadNetwork]); const switchNetwork = async (network: string) => { // if (network === 'crescendo' && !isSandboxEnabled) { @@ -224,7 +211,6 @@ const DeveloperMode = () => { if (currentNetwork !== network) { // TODO: replace it with better UX - window.location.reload(); } }; @@ -239,87 +225,6 @@ const DeveloperMode = () => { storage.set('developerMode', !modeOn); }; - // const channelName = nanoid(); - - // const injectProviderScript = async (isDefaultWallet) => { - // await localStorage.setItem('frw:channelName', channelName); - // await localStorage.setItem('frw:isDefaultWallet', isDefaultWallet); - // await localStorage.setItem('frw:uuid', uuid()); - - // console.log(localStorage.getItem('frw:channelName')); - - // const container = document.head || document.documentElement; - // const scriptElement = document.createElement('script'); - - // scriptElement.id = "injectedScript"; - // scriptElement.setAttribute('src', chrome.runtime.getURL('pageProvider.js')); - - // container.insertBefore(scriptElement, container.children[0]); - - // return scriptElement; - // }; - - // const switchInject = async () => { - // const injectStatus = await localStorage.getItem('frw:injectSetting'); - // const newInjectMode = injectStatus !== 'true'; - // console.log('newInjectMode ', newInjectMode); - // setInjectMode(newInjectMode); - // await localStorage.setItem('frw:injectSetting', newInjectMode ? 'true' : 'false'); - - // chrome.tabs.query({ url: ["http://*/*", "https://*/*"] }, (tabs) => { - - // tabs.forEach((tab) => { - // if (!tab.id) { - // console.error('No tab ID available'); - // return; - // } - // if (newInjectMode) { - // chrome.scripting.executeScript({ - // target: { tabId: tab.id }, - // files: ["content-script.js"], - // }).catch((error) => console.error('Error injecting script:', error)); - // } else { - // chrome.scripting.executeScript({ - // target: { tabId: tab.id }, - // func: removeInjectedScript, - // }).catch((error) => console.error('Error removing script:', error)); - // } - // }); - // }); - // }; - - // function removeInjectedScript() { - // const scriptElement = document.getElementById("injectedScript"); - // if (scriptElement) { - // scriptElement.remove(); - // } - // localStorage.removeItem('frw:channelName'); - // localStorage.removeItem('frw:isDefaultWallet'); - // localStorage.removeItem('frw:uuid'); - // } - - // useEffect(() => { - // const initializeInjectMode = async () => { - // const injectStatus = await localStorage.getItem('frw:injectSetting'); - // const initialInjectMode = injectStatus === 'true'; - // setInjectMode(initialInjectMode); - - // if (initialInjectMode) { - // const script = await injectProviderScript(true); - // setScriptElement(script); - // } - // }; - - // initializeInjectMode(); - // }, []); - - const handleErrorClose = (event?: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway') { - return; - } - setShowError(false); - }; - return (
@@ -328,206 +233,175 @@ const DeveloperMode = () => { {chrome.i18n.getMessage('Developer__Mode')} - { switchDeveloperMode(); }} /> - - - {modeOn && ( - - + + + {chrome.i18n.getMessage('Switch__Network')} + + + switchNetwork('mainnet')} > - {chrome.i18n.getMessage('Switch__Network')} - - - switchNetwork('mainnet')} - > - - } - checkedIcon={} - value="mainnet" - checked={currentNetwork === 'mainnet'} - onChange={() => switchNetwork('mainnet')} - /> - } - /> - - {currentNetwork === 'mainnet' && ( - - {chrome.i18n.getMessage('Selected')} - - )} - - - - - - switchNetwork('testnet')} - > - - } - checkedIcon={} - value="testnet" - checked={currentNetwork === 'testnet'} - onChange={() => switchNetwork('testnet')} - /> - } - /> - - {currentNetwork === 'testnet' && ( - - {chrome.i18n.getMessage('Selected')} - - )} - - - - - + } + checkedIcon={} + value="mainnet" + checked={currentNetwork === 'mainnet'} + onChange={() => switchNetwork('mainnet')} + /> + } + /> + + {currentNetwork === 'mainnet' && ( + + {chrome.i18n.getMessage('Selected')} + + )} + + + + + + switchNetwork('testnet')} + > + + } + checkedIcon={} + value="testnet" + checked={currentNetwork === 'testnet'} + onChange={() => switchNetwork('testnet')} + /> + } + /> + + {currentNetwork === 'testnet' && ( + + {chrome.i18n.getMessage('Selected')} + + )} + + + + + + {chrome.i18n.getMessage('Transaction__Monitor')} + + + switchMonitor('flowscan')} > - {chrome.i18n.getMessage('Transaction__Monitor')} - - - switchMonitor('flowscan')} - > - - } - checkedIcon={} - value="flowscan" - checked={currentMonitor === 'flowscan'} - onChange={() => switchMonitor('flowscan')} - /> - } - /> - - {currentMonitor === 'flowscan' && ( - - {chrome.i18n.getMessage('Selected')} - - )} - - - - - - switchMonitor('source')} - > - - } - checkedIcon={} - value="flowViewSource" - checked={currentMonitor === 'source'} - onChange={() => switchMonitor('source')} - /> - } - /> - - {currentMonitor === 'source' && ( - - {chrome.i18n.getMessage('Selected')} - - )} - - - - {/* - - + } + checkedIcon={} + value="flowscan" + checked={currentMonitor === 'flowscan'} + onChange={() => switchMonitor('flowscan')} + /> + } + /> + + {currentMonitor === 'flowscan' && ( + + {chrome.i18n.getMessage('Selected')} + + )} + + + + + + switchMonitor('source')} > - {chrome.i18n.getMessage('EVM_on_flow')} - - - - - - Inject EVM dApp - - { - switchInject(); - }} - /> */} - + + } + checkedIcon={} + value="flowViewSource" + checked={currentMonitor === 'source'} + onChange={() => switchMonitor('source')} + /> + } + /> + + {currentMonitor === 'source' && ( + + {chrome.i18n.getMessage('Selected')} + + )} + + - )} - + +
); }; diff --git a/src/ui/views/Setting/Devices/DeviceInfo.tsx b/src/ui/views/Setting/Devices/DeviceInfo.tsx index 51d7bddc..b0db06a9 100644 --- a/src/ui/views/Setting/Devices/DeviceInfo.tsx +++ b/src/ui/views/Setting/Devices/DeviceInfo.tsx @@ -1,48 +1,32 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router-dom'; -import { styled } from '@mui/system'; -import SwitchUnstyled, { switchUnstyledClasses } from '@mui/core/SwitchUnstyled'; -import { makeStyles } from '@mui/styles'; -import { - Box, - Typography, - Checkbox, - CardActionArea, - Divider, - FormControlLabel, - Alert, - Snackbar, -} from '@mui/material'; -import { useWallet } from 'ui/utils'; -import { LLHeader, LLPrimaryButton } from '@/ui/FRWComponent'; +import { Box, Typography } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; import { useLocation } from 'react-router-dom'; +import { LLHeader } from '@/ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + interface LocationState { deviceItem?: any; } const DeviceInfo = () => { - const usewallet = useWallet(); - const history = useHistory(); - - const [showError, setShowError] = useState(false); const location = useLocation(); const wallet = useWallet(); const [devices, setDevices] = useState({}); - const getDevice = async () => { + const getDevice = useCallback(async () => { const deviceItem = location.state?.deviceItem; setDevices(deviceItem); - }; + }, [location.state?.deviceItem]); - const setTab = async () => { + const setTab = useCallback(async () => { await wallet.setDashIndex(3); - }; + }, [wallet]); useEffect(() => { setTab(); getDevice(); - }, []); + }, [getDevice, setTab]); const formatDate = (dateString) => { const months = [ diff --git a/src/ui/views/Setting/Devices/Devices.tsx b/src/ui/views/Setting/Devices/Devices.tsx index fe6af216..ddf7fc62 100644 --- a/src/ui/views/Setting/Devices/Devices.tsx +++ b/src/ui/views/Setting/Devices/Devices.tsx @@ -1,78 +1,48 @@ -import React, { useState, useEffect } from 'react'; +import { Box, Typography } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { styled } from '@mui/system'; -import SwitchUnstyled, { switchUnstyledClasses } from '@mui/core/SwitchUnstyled'; -import { makeStyles } from '@mui/styles'; -import { - Box, - Typography, - Checkbox, - CardActionArea, - Divider, - FormControlLabel, - Alert, - Snackbar, -} from '@mui/material'; + +import { LLHeader } from '@/ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { LLHeader, LLPrimaryButton } from '@/ui/FRWComponent'; -import Pc from '../../../FRWAssets/image/pc.png'; -import Mobile from '../../../FRWAssets/image/mobile.png'; + import circlecheck from '../../../FRWAssets/image/circlecheck.png'; import goto from '../../../FRWAssets/image/goto.png'; +import Mobile from '../../../FRWAssets/image/mobile.png'; +import Pc from '../../../FRWAssets/image/pc.png'; import QR from '../../../FRWAssets/image/QR2.png'; + import WalletConnect from './WalletConnect'; const Devices = () => { const usewallet = useWallet(); const history = useHistory(); - const [showError, setShowError] = useState(false); - const wallet = useWallet(); - const [privatekey, setKey] = useState(''); - const [publickey, setPublicKey] = useState(''); - const [showKey, setShowkey] = useState(null); const [devices, setDevices] = useState([]); const [currentId, setCurrentId] = useState(''); const [qrCode, setShowQr] = useState(false); - const getDevice = async () => { + const getDevice = useCallback(async () => { const installationId = await usewallet.openapi.getInstallationId(); - console.log(' installationId ', installationId); setCurrentId(installationId); const devices = await usewallet.openapi.deviceList(); if (devices.data) { setDevices(devices.data); } - }; + }, [usewallet]); - const setTab = async () => { + const setTab = useCallback(async () => { await wallet.setDashIndex(3); - }; - - const toggleKey = async (index) => { - if (showKey === index) { - setShowkey(null); - } else { - setShowkey(index); - } - }; + }, [wallet]); - const toggleQr = async () => { + const toggleQr = useCallback(async () => { setShowQr(true); - }; + }, []); useEffect(() => { setTab(); getDevice(); - }, []); - - const handleErrorClose = (event?: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway') { - return; - } - setShowError(false); - }; + }, [getDevice, setTab]); return (
@@ -117,7 +87,7 @@ const Devices = () => { sx={{ width: '339px', height: '1px', backgroundColor: 'rgba(255, 255, 255, 0.12)' }} > {devices - .sort((a, b) => (a.id === currentId ? -1 : 1)) + .sort((a, _b) => (a.id === currentId ? -1 : 1)) .map((item, index) => ( { {chrome.i18n.getMessage('Current_Sessions')} )} - {index == 1 && ( + {index === 1 && ( { > diff --git a/src/ui/views/Setting/Devices/WalletConnect.tsx b/src/ui/views/Setting/Devices/WalletConnect.tsx index c19abdb0..9da8bde8 100644 --- a/src/ui/views/Setting/Devices/WalletConnect.tsx +++ b/src/ui/views/Setting/Devices/WalletConnect.tsx @@ -1,11 +1,4 @@ -import React, { useState, useEffect } from 'react'; -import { Core } from '@walletconnect/core'; -import { Web3Wallet, Web3WalletTypes } from '@walletconnect/web3wallet'; -import { formatJsonRpcResult } from '@walletconnect/jsonrpc-utils'; -import { getSdkError } from '@walletconnect/utils'; -import { DeviceInfo, DeviceInfoRequest, AccountKey } from 'background/service/networkModel'; -import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; - +import SearchIcon from '@mui/icons-material/Search'; import { Typography, Box, @@ -18,16 +11,29 @@ import { Stack, Divider, } from '@mui/material'; -import SearchIcon from '@mui/icons-material/Search'; import { styled } from '@mui/material/styles'; +import { Core } from '@walletconnect/core'; +import { formatJsonRpcResult } from '@walletconnect/jsonrpc-utils'; +import { getSdkError } from '@walletconnect/utils'; +import { Web3Wallet, type Web3WalletTypes } from '@walletconnect/web3wallet'; +import React, { useState, useEffect } from 'react'; +import { useForm, FieldValues } from 'react-hook-form'; +import { useHistory } from 'react-router-dom'; + import { FCLWalletConnectMethod } from '@/ui/utils/type'; +import { + type DeviceInfo, + type DeviceInfoRequest, + type AccountKey, +} from 'background/service/networkModel'; +import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { useForm, FieldValues } from 'react-hook-form'; -import micone from '../../../FRWAssets/image/micone.png'; -import licon from '../../../FRWAssets/image/licon.png'; -import dicon from '../../../FRWAssets/image/dicon.png'; + import closeCircle from '../../../FRWAssets/image/closeCircle.png'; -import { useHistory } from 'react-router-dom'; +import dicon from '../../../FRWAssets/image/dicon.png'; +import licon from '../../../FRWAssets/image/licon.png'; +import micone from '../../../FRWAssets/image/micone.png'; + import QrScannerComponent from './QrScannerComponent'; const StyledInput = styled(InputBase)(({ theme }) => ({ @@ -79,7 +85,6 @@ const WalletConnect = (props: RevokePageProps) => { const createWeb3Wallet = async () => { try { const wallet = await Web3Wallet.init({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Unreachable code error core: new Core({ projectId: process.env.WC_PROJECTID, diff --git a/src/ui/views/Setting/KeyList/RevokePage.tsx b/src/ui/views/Setting/KeyList/RevokePage.tsx index 5a1531db..0e116115 100644 --- a/src/ui/views/Setting/KeyList/RevokePage.tsx +++ b/src/ui/views/Setting/KeyList/RevokePage.tsx @@ -1,13 +1,15 @@ -import React, { useState, useEffect } from 'react'; import { Typography, Box, Drawer, Grid, Stack, InputBase, CircularProgress } from '@mui/material'; import { styled } from '@mui/material/styles'; -import { LLPrimaryButton } from '../../../FRWComponent'; -import { useWallet } from 'ui/utils'; +import React, { useState, useEffect } from 'react'; import { useForm, FieldValues } from 'react-hook-form'; -import warning from '../../../FRWAssets/image/warning.png'; -import closeCircle from '../../../FRWAssets/image/closeCircle.png'; import { useHistory } from 'react-router-dom'; +import { useWallet } from 'ui/utils'; + +import closeCircle from '../../../FRWAssets/image/closeCircle.png'; +import warning from '../../../FRWAssets/image/warning.png'; +import { LLPrimaryButton } from '../../../FRWComponent'; + const StyledInput = styled(InputBase)(({ theme }) => ({ zIndex: 1, color: (theme.palette as any).text, diff --git a/src/ui/views/Setting/Linked/LinkedCollection.tsx b/src/ui/views/Setting/Linked/LinkedCollection.tsx index 211b3278..6e01df6e 100644 --- a/src/ui/views/Setting/Linked/LinkedCollection.tsx +++ b/src/ui/views/Setting/Linked/LinkedCollection.tsx @@ -1,6 +1,7 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import { makeStyles } from '@mui/styles'; -import { StyledEngineProvider } from '@mui/material/styles'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import PublicOutlinedIcon from '@mui/icons-material/PublicOutlined'; +import ReplayRoundedIcon from '@mui/icons-material/ReplayRounded'; +import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined'; import { Typography, Card, @@ -14,19 +15,20 @@ import { ButtonBase, Tooltip, } from '@mui/material'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import PublicOutlinedIcon from '@mui/icons-material/PublicOutlined'; -import StorefrontOutlinedIcon from '@mui/icons-material/StorefrontOutlined'; +import { StyledEngineProvider } from '@mui/material/styles'; +import { makeStyles } from '@mui/styles'; +import { has } from 'lodash'; +import React, { useState, useEffect, useCallback } from 'react'; +import InfiniteScroll from 'react-infinite-scroll-component'; import { useHistory, useParams, useLocation } from 'react-router-dom'; + import { storage } from '@/background/webapi'; +import { LLSpinner } from '@/ui/FRWComponent'; +import { type PostMedia, MatchMediaType } from '@/ui/utils/url'; import { useWallet } from 'ui/utils'; + import GridView from '../../NFT/GridView'; // import InfiniteScroll from 'react-infinite-scroller'; -import InfiniteScroll from 'react-infinite-scroll-component'; -import { LLSpinner } from '@/ui/FRWComponent'; -import { has } from 'lodash'; -import ReplayRoundedIcon from '@mui/icons-material/ReplayRounded'; -import { PostMedia, MatchMediaType } from '@/ui/utils/url'; interface CollectionDisplay { name: string; @@ -194,7 +196,14 @@ const LinkedCollection = (props) => { const collection_name = collection_info[1]; const nftCount = collection_info[2]; - const fetchCollection = async () => { + const getCollection = useCallback( + async (ownerAddress, collection, offset = 0) => { + return await usewallet.getSingleCollection(ownerAddress, collection, offset); + }, + [usewallet] + ); + + const fetchCollection = useCallback(async () => { // const { collection, ownerAddress } = await getInfo(); setOwnerAddress(address); setLoading(true); @@ -211,7 +220,7 @@ const LinkedCollection = (props) => { } finally { setLoading(false); } - }; + }, [address, collection_name, getCollection]); const nextPage = async () => { if (loadingMore) { @@ -244,16 +253,12 @@ const LinkedCollection = (props) => { } }; - const getCollection = async (ownerAddress, collection, offset = 0) => { - return await usewallet.getSingleCollection(ownerAddress, collection, offset); - }; - function truncate(str, n) { return str.length > n ? str.slice(0, n - 1) + '...' : str; } const hasMore = (): boolean => { - if (list && list.length == 0) { + if (list && list.length === 0) { return true; } return list.length < total; @@ -267,7 +272,7 @@ const LinkedCollection = (props) => { useEffect(() => { fetchCollection(); - }, []); + }, [fetchCollection]); const createGridCard = (data, index) => { return ( @@ -427,7 +432,9 @@ const LinkedCollection = (props) => { > {list && list.map(createGridCard)} - {list.length % 2 != 0 && } + {list.length % 2 !== 0 && ( + + )} ) diff --git a/src/ui/views/Setting/Linked/LinkedDetail.tsx b/src/ui/views/Setting/Linked/LinkedDetail.tsx index 3b7ead5a..b02ba8c1 100644 --- a/src/ui/views/Setting/Linked/LinkedDetail.tsx +++ b/src/ui/views/Setting/Linked/LinkedDetail.tsx @@ -1,6 +1,6 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory, useParams } from 'react-router-dom'; -import { makeStyles } from '@mui/styles'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined'; +import EditRoundedIcon from '@mui/icons-material/EditRounded'; import { Typography, IconButton, @@ -18,20 +18,24 @@ import { FormControlLabel, Checkbox, } from '@mui/material'; -import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; -import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined'; -import IconCopy from '../../../../components/iconfont/IconCopy'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useHistory, useParams } from 'react-router-dom'; + +import { LLSecondaryButton } from '@/ui/FRWComponent'; +import { type UserInfoResponse } from 'background/service/networkModel'; +import placeholder from 'ui/FRWAssets/image/placeholder.png'; import IconNext from 'ui/FRWAssets/svg/nextgray.svg'; -import { Link } from 'react-router-dom'; import { useWallet } from 'ui/utils'; + +import CheckCircleIcon from '../../../../components/iconfont/IconCheckmark'; +import IconCopy from '../../../../components/iconfont/IconCopy'; + // import '../../Unlock/style.css'; -import { LLSecondaryButton } from '@/ui/FRWComponent'; -import { UserInfoResponse } from 'background/service/networkModel'; -import UnlinkAccount from './UnlinkAccount'; + import EditAccount from './EditAccount'; -import EditRoundedIcon from '@mui/icons-material/EditRounded'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import placeholder from 'ui/FRWAssets/image/placeholder.png'; +import UnlinkAccount from './UnlinkAccount'; + // import fetchRemoteConfig from 'background/utils/remoteConfig'; type ChildAccount = { @@ -70,6 +74,26 @@ interface Collection { nfts: any[]; } +const extractContractName = (collection) => { + return collection.split('.')[2]; +}; + +const findObjectByContractName = (contractName, collections) => { + const extractedContract = extractContractName(contractName); + const foundObject = collections.find((item) => item.contract_name === extractedContract); + return foundObject || null; +}; + +const checkContractAddressInCollections = (nft, activec) => { + const matchedResult = activec.find((collection) => { + const parts = nft.split('.'); + const address = `0x${parts[1]}`; + const contractName = parts[2]; + return collection.address === address && collection.contract_name === contractName; + }); + return matchedResult; +}; + const LinkedDetail = () => { const location = useParams(); @@ -93,7 +117,7 @@ const LinkedDetail = () => { setValue(newValue); }; - const fetchUserWallet = async () => { + const fetchUserWallet = useCallback(async () => { try { const childresp = await usewallet.checkUserChildAccount(); const isChild = await usewallet.getActiveWallet(); @@ -145,34 +169,14 @@ const LinkedDetail = () => { console.error('Error fetching data:', error); setLoading(false); } - }; - - const extractContractName = (collection) => { - return collection.split('.')[2]; - }; - - const findObjectByContractName = (contractName, collections) => { - const extractedContract = extractContractName(contractName); - const foundObject = collections.find((item) => item.contract_name === extractedContract); - return foundObject || null; - }; - - const checkContractAddressInCollections = (nft, activec) => { - const matchedResult = activec.find((collection) => { - const parts = nft.split('.'); - const address = `0x${parts[1]}`; - const contractName = parts[2]; - return collection.address === address && collection.contract_name == contractName; - }); - return matchedResult; - }; + }, [usewallet, location]); const [userInfo, setUserInfo] = useState(null); - const getUserInfo = async () => { + const getUserInfo = useCallback(async () => { const userResult = await usewallet.getUserInfo(false); await setUserInfo(userResult); - }; + }, [usewallet]); const showUnlink = async (condition) => { await setUnlinking(condition); @@ -206,7 +210,7 @@ const LinkedDetail = () => { useEffect(() => { getUserInfo(); fetchUserWallet(); - }, []); + }, [getUserInfo, fetchUserWallet]); const nftContent = () => { const filteredNftCollection = availableNftCollection.filter( diff --git a/src/ui/views/Setting/Linked/UnlinkAccount.tsx b/src/ui/views/Setting/Linked/UnlinkAccount.tsx index 4974f941..b7f44154 100644 --- a/src/ui/views/Setting/Linked/UnlinkAccount.tsx +++ b/src/ui/views/Setting/Linked/UnlinkAccount.tsx @@ -1,13 +1,15 @@ -import React, { useState, useEffect } from 'react'; -import { makeStyles } from '@mui/styles'; +import CloseIcon from '@mui/icons-material/Close'; import { Box, Drawer, Grid, Typography, Stack, InputBase } from '@mui/material'; import { styled } from '@mui/material/styles'; -import CloseIcon from '@mui/icons-material/Close'; -import { LLPrimaryButton, LLSecondaryButton, LLSpinner } from '../../../FRWComponent'; -import { useWallet } from 'ui/utils'; -import { useForm, FieldValues } from 'react-hook-form'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect } from 'react'; +import { useForm, type FieldValues } from 'react-hook-form'; import { useHistory } from 'react-router-dom'; + import UnlinkSVG from 'ui/FRWAssets/svg/unlink.svg'; +import { useWallet } from 'ui/utils'; + +import { LLPrimaryButton, LLSecondaryButton, LLSpinner } from '../../../FRWComponent'; const useStyles = makeStyles(() => ({ IconCheck: { diff --git a/src/ui/views/Setting/Resetpwd.tsx b/src/ui/views/Setting/Resetpwd.tsx index 71858a68..1fb82aae 100644 --- a/src/ui/views/Setting/Resetpwd.tsx +++ b/src/ui/views/Setting/Resetpwd.tsx @@ -1,21 +1,27 @@ -import React, { useEffect, useState } from 'react'; -import { Link } from 'react-router-dom'; -import Box from '@mui/material/Box'; -import { Typography, Button } from '@mui/material'; -import { useHistory } from 'react-router-dom'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import { Input, InputAdornment } from '@mui/material'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import { makeStyles } from '@mui/styles'; -import { IconButton } from '@mui/material'; -import { FormGroup, LinearProgress } from '@mui/material'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import { + FormGroup, + LinearProgress, + IconButton, + Input, + InputAdornment, + Typography, + Button, +} from '@mui/material'; +import Box from '@mui/material/Box'; +import { makeStyles } from '@mui/styles'; +import React, { useCallback, useEffect, useState } from 'react'; +import { Link, useHistory } from 'react-router-dom'; import zxcvbn from 'zxcvbn'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { useWallet } from 'ui/utils'; +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; + const useStyles = makeStyles(() => ({ customInputLabel: { '& legend': { @@ -122,14 +128,14 @@ const Resetpassword = () => { const [isSame, setSame] = useState(false); const history = useHistory(); - const verify = async () => { + const verify = useCallback(async () => { await wallet.getCurrentPassword(confirmcurrentPassword); setSame(true); - }; + }, [confirmcurrentPassword, wallet]); useEffect(() => { verify(); - }, [confirmcurrentPassword]); + }, [confirmcurrentPassword, verify]); const successInfo = (message) => { return ( @@ -322,7 +328,9 @@ const Resetpassword = () => { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + { // console.log('props.loggedInAccounts', props.current) - const requestChildType = async () => { + const requestChildType = useCallback(async () => { setSelectEmoji(props.emoji); - }; + }, [props.emoji]); const changeProfile = async () => { const address = props.userWallet[0].blockchain[0].address; @@ -51,7 +52,7 @@ const EditProfile = (props: MoveBoardProps) => { if (isValidEthereumAddress(address)) { childType = 'evm'; } - await usewallet.setEmoji(selectedEmoji, childType); + await usewallet.setEmoji(selectedEmoji, childType, props.userWallet[0].blockchain[0].id); setSelectEmoji(selectedEmoji); updateEmojis(); props.updateProfileEmoji(selectedEmoji); @@ -64,7 +65,7 @@ const EditProfile = (props: MoveBoardProps) => { useEffect(() => { requestChildType(); - }, [props.emoji]); + }, [props.emoji, requestChildType]); return ( ({ arrowback: { @@ -111,16 +113,16 @@ const RemoveWallet = ({ hideBackButton = false }) => { const [walletList, setWalletList] = useState([]); - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { const userInfo = await usewallet.getUserInfo(true); const wallet = await usewallet.getUserWallets(); await setWallet(wallet); await setUserInfo(userInfo); - }; + }, [usewallet]); useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); useEffect(() => { const list = wallets(userWallet); diff --git a/src/ui/views/Setting/Wallet/WalletDetail.tsx b/src/ui/views/Setting/Wallet/WalletDetail.tsx index d6c2a75c..2830affb 100644 --- a/src/ui/views/Setting/Wallet/WalletDetail.tsx +++ b/src/ui/views/Setting/Wallet/WalletDetail.tsx @@ -1,7 +1,4 @@ -import React, { useState, useEffect } from 'react'; -import { makeStyles } from '@mui/styles'; -import { useHistory } from 'react-router-dom'; -import { Link } from 'react-router-dom'; +import { Switch, switchClasses } from '@mui/base/Switch'; import { Typography, Box, @@ -16,16 +13,21 @@ import { Snackbar, CardMedia, } from '@mui/material'; -import IconEnd from '../../../../components/iconfont/IconAVector11Stroke'; -import { useWallet } from 'ui/utils'; -import { StorageInfo, UserInfoResponse } from 'background/service/networkModel'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; -import { LLHeader } from '@/ui/FRWComponent'; +import LinearProgress from '@mui/material/LinearProgress'; +import { makeStyles } from '@mui/styles'; import { styled } from '@mui/system'; -import SwitchUnstyled, { switchUnstyledClasses } from '@mui/core/SwitchUnstyled'; +import React, { useState, useEffect, useCallback } from 'react'; +import { Link } from 'react-router-dom'; + import { storage } from '@/background/webapi'; -import LinearProgress, { LinearProgressProps } from '@mui/material/LinearProgress'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; +import { LLHeader } from '@/ui/FRWComponent'; +import type { StorageInfo } from 'background/service/networkModel'; +import { useWallet } from 'ui/utils'; + +import IconEnd from '../../../../components/iconfont/IconAVector11Stroke'; import editEmoji from '../../../FRWAssets/svg/editEmoji.svg'; + import EditProfile from './EditProfile'; const useStyles = makeStyles(() => ({ @@ -147,13 +149,13 @@ const Root = styled('span')( // margin: 0; margin-left: auto; cursor: pointer; - - &.${switchUnstyledClasses.disabled} { + + &.${switchClasses.disabled} { opacity: 0.4; cursor: not-allowed; } - - & .${switchUnstyledClasses.track} { + + & .${switchClasses.track} { background: ${theme.palette.mode === 'dark' ? grey[600] : grey[400]}; border-radius: 10px; display: block; @@ -161,8 +163,8 @@ const Root = styled('span')( width: 100%; position: absolute; } - - & .${switchUnstyledClasses.thumb} { + + & .${switchClasses.thumb} { display: block; width: 14px; height: 14px; @@ -173,25 +175,25 @@ const Root = styled('span')( position: relative; transition: all 200ms ease; } - - &.${switchUnstyledClasses.focusVisible} .${switchUnstyledClasses.thumb} { + + &.${switchClasses.focusVisible} .${switchClasses.thumb} { background-color: ${grey[500]}; box-shadow: 0 0 1px 8px rgba(0, 0, 0, 0.25); } - - &.${switchUnstyledClasses.checked} { - .${switchUnstyledClasses.thumb} { + + &.${switchClasses.checked} { + .${switchClasses.thumb} { left: 17px; top: 3px; background-color: #fff; } - - .${switchUnstyledClasses.track} { + + .${switchClasses.track} { background: ${orange[500]}; } } - - & .${switchUnstyledClasses.input} { + + & .${switchClasses.input} { cursor: inherit; position: absolute; width: 100%; @@ -211,20 +213,31 @@ const tempEmoji = { bgcolor: '#FFE4C4', }; +function formatBytes(bytes, decimals = 2) { + if (bytes === 0) return '0 Bytes'; + const k = 1000; + const dm = decimals < 0 ? 0 : decimals; + const sizes = ['', 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; +} + +function formatStorageInfo(used: number | undefined, capacity: number | undefined) { + return `${formatBytes((used || 0) * 10)} / ${formatBytes((capacity || 0) * 10)}`; +} + const WalletDetail = () => { const classes = useStyles(); - const history = useHistory(); const usewallet = useWallet(); - const [isLoading, setLoading] = useState(true); + const [, setLoading] = useState(true); const [userWallet, setWallet] = useState(null); - const [userInfo, setUserInfo] = useState(null); - const [walletName, setWalletName] = useState(''); + const [, setWalletName] = useState(''); const [showProfile, setShowProfile] = useState(false); const [gasKillSwitch, setGasKillSwitch] = useState(false); const [modeGas, setGasMode] = useState(false); const [showError, setShowError] = useState(false); - const [walletList, setWalletList] = useState([]); + const [, setWalletList] = useState([]); const [storageInfo, setStorageInfo] = useState(null); const [isKeyphrase, setIsKeyphrase] = useState(false); const [emoji, setEmoji] = useState(tempEmoji); @@ -236,20 +249,20 @@ const WalletDetail = () => { setShowError(false); }; - const loadGasMode = async () => { + const loadGasMode = useCallback(async () => { const isFreeGasFeeEnabled = await storage.get('lilicoPayer'); if (isFreeGasFeeEnabled) { setGasMode(isFreeGasFeeEnabled); } - }; + }, []); - const loadGasKillSwitch = async () => { - const config = await usewallet.getPayerAddressAndKeyId(); + const loadGasKillSwitch = useCallback(async () => { + await usewallet.getPayerAddressAndKeyId(); const isFreeGasFeeEnabled = await storage.get('freeGas'); if (isFreeGasFeeEnabled) { setGasKillSwitch(isFreeGasFeeEnabled); } - }; + }, [usewallet]); const switchGasMode = async () => { setGasMode(!modeGas); @@ -276,23 +289,26 @@ const WalletDetail = () => { }); }; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { await usewallet.setDashIndex(3); const savedWallet = await storage.get('walletDetail'); const walletDetail = JSON.parse(savedWallet); if (walletDetail) { + console.log('walletDetail ', walletDetail); setWallet([walletDetail.wallet]); - setEmoji(walletDetail.selectedEmoji); + const selectingEmoji = {}; + selectingEmoji['name'] = walletDetail.wallet.name; + selectingEmoji['emoji'] = walletDetail.wallet.icon; + selectingEmoji['bgcolor'] = walletDetail.wallet.color; + setEmoji(selectingEmoji); } - }; + }, [usewallet]); - const loadStorageInfo = async () => { + const loadStorageInfo = useCallback(async () => { const address = await usewallet.getCurrentAddress(); - console.log('loadStorageInfo ->', address); const info = await usewallet.openapi.getStorageInfo(address!); setStorageInfo(info); - console.log('loadStorageInfo ->', info); - }; + }, [usewallet]); function storageCapacity(storage): number { const used = storage?.used ?? 1; @@ -300,19 +316,10 @@ const WalletDetail = () => { return (used / capacity) * 100; } - function formatBytes(bytes, decimals = 2) { - if (bytes === 0) return '0 Bytes'; - const k = 1000; - const dm = decimals < 0 ? 0 : decimals; - const sizes = ['', 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; - } - - const checkKeyphrase = async () => { + const checkKeyphrase = useCallback(async () => { const keyrings = await usewallet.checkMnemonics(); await setIsKeyphrase(keyrings); - }; + }, [usewallet]); useEffect(() => { setUserWallet(); @@ -320,7 +327,7 @@ const WalletDetail = () => { loadGasMode(); loadStorageInfo(); checkKeyphrase(); - }, []); + }, [checkKeyphrase, loadGasKillSwitch, loadGasMode, loadStorageInfo, setUserWallet]); useEffect(() => { const list = wallets(userWallet); @@ -463,17 +470,18 @@ const WalletDetail = () => { : chrome.i18n.getMessage('This__feature__has__been__disabled__temporarily')} - { switchGasMode(); }} /> - - {storageInfo && ( + {!!storageInfo /* TODO: remove this after the storage usage card is implemented */ && ( { color={gasKillSwitch ? 'text.secondary' : 'error.main'} sx={{ weight: 400, fontSize: '12px' }} > - {`${formatBytes(storageInfo.used * 10)} / ${formatBytes(storageInfo.capacity * 10)}`} + {`${formatStorageInfo(storageInfo?.used, storageInfo?.capacity)}`} { const [isLoading, setLoading] = useState(true); const [userWallet, setWallet] = useState([]); const [evmList, setEvmList] = useState([]); - const [flowBalance, setFlowBalance] = useState(0); + const [currentAddress, setCurrentWallet] = useState(''); const [emojis, setEmojis] = useState(tempEmoji); function handleWalletClick(wallet, eindex) { @@ -46,12 +49,52 @@ const Wallet = () => { storage.set('walletDetail', JSON.stringify(walletDetailInfo)); } - const setUserWallet = async () => { + const fetchBalances = useCallback( + async (wallet) => { + const updatedData = await Promise.all( + wallet.map(async (item) => { + const blockchainData = await Promise.all( + item.blockchain.map(async (bc) => { + const balance = await usewallet.getFlowBalance(bc.address); + return { ...bc, balance }; + }) + ); + return { ...item, blockchain: blockchainData }; + }) + ); + return updatedData; + }, + [usewallet] + ); + + const fetchEvmBalances = useCallback( + async (wallet) => { + const updatedData = await Promise.all( + wallet.map(async (item) => { + const blockchainData = await Promise.all( + item.blockchain.map(async (bc) => { + let balance = ''; + if (isValidEthereumAddress(bc.address)) { + balance = await usewallet.getBalance(bc.address); + } + return { ...bc, balance }; + }) + ); + return { ...item, blockchain: blockchainData }; + }) + ); + return updatedData; + }, + [usewallet] + ); + + const setUserWallet = useCallback(async () => { await usewallet.setDashIndex(3); const emojires = await usewallet.getEmoji(); const wallet = await usewallet.getUserWallets(); const fectechdWallet = await fetchBalances(wallet); - const network = await usewallet.getNetwork(); + const cwallet = await usewallet.getCurrentWallet(); + setCurrentWallet(cwallet.address); const evmWallet = await usewallet.getEvmWallet(); const filteredEvm = [evmWallet].filter((evm) => evm.address); if (filteredEvm.length > 0) { @@ -60,19 +103,19 @@ const Wallet = () => { } setEmojis(emojires); setWallet(fectechdWallet); - }; + }, [usewallet, fetchBalances, fetchEvmBalances]); const transformData = (data) => { return data.map((item, index) => ({ id: item.id, - name: 'flow', + name: item.name, chain_id: item.chain_id, - icon: 'placeholder', - color: 'placeholder', + icon: item.icon, + color: item.color, blockchain: [ { id: index + 1, - name: 'Flow', + name: item.name, chain_id: item.chain_id, address: item.address, coins: item.coins, @@ -81,42 +124,9 @@ const Wallet = () => { })); }; - const fetchBalances = async (wallet) => { - const updatedData = await Promise.all( - wallet.map(async (item) => { - const blockchainData = await Promise.all( - item.blockchain.map(async (bc) => { - const balance = await usewallet.getFlowBalance(bc.address); - return { ...bc, balance }; - }) - ); - return { ...item, blockchain: blockchainData }; - }) - ); - return updatedData; - }; - - const fetchEvmBalances = async (wallet) => { - const updatedData = await Promise.all( - wallet.map(async (item) => { - const blockchainData = await Promise.all( - item.blockchain.map(async (bc) => { - let balance = ''; - if (isValidEthereumAddress(bc.address)) { - balance = await usewallet.getBalance(bc.address); - } - return { ...bc, balance }; - }) - ); - return { ...item, blockchain: blockchainData }; - }) - ); - return updatedData; - }; - useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); return (
@@ -139,7 +149,7 @@ const Wallet = () => { > {userWallet.map((item) => ( handleWalletClick(item, 0)} @@ -170,15 +180,16 @@ const Wallet = () => { borderRadius: '32px', alignItems: 'center', justifyContent: 'center', - backgroundColor: emojis[0]['bgcolor'], + backgroundColor: item.color, marginRight: '12px', }} > - - {emojis[0].emoji} - + {item.icon} - + @@ -190,11 +201,22 @@ const Wallet = () => { marginRight: '4px', }} > - {emojis[0].name} + {item.name} {`(${item.blockchain[0].address})`} + {item.blockchain[0].address === currentAddress && ( + + + + )} {(item.blockchain[0].balance / 100000000).toFixed(3)} Flow @@ -227,7 +249,7 @@ const Wallet = () => { > {evmList.map((item) => ( handleWalletClick(item, 1)} @@ -255,15 +277,16 @@ const Wallet = () => { borderRadius: '32px', alignItems: 'center', justifyContent: 'center', - backgroundColor: emojis[1]['bgcolor'], + backgroundColor: item.color, marginRight: '12px', }} > - - {emojis[1].emoji} - + {item.icon} - + @@ -275,7 +298,7 @@ const Wallet = () => { marginRight: '4px', }} > - {emojis[1].name} + {item.blockchain[0].name} ({ listDiv: { justifyContent: 'center', @@ -79,16 +83,19 @@ const useStyles = makeStyles(() => ({ const SettingTab = () => { const classes = useStyles(); - const wallet = useWallet(); + const usewallet = useWallet(); const [isActive, setIsActive] = useState(false); + const [isKeyphrase, setIsKeyphrase] = useState(false); const checkIsActive = useCallback(async () => { // setSending(true); - const activeChild = await wallet.getActiveWallet(); + const activeChild = await usewallet.getActiveWallet(); if (activeChild) { setIsActive(activeChild); } - }, [wallet]); + const keyrings = await usewallet.checkMnemonics(); + await setIsKeyphrase(keyrings); + }, [usewallet]); useEffect(() => { checkIsActive(); @@ -149,7 +156,7 @@ const SettingTab = () => { > - + @@ -184,24 +191,25 @@ const SettingTab = () => { )} {!isActive && } - - - - - - - - - - - - + {isKeyphrase && ( + + + + + + + + + + + + )} @@ -210,7 +218,6 @@ const SettingTab = () => { // component={Link} // to="https://lilico.app" disablePadding - // eslint-disable-next-line no-restricted-globals onClick={() => window.open('https://core.flow.com')} className={classes.listItem} > @@ -223,7 +230,6 @@ const SettingTab = () => { {/* */} - // eslint-disable-next-line no-restricted-globals window.open( 'https://apps.apple.com/ca/app/flow-wallet-nfts-and-crypto/id6478996750' ) @@ -233,7 +239,6 @@ const SettingTab = () => { - // eslint-disable-next-line no-restricted-globals window.open( 'https://play.google.com/store/apps/details?id=com.flowfoundation.wallet' ) @@ -268,29 +273,33 @@ const SettingTab = () => { - - - - - - - - - - - + {SHOW_DEVICES && ( + <> + + + + + + + + + + + - + + + )} { const location = useLocation(); - const match = useRouteMatch(); - const wallet = useWallet(); + const usewallet = useWallet(); const [privatekey, setKey] = useState(''); const [publickey, setPublicKey] = useState(''); + const [hashAlgorithm, setHash] = useState(''); + const [signAlgorithm, setSign] = useState(''); - const verify = async () => { - const pwd = location.state.password; - const result = await wallet.getKey(pwd); - // const privateKey = hdwallet - // .derive("m/44'/539'/0'/0/0") - // .getPrivateKey() - // .toString('hex'); - setKey(result); - const pubKey = await storage.get('pubKey'); - setPublicKey(pubKey); - }; + const verify = useCallback(async () => { + try { + const pwd = location.state.password; + const result = await usewallet.getKey(pwd); + setKey(result); - const setTab = async () => { - await wallet.setDashIndex(3); - }; + const pubKey = await storage.get('pubKey'); + const account = await getStoragedAccount(); + const { hashAlgo, signAlgo } = account; + + setPublicKey(pubKey); + setHash(hashAlgo); + setSign(signAlgo); + } catch (error) { + console.error('Error during verification:', error); + } + }, [location.state.password, usewallet, setKey, setPublicKey, setHash, setSign]); + + const setTab = useCallback(async () => { + try { + await usewallet.setDashIndex(3); // Set the dashboard index in the wallet + } catch (error) { + console.error('Error setting tab:', error); + } + }, [usewallet]); useEffect(() => { setTab(); verify(); - }, []); + }, [verify, setTab]); const CredentialBox = ({ data }) => { return ( @@ -95,7 +105,7 @@ const Keydetail = () => { }; return ( -
+ {chrome.i18n.getMessage('Private__Key')} @@ -114,7 +124,7 @@ const Keydetail = () => { px: '20px', justifyContent: 'space-between', alignItems: 'center', - marginTop: '30px', + paddingY: '30px', }} > { > {chrome.i18n.getMessage('Hash__Algorithm')}
- SHA2_256 + {hashAlgorithm}
{ > {chrome.i18n.getMessage('Sign__Algorithm')}
- ECDSA_secp256k1 + {signAlgorithm}
-
+
); }; diff --git a/src/ui/views/Setting/privatekey/Privatekeypassword.tsx b/src/ui/views/Setting/privatekey/Privatekeypassword.tsx index e4ccb9b0..fa3bb162 100644 --- a/src/ui/views/Setting/privatekey/Privatekeypassword.tsx +++ b/src/ui/views/Setting/privatekey/Privatekeypassword.tsx @@ -1,13 +1,14 @@ -import React, { useEffect, useState } from 'react'; -import { Link, useHistory } from 'react-router-dom'; +import { Typography, Button, Fade, Input, FormControl } from '@mui/material'; import Box from '@mui/material/Box'; -import { Typography, Button } from '@mui/material'; -import { Input, FormControl } from '@mui/material'; -import { useWallet } from 'ui/utils'; +import { makeStyles } from '@mui/styles'; +import React, { useCallback, useEffect, useState } from 'react'; +import { Link, useHistory } from 'react-router-dom'; + import { LLHeader } from '@/ui/FRWComponent'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { useWallet } from 'ui/utils'; + import CancelIcon from '../../../../components/iconfont/IconClose'; -import { Presets } from 'react-component-transition'; -import { makeStyles } from '@mui/styles'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -44,7 +45,7 @@ const PrivateKeyPassword = () => { } }; - const verify = async () => { + const verify = useCallback(() => { setMatch(false); if (confirmPassword.length > 7) { @@ -57,28 +58,28 @@ const PrivateKeyPassword = () => { setMatch(false); }); } - }; + }, [confirmPassword, wallet]); - const setTab = async () => { + const setTab = useCallback(async () => { await wallet.setDashIndex(3); - }; + }, [wallet]); - const navigate = async () => { + const navigate = useCallback(async () => { history.push({ pathname: '/dashboard/nested/keydetail', state: { password: confirmPassword, }, }); - }; + }, [confirmPassword, history]); useEffect(() => { setTab(); - }, []); + }, [setTab]); useEffect(() => { verify(); - }, [confirmPassword]); + }, [confirmPassword, verify]); const passwordError = () => ( { onKeyDown={handleKeyDown} /> - - {confirmPassword && !isMatch && ( - - {passwordError()} - - )} - + + + {passwordError()} + + {/* */} - + { {chrome.i18n.getMessage('If__someone__has__your__private__key')} - + diff --git a/src/ui/views/Setting/recoveryphase/Recoveryphrasepassword.tsx b/src/ui/views/Setting/recoveryphase/Recoveryphrasepassword.tsx index 7b5fb84d..40e497a7 100644 --- a/src/ui/views/Setting/recoveryphase/Recoveryphrasepassword.tsx +++ b/src/ui/views/Setting/recoveryphase/Recoveryphrasepassword.tsx @@ -1,14 +1,14 @@ -import React, { useEffect, useState } from 'react'; -import { Link } from 'react-router-dom'; +import { Input, FormControl, Typography, Button, Fade } from '@mui/material'; import Box from '@mui/material/Box'; -import { Typography, Button } from '@mui/material'; -import { Input, FormControl } from '@mui/material'; -import { useWallet } from 'ui/utils'; +import { makeStyles } from '@mui/styles'; +import React, { useCallback, useEffect, useState } from 'react'; +import { Link, useHistory } from 'react-router-dom'; + import { LLHeader } from '@/ui/FRWComponent'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { useWallet } from 'ui/utils'; + import CancelIcon from '../../../../components/iconfont/IconClose'; -import { Presets } from 'react-component-transition'; -import { makeStyles } from '@mui/styles'; -import { useHistory } from 'react-router-dom'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -45,7 +45,7 @@ const Recoveryphrasepassword = () => { } }; - const verify = async () => { + const verify = useCallback(() => { setMatch(false); if (confirmPassword.length > 7) { @@ -58,28 +58,28 @@ const Recoveryphrasepassword = () => { setMatch(false); }); } - }; + }, [confirmPassword, wallet]); - const setTab = async () => { + const setTab = useCallback(async () => { await wallet.setDashIndex(3); - }; + }, [wallet]); - const navigate = async () => { + const navigate = useCallback(async () => { history.push({ pathname: '/dashboard/nested/recoveryphrasedetail', state: { password: confirmPassword, }, }); - }; + }, [confirmPassword, history]); useEffect(() => { setTab(); - }, []); + }, [setTab]); useEffect(() => { verify(); - }, [confirmPassword]); + }, [confirmPassword, verify]); const passwordError = () => ( { onKeyDown={handleKeyDown} /> - - {confirmPassword && !isMatch && ( + + <> { > {passwordError()} - )} - + + {/* */} - + { {chrome.i18n.getMessage('If__someone__has__your__secret__phrase')} - + diff --git a/src/ui/views/SortHat.tsx b/src/ui/views/SortHat.tsx index 0675dc9b..c52d3aaf 100644 --- a/src/ui/views/SortHat.tsx +++ b/src/ui/views/SortHat.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { Redirect } from 'react-router-dom'; + +import { Spin } from 'ui/component'; import { useWallet, getUiType, useApproval } from 'ui/utils'; import { openInternalPageInTab } from 'ui/utils/webapi'; -import { Spin } from 'ui/component'; const SortHat = () => { const wallet = useWallet(); @@ -11,7 +11,7 @@ const SortHat = () => { // eslint-disable-next-line prefer-const let [getApproval, , rejectApproval] = useApproval(); - const loadView = async () => { + const loadView = useCallback(async () => { const UIType = getUiType(); const isInNotification = UIType.isNotification; const isInTab = UIType.isTab; @@ -58,11 +58,11 @@ const SortHat = () => { } else { setTo('/dashboard'); } - }; + }, [getApproval, rejectApproval, wallet]); useEffect(() => { loadView(); - }, []); + }, [loadView]); return ( // diff --git a/src/ui/views/Staking/NoStake.tsx b/src/ui/views/Staking/NoStake.tsx index 6af6d3c5..275e8c1e 100644 --- a/src/ui/views/Staking/NoStake.tsx +++ b/src/ui/views/Staking/NoStake.tsx @@ -1,14 +1,16 @@ -import React, { useEffect, useState } from 'react'; import { Typography, Box, CardMedia } from '@mui/material'; +import React, { useEffect, useState, useCallback } from 'react'; + +import crown from 'ui/FRWAssets/image/crown.png'; +import Certificate from 'ui/FRWAssets/svg/Certificate.svg'; +import Dashboard from 'ui/FRWAssets/svg/Dashboard.svg'; +import Synchronize from 'ui/FRWAssets/svg/Synchronize.svg'; +import TimeClock from 'ui/FRWAssets/svg/TimeClock.svg'; import { LLHeader, LLPrimaryButton } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import StakeCard from './components/StakeCard'; -import crown from 'ui/FRWAssets/svg/crown.svg'; -import TimeClock from 'ui/FRWAssets/svg/TimeClock.svg'; -import Synchronize from 'ui/FRWAssets/svg/Synchronize.svg'; -import Dashboard from 'ui/FRWAssets/svg/Dashboard.svg'; -import Certificate from 'ui/FRWAssets/svg/Certificate.svg'; import nodeList from './nodeList.json'; -import { useWallet } from 'ui/utils'; interface NoStakeProps { noStakeOpen: boolean; network: string; @@ -21,14 +23,14 @@ interface NoStakeProps { const NoStake = (props: NoStakeProps) => { const usewallet = useWallet(); const [apr, setApr] = useState(0); - const getApy = async () => { + const getApy = useCallback(async () => { const result = await usewallet.getApr(); setApr(result); - }; + }, [usewallet]); useEffect(() => { getApy(); - }, []); + }, [getApy]); return ( { {chrome.i18n.getMessage('Recommend')} {nodeList - .filter((item) => item.name == 'Lilico') + .filter((item) => item.name === 'Lilico') .map((item) => ( { {nodeList - .filter((item) => item.name != 'Lilico') + .filter((item) => item.name !== 'Lilico') .map((item) => ( { - + Earn Rewards{' '} - {' '} - when you stake your FLOW - + + + when you stake your FLOW + + { @@ -43,13 +44,13 @@ const NodeDetail = () => { const [errorType, setErrorType] = useState(null); const [current, setCurrent] = useState(nodeList); - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { const nodeid = location['nodeid']; const delegateid = location['delegateid']; setNodeid(nodeid); setDelegate(delegateid); const currentNode = nodeList.filter((node) => { - return node.id == nodeid; + return node.id === nodeid; }); setCurrent(currentNode[0]); // const walletList = await storage.get('userWallet'); @@ -91,7 +92,7 @@ const NodeDetail = () => { setEpochStart(epochStart); return; - }; + }, [location, usewallet]); const getDate = () => { const date = new Date(); @@ -213,18 +214,18 @@ const NodeDetail = () => { }); }; - const getApy = async () => { + const getApy = useCallback(async () => { const result = await usewallet.getApr(); setApr(result); - }; + }, [usewallet]); useEffect(() => { getApy(); setUserWallet(); - }, []); + }, [getApy, setUserWallet]); return ( - + <> { - + ); }; diff --git a/src/ui/views/Staking/StakingPage.tsx b/src/ui/views/Staking/StakingPage.tsx index 885433c0..e7a55589 100644 --- a/src/ui/views/Staking/StakingPage.tsx +++ b/src/ui/views/Staking/StakingPage.tsx @@ -1,23 +1,41 @@ -import React, { useState, useEffect } from 'react'; -import { Box, Button, Typography, CardMedia } from '@mui/material'; -import { useHistory, useParams, useLocation } from 'react-router-dom'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import { CoinItem } from 'background/service/coinList'; -import theme from '../../style/LLTheme'; -import { ThemeProvider } from '@mui/material/styles'; -import StakeAmount from './components/StakeAmount'; -import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; -import IconSwitch from '../../../components/iconfont/IconSwitch'; -import { LLSpinner } from 'ui/FRWComponent'; -import { Contact } from 'background/service/networkModel'; -import { Presets } from 'react-component-transition'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Box, Button, Typography } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useParams } from 'react-router-dom'; + import { LLHeader } from '@/ui/FRWComponent'; -import { TokenListProvider } from 'flow-native-token-registry'; +import { type CoinItem } from 'background/service/coinList'; +import { useWallet } from 'ui/utils'; + +import StakeAmount from './components/StakeAmount'; import StakeConfirm from './components/StakeConfirm'; -import Increment from '../../FRWAssets/svg/increment.svg'; +const FLOW_TOKEN = { + name: 'Flow', + address: { + mainnet: '0x1654653399040a61', + testnet: '0x7e60df042a9c0868', + crescendo: '0x7e60df042a9c0868', + }, + contract_name: 'FlowToken', + storage_path: { + balance: '/public/flowTokenBalance', + vault: '/storage/flowTokenVault', + receiver: '/public/flowTokenReceiver', + }, + decimal: 8, + icon: 'https://raw.githubusercontent.com/Outblock/Assets/main/ft/flow/logo.png', + symbol: 'flow', + website: 'https://www.onflow.org', +}; +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; const StakingPage = () => { enum ENV { @@ -36,34 +54,6 @@ const StakingPage = () => { // CDN = 'CDN' // } - const flowToken = { - name: 'Flow', - address: { - mainnet: '0x1654653399040a61', - testnet: '0x7e60df042a9c0868', - crescendo: '0x7e60df042a9c0868', - }, - contract_name: 'FlowToken', - storage_path: { - balance: '/public/flowTokenBalance', - vault: '/storage/flowTokenVault', - receiver: '/public/flowTokenReceiver', - }, - decimal: 8, - icon: 'https://raw.githubusercontent.com/Outblock/Assets/main/ft/flow/logo.png', - symbol: 'flow', - website: 'https://www.onflow.org', - }; - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; - const usewallet = useWallet(); const location = useParams(); const [userWallet, setWallet] = useState(null); @@ -73,7 +63,7 @@ const StakingPage = () => { const [amount, setAmount] = useState('0'); const [outAmount, setOutAmount] = useState(0); const [network, setNetwork] = useState('mainnet'); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [nodeid, setNodeid] = useState(null); const [delegateid, setDelegate] = useState(null); const [token1, setToken1] = useState(null); @@ -87,7 +77,7 @@ const StakingPage = () => { const inputAmount = (coinInfo.balance * value).toString(); setAmount(inputAmount); }; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { const nodeid = location['nodeid']; const delegateid = location['delegateid']; setNodeid(nodeid); @@ -108,22 +98,22 @@ const StakingPage = () => { setCoinInfo(coinInfo!); setLoading(false); return; - }; + }, [location, usewallet]); - const getApy = async () => { + const getApy = useCallback(async () => { const result = await usewallet.getApr(); setApr(result); - }; + }, [usewallet]); useEffect(() => { getApy(); setUserWallet(); - setToken0(flowToken); - }, []); + setToken0(FLOW_TOKEN); + }, [getApy, setUserWallet]); return (
- + <> @@ -366,7 +356,7 @@ const StakingPage = () => { }} /> - +
); }; diff --git a/src/ui/views/Staking/TransferList.tsx b/src/ui/views/Staking/TransferList.tsx index 3636969d..da1e6587 100644 --- a/src/ui/views/Staking/TransferList.tsx +++ b/src/ui/views/Staking/TransferList.tsx @@ -1,8 +1,7 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { useWallet } from 'ui/utils'; -import { formatString } from 'ui/utils/address'; -import theme from '../../style/LLTheme'; +import CallMadeRoundedIcon from '@mui/icons-material/CallMadeRounded'; +import CallReceivedRoundedIcon from '@mui/icons-material/CallReceivedRounded'; +import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded'; +import ExpandLessRoundedIcon from '@mui/icons-material/ExpandLessRounded'; import { Typography, ListItem, @@ -14,14 +13,17 @@ import { CardMedia, Button, } from '@mui/material'; -import activity from 'ui/FRWAssets/svg/activity.svg'; +import { Box } from '@mui/system'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; +import React, { useCallback, useEffect, useState } from 'react'; + +import { formatString } from '@/shared/utils/address'; +import activity from 'ui/FRWAssets/svg/activity.svg'; +import { useWallet } from 'ui/utils'; + import IconExec from '../../../components/iconfont/IconExec'; -import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded'; -import ExpandLessRoundedIcon from '@mui/icons-material/ExpandLessRounded'; -import CallMadeRoundedIcon from '@mui/icons-material/CallMadeRounded'; -import CallReceivedRoundedIcon from '@mui/icons-material/CallReceivedRounded'; + dayjs.extend(relativeTime); const TransferList = ({ setCount }) => { @@ -34,7 +36,7 @@ const TransferList = ({ setCount }) => { const [address, setAddress] = useState('0x'); const [showButton, setShowButton] = useState(false); - const fetchTransaction = async () => { + const fetchTransaction = useCallback(async () => { setLoading(true); const monitor = await wallet.getMonitor(); setMonitor(monitor); @@ -55,14 +57,17 @@ const TransferList = ({ setCount }) => { } catch (e) { setLoading(false); } - }; + }, [wallet, setCount]); - const extMessageHandler = (req) => { - if (req.msg === 'transferListReceived') { - fetchTransaction(); - } - return true; - }; + const extMessageHandler = useCallback( + (req) => { + if (req.msg === 'transferListReceived') { + fetchTransaction(); + } + return true; + }, + [fetchTransaction] + ); useEffect(() => { fetchTransaction(); @@ -71,7 +76,7 @@ const TransferList = ({ setCount }) => { return () => { chrome.runtime.onMessage.removeListener(extMessageHandler); }; - }, []); + }, [extMessageHandler, fetchTransaction]); const timeConverter = (timeStamp: number) => { let time = dayjs.unix(timeStamp); @@ -98,7 +103,7 @@ const TransferList = ({ setCount }) => { color: isReceive && isFT ? 'success.main' : 'text.primary', }} > - {props.type == 1 + {props.type === 1 ? (isReceive ? '+' : '-') + `${props.amount}` : `${props.token.split('.')[2]}`} @@ -143,7 +148,7 @@ const TransferList = ({ setCount }) => { variant="body1" sx={{ fontSize: 14, fontWeight: '500', textAlign: 'start' }} > - {props.type == 1 ? `${props.token}` : `${props.token.split('.')[2]}`} + {props.type === 1 ? `${props.token}` : `${props.token.split('.')[2]}`}
) : ( @@ -182,7 +187,7 @@ const TransferList = ({ setCount }) => { }; return ( - + <> {!isLoading ? ( {transaction.length ? ( @@ -208,10 +213,10 @@ const TransferList = ({ setCount }) => { sx={{ paddingRight: '0px' }} dense={true} onClick={() => { - { - monitor === 'flowscan' - ? window.open(`${flowscanURL}/tx/${tx.hash}`) - : window.open(`${viewSource}/${tx.hash}`); + if (monitor === 'flowscan') { + window.open(`${flowscanURL}/tx/${tx.hash}`); + } else { + window.open(`${viewSource}/${tx.hash}`); } }} > @@ -300,7 +305,7 @@ const TransferList = ({ setCount }) => { ); }) )} - + ); }; diff --git a/src/ui/views/Staking/UnstakePage.tsx b/src/ui/views/Staking/UnstakePage.tsx index 5743e923..16bc12f9 100644 --- a/src/ui/views/Staking/UnstakePage.tsx +++ b/src/ui/views/Staking/UnstakePage.tsx @@ -1,21 +1,42 @@ -import React, { useState, useEffect } from 'react'; -import { Box, Button, Typography, CardMedia } from '@mui/material'; -import { useHistory, useParams, useLocation } from 'react-router-dom'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import { CoinItem } from 'background/service/coinList'; -import theme from '../../style/LLTheme'; -import { ThemeProvider } from '@mui/material/styles'; -import UnstakeAmount from './components/UnstakeAmount'; -import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; -import IconSwitch from '../../../components/iconfont/IconSwitch'; -import { LLSpinner } from 'ui/FRWComponent'; -import { Contact } from 'background/service/networkModel'; -import { Presets } from 'react-component-transition'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Box, Button, Typography } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useParams } from 'react-router-dom'; + import { LLHeader } from '@/ui/FRWComponent'; +import { type CoinItem } from 'background/service/coinList'; +import { useWallet } from 'ui/utils'; + +import UnstakeAmount from './components/UnstakeAmount'; import UnstakeConfirm from './components/UnstakeConfirm'; +const FLOW_TOKEN = { + name: 'Flow', + address: { + mainnet: '0x1654653399040a61', + testnet: '0x7e60df042a9c0868', + crescendo: '0x7e60df042a9c0868', + }, + contract_name: 'FlowToken', + storage_path: { + balance: '/public/flowTokenBalance', + vault: '/storage/flowTokenVault', + receiver: '/public/flowTokenReceiver', + }, + decimal: 8, + icon: 'https://raw.githubusercontent.com/Outblock/Assets/main/ft/flow/logo.png', + symbol: 'flow', + website: 'https://www.onflow.org', +}; +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; + const UnstakePage = () => { enum ENV { Mainnet = 'mainnet', @@ -32,34 +53,6 @@ const UnstakePage = () => { // CDN = 'CDN' // } - const flowToken = { - name: 'Flow', - address: { - mainnet: '0x1654653399040a61', - testnet: '0x7e60df042a9c0868', - crescendo: '0x7e60df042a9c0868', - }, - contract_name: 'FlowToken', - storage_path: { - balance: '/public/flowTokenBalance', - vault: '/storage/flowTokenVault', - receiver: '/public/flowTokenReceiver', - }, - decimal: 8, - icon: 'https://raw.githubusercontent.com/Outblock/Assets/main/ft/flow/logo.png', - symbol: 'flow', - website: 'https://www.onflow.org', - }; - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; - const usewallet = useWallet(); const location = useParams(); const [userWallet, setWallet] = useState(null); @@ -68,7 +61,7 @@ const UnstakePage = () => { const [exceed, setExceed] = useState(false); const [amount, setAmount] = useState('0'); const [network, setNetwork] = useState('mainnet'); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [nodeid, setNodeid] = useState(null); const [delegateid, setDelegate] = useState(null); const [token0, setToken0] = useState(null); @@ -83,7 +76,7 @@ const UnstakePage = () => { const inputAmount = (nodeInfo.tokensStaked * value).toString(); setAmount(inputAmount); }; - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { const nodeid = location['nodeid']; const delegateid = location['delegateid']; setNodeid(nodeid); @@ -114,22 +107,22 @@ const UnstakePage = () => { setCoinInfo(coinInfo!); setLoading(false); return; - }; + }, [usewallet, location]); - const getApy = async () => { + const getApy = useCallback(async () => { const result = await usewallet.getApr(); setApr(result); - }; + }, [usewallet]); useEffect(() => { getApy(); setUserWallet(); - setToken0(flowToken); - }, []); + setToken0(FLOW_TOKEN); + }, [getApy, setUserWallet]); return (
- + <> @@ -371,7 +364,7 @@ const UnstakePage = () => { }} /> - +
); }; diff --git a/src/ui/views/Staking/components/StakeAmount.tsx b/src/ui/views/Staking/components/StakeAmount.tsx index 5c384580..60a0752c 100644 --- a/src/ui/views/Staking/components/StakeAmount.tsx +++ b/src/ui/views/Staking/components/StakeAmount.tsx @@ -1,27 +1,7 @@ -import React, { useState, useEffect } from 'react'; -import { - Box, - Typography, - Button, - ListItemText, - Select, - MenuItem, - ListItemIcon, - FormControl, - InputAdornment, - Input, - Chip, - Tooltip, - Stack, - Avatar, -} from '@mui/material'; -import { makeStyles } from '@mui/styles'; -import StakeConfirm from './StakeConfirm'; -import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; +import { Box, Typography, FormControl, InputAdornment, Input, Stack } from '@mui/material'; import { StyledEngineProvider } from '@mui/material/styles'; -import BN from 'bignumber.js'; -import { Presets } from 'react-component-transition'; -import SelectIcon from '@mui/icons-material/ArrowDropDown'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -129,15 +109,15 @@ const StakeAmount = ({ removeError(); } } - }, [amount]); + }, [amount, coinInfo, removeError, setError, setLess]); - const currentCoinType = () => { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [currentCoinType]); return ( diff --git a/src/ui/views/Staking/components/UnstakeAmount.tsx b/src/ui/views/Staking/components/UnstakeAmount.tsx index e7ebd3ca..eece2d3b 100644 --- a/src/ui/views/Staking/components/UnstakeAmount.tsx +++ b/src/ui/views/Staking/components/UnstakeAmount.tsx @@ -1,27 +1,7 @@ -import React, { useState, useEffect } from 'react'; -import { - Box, - Typography, - Button, - ListItemText, - Select, - MenuItem, - ListItemIcon, - FormControl, - InputAdornment, - Input, - Chip, - Tooltip, - Stack, - Avatar, -} from '@mui/material'; -import { makeStyles } from '@mui/styles'; -import StakeConfirm from './StakeConfirm'; -import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; +import { Box, Typography, FormControl, InputAdornment, Input, Stack } from '@mui/material'; import { StyledEngineProvider } from '@mui/material/styles'; -import BN from 'bignumber.js'; -import { Presets } from 'react-component-transition'; -import SelectIcon from '@mui/icons-material/ArrowDropDown'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -128,15 +108,15 @@ const UnstakeAmount = ({ removeError(); } } - }, [amount]); + }, [amount, coinInfo, nodeInfo.tokensStaked, removeError, setError]); - const currentCoinType = () => { + const currentCoinType = useCallback(() => { setCoin(coinInfo.unit); - }; + }, [coinInfo.unit]); useEffect(() => { currentCoinType(); - }, []); + }, [currentCoinType]); return ( diff --git a/src/ui/views/Staking/index.tsx b/src/ui/views/Staking/index.tsx index eb2c7751..e3e97960 100644 --- a/src/ui/views/Staking/index.tsx +++ b/src/ui/views/Staking/index.tsx @@ -1,11 +1,12 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router-dom'; -import { Typography, Box, CardMedia, Snackbar, Alert, SnackbarContent, Slide } from '@mui/material'; +import { Box, Snackbar, Alert } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; + import { notification } from 'background/webapi'; // import '../../Unlock/style.css'; import { useWallet } from 'ui/utils'; -import NoStake from './NoStake'; + import HaveStake from './HaveStake'; +import NoStake from './NoStake'; const Staking = () => { const wallet = useWallet(); @@ -34,7 +35,7 @@ const Staking = () => { // const result = await wallet.createStake('true'); }; - const loadNetwork = async () => { + const loadNetwork = useCallback(async () => { const result = await wallet.getNetwork(); setNetwork(result); @@ -45,7 +46,7 @@ const Staking = () => { const storageData = await wallet.getCoinList(); const flowObject = storageData.find((coin) => coin.unit.toLowerCase() === 'flow'); setAmount(flowObject!.balance); - }; + }, [wallet]); useEffect(() => { console.log('Updated amount: ', amount); @@ -58,7 +59,7 @@ const Staking = () => { setLoading(false); }; - const getNodeInfo = async () => { + const getNodeInfo = useCallback(async () => { const address = await wallet.getCurrentAddress(); wallet .delegateInfo(address) @@ -77,12 +78,12 @@ const Staking = () => { .catch((err) => { console.log(err); }); - }; + }, [wallet]); useEffect(() => { getNodeInfo(); loadNetwork(); - }, []); + }, [getNodeInfo, loadNetwork]); return ( diff --git a/src/ui/views/Swap/SelectToken.tsx b/src/ui/views/Swap/SelectToken.tsx index 236b2f60..1a5b0ebd 100644 --- a/src/ui/views/Swap/SelectToken.tsx +++ b/src/ui/views/Swap/SelectToken.tsx @@ -1,6 +1,6 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router-dom'; - +import CloseIcon from '@mui/icons-material/Close'; +import InfoIcon from '@mui/icons-material/Info'; +import SearchIcon from '@mui/icons-material/Search'; import { Box, Typography, @@ -19,18 +19,14 @@ import { ListItemButton, ListItemText, } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { LLSpinner } from 'ui/FRWComponent'; +import { makeStyles } from '@mui/styles'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useHistory } from 'react-router-dom'; + import { useWallet } from 'ui/utils'; -import { LLProfile } from 'ui/FRWComponent'; -import IconNext from 'ui/FRWAssets/svg/next.svg'; + +import { IconCheckmark } from '../../../components/iconfont'; import IconSwitch from '../../../components/iconfont/IconSwitch'; -import eventBus from '@/eventBus'; -import InfoIcon from '@mui/icons-material/Info'; -import { Presets } from 'react-component-transition'; -import SearchIcon from '@mui/icons-material/Search'; -import { makeStyles } from '@mui/styles'; -import { IconCheckmark, IconPlus } from '../../../components/iconfont'; interface TransferConfirmationProps { isConfirmationOpen: boolean; @@ -77,14 +73,14 @@ const SelectToken = (props: TransferConfirmationProps) => { const [token0, setToken0] = useState(null); const [token1, setToken1] = useState(null); - const setToken = async () => { + const setToken = useCallback(async () => { if (props.data.token0) { setToken0(props.data.token0.contract_name); } if (props.data.token1) { setToken1(props.data.token1.contract_name); } - }; + }, [props.data.token0, props.data.token1]); const setSelectToken = (token) => { props.updateCoinInfo(token); @@ -95,12 +91,12 @@ const SelectToken = (props: TransferConfirmationProps) => { useEffect(() => { // startCount(); setToken(); - }, [props.data.token0]); + }, [props.data.token0, setToken]); useEffect(() => { // startCount(); setToken(); - }, [props.data.token1]); + }, [props.data.token1, setToken]); const renderContent = () => ( { backgroundColor: '#1f1f1f', borderRadius: '16px', }} - disabled={coin.contract_name == token0 || coin.contract_name == token1} + disabled={coin.contract_name === token0 || coin.contract_name === token1} > setSelectToken(coin)} secondaryAction={ - coin.contract_name == token0 || coin.contract_name == token1 ? ( + coin.contract_name === token0 || coin.contract_name === token1 ? ( diff --git a/src/ui/views/Swap/SwapTarget.tsx b/src/ui/views/Swap/SwapTarget.tsx index 4f32cddd..c15083cb 100644 --- a/src/ui/views/Swap/SwapTarget.tsx +++ b/src/ui/views/Swap/SwapTarget.tsx @@ -1,29 +1,8 @@ -import React, { useState, useEffect } from 'react'; -import { - Box, - Typography, - Button, - ListItemText, - Select, - MenuItem, - ListItemIcon, - FormControl, - InputAdornment, - Input, - Chip, - Tooltip, - Avatar, -} from '@mui/material'; -import { makeStyles } from '@mui/styles'; -import CloseIcon from '@mui/icons-material/Close'; -import IconFlow from '../../../components/iconfont/IconFlow'; -import IconSwitch from '../../../components/iconfont/IconSwitch'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; -import { StyledEngineProvider } from '@mui/material/styles'; -import BN from 'bignumber.js'; -import { Presets } from 'react-component-transition'; import SelectIcon from '@mui/icons-material/ArrowDropDown'; +import { Box, Typography, Button, FormControl, InputAdornment, Input, Avatar } from '@mui/material'; +import { StyledEngineProvider } from '@mui/material/styles'; +import { makeStyles } from '@mui/styles'; +import React from 'react'; const useStyles = makeStyles(() => ({ customInputLabel: { diff --git a/src/ui/views/Swap/TransferAmount.tsx b/src/ui/views/Swap/TransferAmount.tsx index fbd46bb3..a01f35d7 100644 --- a/src/ui/views/Swap/TransferAmount.tsx +++ b/src/ui/views/Swap/TransferAmount.tsx @@ -1,28 +1,18 @@ -import React, { useState, useEffect } from 'react'; +import SelectIcon from '@mui/icons-material/ArrowDropDown'; import { Box, Typography, Button, - ListItemText, - Select, - MenuItem, - ListItemIcon, FormControl, InputAdornment, Input, Chip, - Tooltip, Stack, Avatar, } from '@mui/material'; -import { makeStyles } from '@mui/styles'; -import IconFlow from '../../../components/iconfont/IconFlow'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import AttachMoneyRoundedIcon from '@mui/icons-material/AttachMoneyRounded'; import { StyledEngineProvider } from '@mui/material/styles'; -import BN from 'bignumber.js'; -import { Presets } from 'react-component-transition'; -import SelectIcon from '@mui/icons-material/ArrowDropDown'; +import { makeStyles } from '@mui/styles'; +import React, { useEffect } from 'react'; const useStyles = makeStyles(() => ({ customInputLabel: { @@ -134,7 +124,7 @@ const TransferAmount = ({ removeError(); } } - }, [amount]); + }, [amount, coinInfo, removeError, setError]); return ( diff --git a/src/ui/views/Swap/TransferConfirmation.tsx b/src/ui/views/Swap/TransferConfirmation.tsx index 65d357c2..ca52c9a5 100644 --- a/src/ui/views/Swap/TransferConfirmation.tsx +++ b/src/ui/views/Swap/TransferConfirmation.tsx @@ -2,9 +2,9 @@ import CloseIcon from '@mui/icons-material/Close'; import InfoIcon from '@mui/icons-material/Info'; import { Box, Typography, Drawer, Grid, CardMedia, IconButton, Button } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; -import { Presets } from 'react-component-transition'; import { useHistory } from 'react-router-dom'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -259,28 +259,26 @@ const TransferConfirmation = (props: TransferConfirmationProps) => { - {occupied && ( - - - {/* */} - - - {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} - - - - )} + + + {/* */} + + + {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} + + + { size="large" sx={{ height: '50px', + width: '100%', borderRadius: '12px', textTransform: 'capitalize', display: 'flex', diff --git a/src/ui/views/Swap/index.tsx b/src/ui/views/Swap/index.tsx index 821ecbe5..be5c375f 100644 --- a/src/ui/views/Swap/index.tsx +++ b/src/ui/views/Swap/index.tsx @@ -1,25 +1,64 @@ -import React, { useState, useEffect } from 'react'; import { Box, Button, Typography, IconButton, CardMedia } from '@mui/material'; +import React, { useState, useEffect, useCallback } from 'react'; + // import { useHistory, useLocation } from 'react-router-dom'; // import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import { CoinItem } from 'background/service/coinList'; -import theme from '../../style/LLTheme'; -import { ThemeProvider } from '@mui/material/styles'; -import TransferAmount from './TransferAmount'; -import SwapTarget from './SwapTarget'; +import { withPrefix } from '@/shared/utils/address'; +import { LLHeader } from '@/ui/FRWComponent'; +import { type CoinItem } from 'background/service/coinList'; +import { type Contact } from 'background/service/networkModel'; +import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; + import IconSwitch from '../../../components/iconfont/IconSwitch'; -import TransferConfirmation from './TransferConfirmation'; +import Increment from '../../FRWAssets/svg/increment.svg'; + import SelectToken from './SelectToken'; -import { LLSpinner } from 'ui/FRWComponent'; -import { Contact } from 'background/service/networkModel'; -// import { Presets } from 'react-component-transition'; +import SwapTarget from './SwapTarget'; +import TransferAmount from './TransferAmount'; +import TransferConfirmation from './TransferConfirmation'; + +// // import CancelIcon from '../../../components/iconfont/IconClose'; -import { LLHeader } from '@/ui/FRWComponent'; // import { TokenListProvider } from 'flow-native-token-registry'; +const USER_CONTACT = { + address: '', + id: 0, + contact_name: '', + avatar: '', + domain: { + domain_type: 999, + value: '', + }, +} as unknown as Contact; -import Increment from '../../FRWAssets/svg/increment.svg'; +const FLOW_TOKEN = { + name: 'Flow', + address: { + mainnet: '0x1654653399040a61', + testnet: '0x7e60df042a9c0868', + crescendo: '0x7e60df042a9c0868', + }, + contract_name: 'FlowToken', + storage_path: { + balance: '/public/flowTokenBalance', + vault: '/storage/flowTokenVault', + receiver: '/public/flowTokenReceiver', + }, + decimal: 8, + icon: 'https://raw.githubusercontent.com/Outblock/Assets/main/ft/flow/logo.png', + symbol: 'flow', + website: 'https://www.onflow.org', +}; +const EMPTY_COIN: CoinItem = { + coin: '', + unit: '', + balance: 0, + price: 0, + change24h: 0, + total: 0, + icon: '', +}; const Swap = () => { enum ENV { @@ -36,44 +75,6 @@ const Swap = () => { // Static = 'Static', // CDN = 'CDN' // } - const userContact = { - address: '', - id: 0, - contact_name: '', - avatar: '', - domain: { - domain_type: 999, - value: '', - }, - } as unknown as Contact; - - const flowToken = { - name: 'Flow', - address: { - mainnet: '0x1654653399040a61', - testnet: '0x7e60df042a9c0868', - crescendo: '0x7e60df042a9c0868', - }, - contract_name: 'FlowToken', - storage_path: { - balance: '/public/flowTokenBalance', - vault: '/storage/flowTokenVault', - receiver: '/public/flowTokenReceiver', - }, - decimal: 8, - icon: 'https://raw.githubusercontent.com/Outblock/Assets/main/ft/flow/logo.png', - symbol: 'flow', - website: 'https://www.onflow.org', - }; - const empty: CoinItem = { - coin: '', - unit: '', - balance: 0, - price: 0, - change24h: 0, - total: 0, - icon: '', - }; const usewallet = useWallet(); const [userWallet, setWallet] = useState(null); @@ -85,10 +86,10 @@ const Swap = () => { const [amount, setAmount] = useState('0'); const [outAmount, setOutAmount] = useState(0); // const [validated, setValidated] = useState(null); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [selectTarget, setSelectTarget] = useState(0); const [network, setNetwork] = useState('mainnet'); - const [coinInfo, setCoinInfo] = useState(empty); + const [coinInfo, setCoinInfo] = useState(EMPTY_COIN); const [estimateInfo, setEstimateInfo] = useState(null); const [token1, setToken1] = useState(null); const [token0, setToken0] = useState(null); @@ -98,7 +99,7 @@ const Swap = () => { const [swapPrice, setPrice] = useState(0); const [errorType, setErrorType] = useState(null); - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { // const walletList = await storage.get('userWallet'); setLoading(true); const token = await usewallet.getCurrentCoin(); @@ -114,9 +115,12 @@ const Swap = () => { setCoinInfo(coinInfo!); const info = await usewallet.getUserInfo(false); - userContact.address = withPrefix(wallet.address) || ''; - userContact.avatar = info.avatar; - userContact.contact_name = info.username; + const userContact = { + ...USER_CONTACT, + address: withPrefix(wallet.address) || '', + avatar: info.avatar, + contact_name: info.username, + }; setUser(userContact); // const result = await usewallet.openapi.fetchTokenList(network); usewallet.openapi.getAllToken().then((res) => { @@ -124,7 +128,7 @@ const Swap = () => { }); setLoading(false); return; - }; + }, [usewallet]); const updateCoinInfo = (token) => { if (selectTarget) { @@ -165,7 +169,7 @@ const Swap = () => { setSwapTypes(1); }; - const estimateOut = async () => { + const estimateOut = useCallback(async () => { setLoading(true); const network = await usewallet.getNetwork(); if (token0 && token1) { @@ -185,7 +189,7 @@ const Swap = () => { let price: any = result.data.tokenOutAmount / parseFloat(result.data.tokenInAmount); price = (Math.round(price * 1000) / 1000).toFixed(3); setPrice(price); - if (errorType == Error.Fail) { + if (errorType === Error.Fail) { setErrorType(null); } setEstimateInfo(result.data); @@ -197,9 +201,9 @@ const Swap = () => { } setLoading(false); return; - }; + }, [outAmount, usewallet, token0, token1, errorType, Error.Fail]); - const estimate = async () => { + const estimate = useCallback(async () => { setLoading(true); if (Number(amount) <= 0) { setLoading(false); @@ -219,7 +223,7 @@ const Swap = () => { let price: any = result.data.tokenOutAmount / parseFloat(result.data.tokenInAmount); price = (Math.round(price * 1000) / 1000).toFixed(3); setPrice(price); - if (errorType == Error.Fail) { + if (errorType === Error.Fail) { setErrorType(null); } setEstimateInfo(result.data); @@ -231,12 +235,12 @@ const Swap = () => { } } setLoading(false); - }; + }, [amount, usewallet, token0, token1, errorType, Error.Fail]); useEffect(() => { setUserWallet(); - setToken0(flowToken); - }, []); + setToken0(FLOW_TOKEN); + }, [setUserWallet]); useEffect(() => { if (swapTypes) { @@ -247,21 +251,21 @@ const Swap = () => { }, 500); return () => clearTimeout(delayDebounceFn); - }, [amount]); + }, [amount, estimate, swapTypes]); useEffect(() => { const delayDebounceFn = setTimeout(async () => { estimate(); }, 500); return () => clearTimeout(delayDebounceFn); - }, [token1]); + }, [token1, estimate]); useEffect(() => { const delayDebounceFn = setTimeout(async () => { estimate(); }, 500); return () => clearTimeout(delayDebounceFn); - }, [token0]); + }, [token0, estimate]); useEffect(() => { if (!swapTypes) { @@ -271,11 +275,11 @@ const Swap = () => { estimateOut(); }, 500); return () => clearTimeout(delayDebounceFn); - }, [outAmount]); + }, [outAmount, estimateOut, swapTypes]); return (
- + <> @@ -443,7 +447,7 @@ const Swap = () => { {/* - { }}> Estimated Fees - { textTransform: 'capitalize', }} disabled={ - outAmount <= 0 || Number(amount) <= 0 || errorType || isLoading || token1 == null + outAmount <= 0 || Number(amount) <= 0 || errorType || isLoading || token1 === null } > @@ -511,7 +515,7 @@ const Swap = () => { updateCoinInfo={updateCoinInfo} /> - +
); }; diff --git a/src/ui/views/SwitchUnlock/index.tsx b/src/ui/views/SwitchUnlock/index.tsx index cbadadb8..80497e4d 100644 --- a/src/ui/views/SwitchUnlock/index.tsx +++ b/src/ui/views/SwitchUnlock/index.tsx @@ -1,14 +1,16 @@ -import React, { useEffect, useRef, useState } from 'react'; // import { useTranslation } from 'react-i18next'; -import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; -import { Typography, Box, FormControl } from '@mui/material'; -import { LLPrimaryButton, LLResetPopup } from 'ui/FRWComponent'; -import { Input } from '@mui/material'; -import { Presets } from 'react-component-transition'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Input, Typography, Box, FormControl } from '@mui/material'; import { makeStyles } from '@mui/styles'; +import React, { useEffect, useRef, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import lilo from 'ui/FRWAssets/image/lilo.png'; +import { LLPrimaryButton, LLResetPopup } from 'ui/FRWComponent'; +import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; import { openInternalPageInTab } from 'ui/utils/webapi'; + +import CancelIcon from '../../../components/iconfont/IconClose'; + import './style.css'; const useStyles = makeStyles(() => ({ @@ -143,20 +145,18 @@ const SwitchUnlock = () => { onKeyDown={handleKeyDown} /> - - {showError && ( - - {usernameError()} - - )} - + + + {usernameError()} + + {/* */} diff --git a/src/ui/views/Sync/AllSet.tsx b/src/ui/views/Sync/AllSet.tsx index 1252f73c..cca17c81 100644 --- a/src/ui/views/Sync/AllSet.tsx +++ b/src/ui/views/Sync/AllSet.tsx @@ -1,13 +1,12 @@ +import { Button, Typography, CardMedia } from '@mui/material'; +import { Box } from '@mui/system'; import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, CssBaseline, CardMedia } from '@mui/material'; -import theme from '../../style/LLTheme'; + import AllSetIcon from 'ui/FRWAssets/svg/allset.svg'; const AllSet = ({ handleClick }) => { return ( - - + <> { - + ); }; diff --git a/src/ui/views/Sync/RegisterHeader.tsx b/src/ui/views/Sync/RegisterHeader.tsx index 234219ff..fb499d7f 100644 --- a/src/ui/views/Sync/RegisterHeader.tsx +++ b/src/ui/views/Sync/RegisterHeader.tsx @@ -1,12 +1,11 @@ -import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography } from '@mui/material'; -import theme from '../../style/LLTheme'; import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import { Button, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import React from 'react'; const RegisterHeader = () => { return ( - + <> { - + ); }; diff --git a/src/ui/views/Sync/SetPassword.tsx b/src/ui/views/Sync/SetPassword.tsx index 267d2d9d..95f9317e 100644 --- a/src/ui/views/Sync/SetPassword.tsx +++ b/src/ui/views/Sync/SetPassword.tsx @@ -1,6 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles, styled } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Button, Typography, @@ -11,18 +10,19 @@ import { LinearProgress, Alert, Snackbar, - CssBaseline, } from '@mui/material'; -import { LLSpinner } from 'ui/FRWComponent'; -import CancelIcon from '../../../components/iconfont/IconClose'; -import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; -import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; -import VisibilityIcon from '@mui/icons-material/Visibility'; -import { Presets } from 'react-component-transition'; +import { makeStyles, styled } from '@mui/styles'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; import zxcvbn from 'zxcvbn'; -import theme from '../../style/LLTheme'; -import { useWallet, saveIndex } from 'ui/utils'; + import { storage } from '@/background/webapi'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLSpinner } from 'ui/FRWComponent'; +import { useWallet, saveIndex } from 'ui/utils'; + +import CheckCircleIcon from '../../../components/iconfont/IconCheckmark'; +import CancelIcon from '../../../components/iconfont/IconClose'; // const helperTextStyles = makeStyles(() => ({ // root: { @@ -238,8 +238,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { }, [confirmPassword, password]); return ( - - + <> { } /> - {password && helperText} + + {helperText} + { } /> - - {confirmPassword && helperMatch} - + + {helperMatch} + @@ -394,7 +395,7 @@ const SetPassword = ({ handleClick, mnemonic, username }) => { - + ); }; diff --git a/src/ui/views/Sync/SyncQr.tsx b/src/ui/views/Sync/SyncQr.tsx index 9c070274..2befa86e 100644 --- a/src/ui/views/Sync/SyncQr.tsx +++ b/src/ui/views/Sync/SyncQr.tsx @@ -1,17 +1,17 @@ -import React, { useEffect, useCallback, useState } from 'react'; +import { Button, Typography, FormControl, Input, InputAdornment } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { Box, ThemeProvider } from '@mui/system'; -import { Button, Typography, FormControl, Input, InputAdornment, CssBaseline } from '@mui/material'; -import theme from '../../style/LLTheme'; -import { useWallet } from 'ui/utils'; +import { Box } from '@mui/system'; import { Core } from '@walletconnect/core'; -import { FCLWalletConnectMethod } from '@/ui/utils/type'; import SignClient from '@walletconnect/sign-client'; -import { PairingTypes, SessionTypes } from '@walletconnect/types'; +import { PairingTypes, type SessionTypes } from '@walletconnect/types'; import * as bip39 from 'bip39'; import HDWallet from 'ethereum-hdwallet'; +import React, { useEffect, useCallback, useState } from 'react'; import { QRCode } from 'react-qrcode-logo'; + +import { FCLWalletConnectMethod } from '@/ui/utils/type'; import lilo from 'ui/FRWAssets/image/lilo.png'; +import { useWallet } from 'ui/utils'; interface AccountKey { hashAlgo: number; @@ -73,73 +73,16 @@ const SyncQr = ({ handleClick, savedUsername, confirmMnemonic, setUsername }) => const [loading, setShowLoading] = useState(false); const [session, setSession] = useState(); const [mnemonic, setMnemonic] = useState(bip39.generateMnemonic()); - const [currentNetwork, setNetwork] = useState( - process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet' - ); + const [currentNetwork, setNetwork] = useState('mainnet'); - const loadNetwork = async () => { + const loadNetwork = useCallback(async () => { const currentNetwork = await usewallet.getNetwork(); setNetwork(currentNetwork); - }; + }, [usewallet]); useEffect(() => { loadNetwork(); - }, []); - - useEffect(() => { - const createWeb3Wallet = async () => { - try { - const wallet = await SignClient.init({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore: Unreachable code error - core: new Core({ - projectId: process.env.WC_PROJECTID, - }), - metadata: { - name: 'Flow Walllet', - description: 'Digital wallet created for everyone.', - url: 'https://fcw-link.lilico.app', - icons: ['https://fcw-link.lilico.app/logo.png'], - }, - }); - await _subscribeToEvents(wallet); - - try { - const { uri, approval } = await wallet.connect({ - requiredNamespaces: { - flow: { - methods: [FCLWalletConnectMethod.accountInfo, FCLWalletConnectMethod.addDeviceInfo], - chains: [`flow:${currentNetwork}`], - events: [], - }, - }, - }); - - // Open QRCode modal if a URI was returned (i.e. we're not connecting an existing pairing). - if (uri) { - console.log('uri ', uri); - await setUri(uri); - // Await session approval from the wallet. - const session = await approval(); - await onSessionConnected(session); - - console.log('session ', session); - sendRequest(wallet, session.topic); - - // onSessionConnect(session) - // Close the QRCode modal in case it was open. - } - } catch (e) { - console.error(e); - } - await setWeb3Wallet(wallet); - console.log('web3wallet', web3wallet); - } catch (e) { - console.error(e); - } - }; - createWeb3Wallet(); - }, []); + }, [loadNetwork]); const onSessionConnected = useCallback(async (_session: SessionTypes.Struct) => { console.log('_session ', _session); @@ -165,68 +108,7 @@ const SyncQr = ({ handleClick, savedUsername, confirmMnemonic, setUsername }) => [onSessionConnected] ); - async function sendRequest(wallet: SignClient, topic: string) { - wallet - .request({ - topic: topic, - chainId: `flow:${currentNetwork}`, - request: { - method: FCLWalletConnectMethod.accountInfo, - params: [], - }, - }) - .then(async (result: any) => { - const jsonObject = JSON.parse(result); - if (jsonObject.method === FCLWalletConnectMethod.accountInfo) { - const accountKey: AccountKey = getAccountKey(); - const deviceInfo: DeviceInfoRequest = await getDeviceInfo(); - - wallet - .request({ - topic: topic, - chainId: `flow:${currentNetwork}`, - request: { - method: FCLWalletConnectMethod.addDeviceInfo, - params: { - method: '', - data: { - username: '', - accountKey: accountKey, - deviceInfo: deviceInfo, - }, - }, - }, - }) - .then(async (sent) => { - const ak = { - public_key: accountKey.publicKey, - hash_algo: accountKey.hashAlgo, - sign_algo: accountKey.signAlgo, - weight: accountKey.weight, - }; - usewallet - .signInV3(mnemonic, ak, deviceInfo) - .then(async (result) => { - confirmMnemonic(mnemonic); - const userInfo = await usewallet.getUserInfo(true); - setUsername(userInfo.username); - handleClick(); - }) - .catch((error) => { - console.error('Error in sign in wallet request:', error); - }); - }) - .catch((error) => { - console.error('Error in second wallet request:', error); - }); - } - }) - .catch((error) => { - console.error('Error in first wallet request:', error); - }); - } - - const getAccountKey = () => { + const getAccountKey = useCallback(() => { const hdwallet = HDWallet.fromMnemonic(mnemonic); const publicKey = hdwallet.derive("m/44'/539'/0'/0/0").getPublicKey().toString('hex'); const key: AccountKey = { @@ -236,9 +118,9 @@ const SyncQr = ({ handleClick, savedUsername, confirmMnemonic, setUsername }) => publicKey: publicKey, }; return key; - }; + }, [mnemonic]); - const getDeviceInfo = async (): Promise => { + const getDeviceInfo = useCallback(async (): Promise => { const result = await usewallet.openapi.getLocation(); const installationId = await usewallet.openapi.getInstallationId(); const userlocation = result.data; @@ -264,11 +146,137 @@ const SyncQr = ({ handleClick, savedUsername, confirmMnemonic, setUsername }) => zip: userlocation.zip, }; return deviceInfo; - }; + }, [usewallet]); + + const sendRequest = useCallback( + async (wallet: SignClient, topic: string) => { + wallet + .request({ + topic: topic, + chainId: `flow:${currentNetwork}`, + request: { + method: FCLWalletConnectMethod.accountInfo, + params: [], + }, + }) + .then(async (result: any) => { + const jsonObject = JSON.parse(result); + if (jsonObject.method === FCLWalletConnectMethod.accountInfo) { + const accountKey: AccountKey = getAccountKey(); + const deviceInfo: DeviceInfoRequest = await getDeviceInfo(); + + wallet + .request({ + topic: topic, + chainId: `flow:${currentNetwork}`, + request: { + method: FCLWalletConnectMethod.addDeviceInfo, + params: { + method: '', + data: { + username: '', + accountKey: accountKey, + deviceInfo: deviceInfo, + }, + }, + }, + }) + .then(async (sent) => { + const ak = { + public_key: accountKey.publicKey, + hash_algo: accountKey.hashAlgo, + sign_algo: accountKey.signAlgo, + weight: accountKey.weight, + }; + usewallet + .signInV3(mnemonic, ak, deviceInfo) + .then(async (result) => { + confirmMnemonic(mnemonic); + const userInfo = await usewallet.getUserInfo(true); + setUsername(userInfo.username); + handleClick(); + }) + .catch((error) => { + console.error('Error in sign in wallet request:', error); + }); + }) + .catch((error) => { + console.error('Error in second wallet request:', error); + }); + } + }) + .catch((error) => { + console.error('Error in first wallet request:', error); + }); + }, + [ + confirmMnemonic, + currentNetwork, + getAccountKey, + getDeviceInfo, + handleClick, + mnemonic, + setUsername, + usewallet, + ] + ); + + useEffect(() => { + const createWeb3Wallet = async () => { + try { + const wallet = await SignClient.init({ + // @ts-ignore: Unreachable code error + core: new Core({ + projectId: process.env.WC_PROJECTID, + }), + metadata: { + name: 'Flow Walllet', + description: 'Digital wallet created for everyone.', + url: 'https://fcw-link.lilico.app', + icons: ['https://fcw-link.lilico.app/logo.png'], + }, + }); + await _subscribeToEvents(wallet); + + try { + const { uri, approval } = await wallet.connect({ + requiredNamespaces: { + flow: { + methods: [FCLWalletConnectMethod.accountInfo, FCLWalletConnectMethod.addDeviceInfo], + chains: [`flow:${currentNetwork}`], + events: [], + }, + }, + }); + + // Open QRCode modal if a URI was returned (i.e. we're not connecting an existing pairing). + if (uri) { + console.log('uri ', uri); + await setUri(uri); + // Await session approval from the wallet. + const session = await approval(); + await onSessionConnected(session); + + console.log('session ', session); + sendRequest(wallet, session.topic); + + // onSessionConnect(session) + // Close the QRCode modal in case it was open. + } + } catch (e) { + console.error(e); + } + await setWeb3Wallet(wallet); + console.log('web3wallet', web3wallet); + } catch (e) { + console.error(e); + } + }; + createWeb3Wallet(); + }, [_subscribeToEvents, currentNetwork, onSessionConnected, sendRequest, web3wallet]); return ( - - + <> {/* */} - + ); }; diff --git a/src/ui/views/Sync/index.tsx b/src/ui/views/Sync/index.tsx index cde10911..2ee8ebb8 100644 --- a/src/ui/views/Sync/index.tsx +++ b/src/ui/views/Sync/index.tsx @@ -1,18 +1,20 @@ -import React, { useState, useEffect } from 'react'; +import { IconButton } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, ThemeProvider } from '@mui/system'; -import { IconButton, Typography, Button, Snackbar, Alert } from '@mui/material'; + +import Confetti from '@/ui/FRWComponent/Confetti'; +import SlideLeftRight from '@/ui/FRWComponent/SlideLeftRight'; +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; +import { LLPinAlert } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import BackButtonIcon from '../../../components/iconfont/IconBackButton'; -import IconGoogleDrive from '../../../components/iconfont/IconGoogleDrive'; -import theme from '../../style/LLTheme'; -import RegisterHeader from '../Register/RegisterHeader'; import AllSet from '../Register/AllSet'; +import RegisterHeader from '../Register/RegisterHeader'; + import SetPassword from './SetPassword'; import SyncQr from './SyncQr'; -import Particles from 'react-tsparticles'; -import { LLPinAlert, LLSpinner } from 'ui/FRWComponent'; -import { ComponentTransition, AnimationTypes } from 'react-component-transition'; -import { useWallet, Options } from 'ui/utils'; enum Direction { Right, @@ -25,16 +27,13 @@ const Sync = () => { const [activeIndex, onChange] = useState(0); const [mnemonic, setMnemonic] = useState(''); const [username, setUsername] = useState(''); - const [errMessage, setErrorMessage] = useState(chrome.i18n.getMessage('No__backup__found')); - const [showError, setShowError] = useState(false); const [direction, setDirection] = useState(Direction.Right); - const [loading, setLoading] = useState(false); const getUsername = (username: string) => { setUsername(username.toLowerCase()); }; - const loadView = async () => { + const loadView = useCallback(async () => { wallet .getCurrentAccount() .then((res) => { @@ -45,7 +44,7 @@ const Sync = () => { .catch(() => { return; }); - }; + }, [wallet, history]); const goNext = () => { setDirection(Direction.Right); if (activeIndex < 2) { @@ -64,13 +63,6 @@ const Sync = () => { } }; - const handleErrorClose = (event?: React.SyntheticEvent | Event, reason?: string) => { - if (reason === 'clickaway') { - return; - } - setShowError(false); - }; - const page = (index) => { switch (index) { case 0: @@ -93,10 +85,10 @@ const Sync = () => { useEffect(() => { loadView(); - }, []); + }, [loadView]); return ( - + <> { alignItems: 'center', }} > - {activeIndex == 2 && ( - - )} + {activeIndex === 2 && } - + {/* height why not use auto */} @@ -144,31 +131,15 @@ const Sync = () => { )} - + {page(activeIndex)} - + - + ); }; diff --git a/src/ui/views/TokenDetail/PriceCard.tsx b/src/ui/views/TokenDetail/PriceCard.tsx index 55ad153c..64cc6f54 100644 --- a/src/ui/views/TokenDetail/PriceCard.tsx +++ b/src/ui/views/TokenDetail/PriceCard.tsx @@ -1,6 +1,24 @@ -import React, { useEffect, useState, useRef } from 'react'; +import ArrowDropDownRoundedIcon from '@mui/icons-material/ArrowDropDownRounded'; +import ArrowDropUpRoundedIcon from '@mui/icons-material/ArrowDropUpRounded'; +import KeyboardArrowDownRoundedIcon from '@mui/icons-material/KeyboardArrowDownRounded'; +import { + ToggleButtonGroup, + ToggleButton, + Menu, + MenuItem, + Typography, + Box, + ButtonBase, +} from '@mui/material'; +import { styled } from '@mui/material/styles'; +import dayjs from 'dayjs'; +import React, { useEffect, useState, useRef, useCallback } from 'react'; +import { AreaChart, Area, YAxis, Tooltip, ResponsiveContainer } from 'recharts'; + +import { getPeriodFrequency } from '@/shared/utils/getPeriodFrequency'; +import { Period, type PriceProvider } from 'background/service/networkModel'; import { useWallet } from 'ui/utils'; -import { Typography, Box, ButtonBase } from '@mui/material'; + import { IconKraken, IconBinance, @@ -8,16 +26,6 @@ import { IconKucoin, IconHuobi, } from '../../../components/iconfont'; -import { ToggleButtonGroup, ToggleButton, Menu, MenuItem } from '@mui/material'; -import { AreaChart, Area, YAxis, Tooltip, ResponsiveContainer } from 'recharts'; -import ArrowDropUpRoundedIcon from '@mui/icons-material/ArrowDropUpRounded'; -import ArrowDropDownRoundedIcon from '@mui/icons-material/ArrowDropDownRounded'; -import KeyboardArrowDownRoundedIcon from '@mui/icons-material/KeyboardArrowDownRounded'; -import { styled } from '@mui/material/styles'; -import { getPeriodFrequency } from 'utils'; - -import dayjs from 'dayjs'; -import { Period, PriceProvider } from 'background/service/networkModel'; const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ '& .MuiToggleButtonGroup-grouped': { @@ -139,52 +147,59 @@ const PriceCard = ({ token, price, setPrice, providers }) => { setAnchorEl(null); }; - const fetchPrice = async (provider: PriceProvider) => { - const response = await wallet.openapi.getTokenPrice(token, provider); - if (mountedRef.current) { - setPrice(response['price']['last']); - const percentage = response['price']['change']['percentage'] * 100; - setChange(percentage); - } - }; + const fetchPrice = useCallback( + async (provider: PriceProvider) => { + const response = await wallet.openapi.getTokenPrice(token, provider); + if (mountedRef.current) { + setPrice(response['price']['last']); + const percentage = response['price']['change']['percentage'] * 100; + setChange(percentage); + } + }, + [token, wallet.openapi, setPrice] + ); - const fetchPriceHistory = async (period: Period, provider: PriceProvider) => { - wallet.openapi.getTokenPriceHistory(token, period, provider).then((response) => { - const frequency = getPeriodFrequency(period); - const data = response[frequency].map((item) => ({ - closeTime: item[0], - openPrice: item[1], - highPrice: item[2], - lowPrice: item[3], - price: item[4], - volume: item[5], - quoteVolume: item[6], - })); - setData(data); - }); - }; + const fetchPriceHistory = useCallback( + async (period: Period, provider: PriceProvider) => { + wallet.openapi.getTokenPriceHistory(token, period, provider).then((response) => { + const frequency = getPeriodFrequency(period); + const data = response[frequency].map((item) => ({ + closeTime: item[0], + openPrice: item[1], + highPrice: item[2], + lowPrice: item[3], + price: item[4], + volume: item[5], + quoteVolume: item[6], + })); + setData(data); + }); + }, + [token, wallet.openapi] + ); + const currentProvider = useCallback((): PriceProvider => { + return priceProviders[selectedIndex] as PriceProvider; + }, [selectedIndex, priceProviders]); useEffect(() => { // FIX ME: Memory leak const timerId = setTimeout(() => { - fetchPrice(currentProvider()), fetchPriceHistory(period, currentProvider()); + fetchPrice(currentProvider()); + fetchPriceHistory(period, currentProvider()); }, 400); return () => clearTimeout(timerId); - }, []); + }, [fetchPrice, fetchPriceHistory, period, currentProvider]); useEffect(() => { - fetchPrice(currentProvider()), fetchPriceHistory(period, currentProvider()); - }, [selectedIndex]); + fetchPrice(currentProvider()); + fetchPriceHistory(period, currentProvider()); + }, [selectedIndex, period, fetchPrice, fetchPriceHistory, currentProvider]); const isUp = (): boolean => { return change >= 0; }; - const currentProvider = (): PriceProvider => { - return priceProviders[selectedIndex] as PriceProvider; - }; - const handlePeriod = (event: React.MouseEvent, newPeriod: string) => { const period = newPeriod as Period; if (period) { @@ -382,7 +397,6 @@ const PriceCard = ({ token, price, setPrice, providers }) => { } diff --git a/src/ui/views/TokenDetail/StackingCard.tsx b/src/ui/views/TokenDetail/StackingCard.tsx index dc560518..62e20e4a 100644 --- a/src/ui/views/TokenDetail/StackingCard.tsx +++ b/src/ui/views/TokenDetail/StackingCard.tsx @@ -1,7 +1,8 @@ -import React from 'react'; import { Typography, Box, ButtonBase } from '@mui/material'; -import flowGrey from 'ui/FRWAssets/svg/flow-grey.svg'; +import React from 'react'; import { useHistory } from 'react-router-dom'; + +import flowGrey from 'ui/FRWAssets/svg/flow-grey.svg'; import { useWallet } from 'ui/utils'; const StackingCard = ({ network }) => { diff --git a/src/ui/views/TokenDetail/TokenInfoCard.tsx b/src/ui/views/TokenDetail/TokenInfoCard.tsx index dd3f6215..ae87e265 100644 --- a/src/ui/views/TokenDetail/TokenInfoCard.tsx +++ b/src/ui/views/TokenDetail/TokenInfoCard.tsx @@ -1,13 +1,16 @@ -import React, { useEffect, useState, useRef } from 'react'; -import { useWallet } from 'ui/utils'; -import { addDotSeparators } from 'ui/utils/number'; import { Typography, Box, ButtonBase, CardMedia } from '@mui/material'; -import IconChevronRight from '../../../components/iconfont/IconChevronRight'; +import { type TokenInfo } from 'flow-native-token-registry'; +import React, { useEffect, useState, useRef, useCallback } from 'react'; +import { useHistory } from 'react-router-dom'; + +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLPrimaryButton } from '@/ui/FRWComponent'; -import { TokenInfo } from 'flow-native-token-registry'; import iconMove from 'ui/FRWAssets/svg/moveIcon.svg'; +import { useWallet } from 'ui/utils'; +import { addDotSeparators } from 'ui/utils/number'; + +import IconChevronRight from '../../../components/iconfont/IconChevronRight'; -import { useHistory } from 'react-router-dom'; // import tips from 'ui/FRWAssets/svg/tips.svg'; const TokenInfoCard = ({ @@ -43,14 +46,14 @@ const TokenInfoCard = ({ }; checkPermission(); - }, [balance]); + }, [balance, tokenInfo.custom, wallet]); const toSend = async () => { await wallet.setCurrentCoin(token); history.push('/dashboard/wallet/send'); }; - const getActive = async () => { + const getActive = useCallback(async () => { const evmEnabled = await wallet.getEvmEnabled(); setEvmEnabled(evmEnabled); const isChild = await wallet.getActiveWallet(); @@ -71,7 +74,7 @@ const TokenInfoCard = ({ .getWalletTokenBalance(token) .then((response) => { if (isMounted.current) { - setBalance(parseFloat(parseFloat(response).toFixed(3))); + setBalance(parseFloat(response)); } }) .catch((err) => { @@ -84,7 +87,7 @@ const TokenInfoCard = ({ isMounted.current = false; // Mark component as unmounted clearTimeout(timerId); // Clear the timer }; - }; + }, [setAccessible, token, tokenInfo, wallet]); const moveToken = () => { if (childType && childType !== 'evm') { @@ -95,6 +98,18 @@ const TokenInfoCard = ({ } }; + const getUrl = (data) => { + if (data.extensions?.website?.trim()) { + return data.extensions.website; + } + if (isValidEthereumAddress(data.address)) { + return `https://evm.flowscan.io/token/${data.address}`; + } else if (data.symbol.toLowerCase() === 'flow') { + return 'https://flow.com/'; + } + return `https://flowscan.io/account/${data.address}/tokens`; + }; + useEffect(() => { isMounted.current = true; getActive(); @@ -102,7 +117,7 @@ const TokenInfoCard = ({ return () => { isMounted.current = false; }; - }, [token]); + }, [token, getActive]); return ( - data.extensions && window.open(data.extensions.website, '_blank')} - > + window.open(getUrl(data), '_blank')}> {data.name} - {data.extensions && - data.extensions.website && - data.extensions.website.trim() !== '' && } + @@ -209,7 +220,7 @@ const TokenInfoCard = ({ - ${addDotSeparators((balance * price).toFixed(3))} {chrome.i18n.getMessage('USD')} + ${addDotSeparators(balance * price)} {chrome.i18n.getMessage('USD')} {(!childType || childType === 'evm') && ( diff --git a/src/ui/views/TokenDetail/index.tsx b/src/ui/views/TokenDetail/index.tsx index 270ceef8..c704c7ff 100644 --- a/src/ui/views/TokenDetail/index.tsx +++ b/src/ui/views/TokenDetail/index.tsx @@ -129,7 +129,7 @@ const TokenDetail = () => { } setProviders(result); if (result.length === 0) { - const data = await usewallet.openapi.getTokenPrices(); + const data = await usewallet.openapi.getTokenPrices('pricesMap'); const price = await usewallet.openapi.getPricesByAddress(tokenResult!.address, data); if (price) { setPrice(price); @@ -240,8 +240,7 @@ const TokenDetail = () => { /> )} {token === 'flow' && } - {/* {network === 'testnet' || network === 'crescendo' && token === 'flow' && } */} - + {network === 'testnet' && token === 'flow' && } {providers?.length > 0 && ( )} diff --git a/src/ui/views/TokenList/AddTokenConfirmation.tsx b/src/ui/views/TokenList/AddTokenConfirmation.tsx index 952cc292..22fc9aeb 100644 --- a/src/ui/views/TokenList/AddTokenConfirmation.tsx +++ b/src/ui/views/TokenList/AddTokenConfirmation.tsx @@ -1,11 +1,11 @@ +import CloseIcon from '@mui/icons-material/Close'; +import { Box, Typography, Drawer, Grid, Button, IconButton } from '@mui/material'; +import { type TokenInfo } from 'flow-native-token-registry'; import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { Box, Typography, Drawer, Grid, Button, IconButton } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { TokenInfo } from 'flow-native-token-registry'; interface AddTokenConfirmationProps { isConfirmationOpen: boolean; @@ -136,6 +136,7 @@ const AddTokenConfirmation = (props: AddTokenConfirmationProps) => { size="large" sx={{ height: '50px', + width: '100%', borderRadius: '12px', textTransform: 'capitalize', display: 'flex', diff --git a/src/ui/views/Unlock/index.tsx b/src/ui/views/Unlock/index.tsx index 43ebf524..9e266ea3 100644 --- a/src/ui/views/Unlock/index.tsx +++ b/src/ui/views/Unlock/index.tsx @@ -1,14 +1,15 @@ -import React, { useEffect, useRef, useState } from 'react'; // import { useTranslation } from 'react-i18next'; -import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; -import { Typography, Box, FormControl } from '@mui/material'; -import { LLPrimaryButton, LLResetPopup } from 'ui/FRWComponent'; -import { Input } from '@mui/material'; -import { Presets } from 'react-component-transition'; -import CancelIcon from '../../../components/iconfont/IconClose'; +import { Input, Typography, Box, FormControl } from '@mui/material'; import { makeStyles } from '@mui/styles'; -import { openInternalPageInTab } from 'ui/utils/webapi'; +import React, { useEffect, useRef, useState } from 'react'; + +import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import lilo from 'ui/FRWAssets/image/lilo.png'; +import { LLPrimaryButton, LLResetPopup } from 'ui/FRWComponent'; +import { useWallet, useApproval, useWalletRequest } from 'ui/utils'; +import { openInternalPageInTab } from 'ui/utils/webapi'; + +import CancelIcon from '../../../components/iconfont/IconClose'; import './style.css'; const useStyles = makeStyles(() => ({ @@ -33,6 +34,15 @@ const useStyles = makeStyles(() => ({ }, })); +const UsernameError: React.FC = () => ( + + + + {chrome.i18n.getMessage('Incorrect__Password')} + + +); + const Unlock = () => { const wallet = useWallet(); const classes = useStyles(); @@ -69,21 +79,6 @@ const Unlock = () => { } }; - const usernameError = () => ( - - - - {chrome.i18n.getMessage('Incorrect__Password')} - - - ); - return ( { - + { onKeyDown={handleKeyDown} /> - - {showError && ( - - {usernameError()} + + + + - )} - - - {/* */} + + diff --git a/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx b/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx index 724f4af8..789a9134 100644 --- a/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx +++ b/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { Typography, Box, @@ -9,16 +9,19 @@ import { FormControl, } from '@mui/material'; import { styled } from '@mui/material/styles'; -import { useHistory } from 'react-router-dom'; -import { LLPrimaryButton, LLFormHelperText } from '../../../FRWComponent'; -import { useWallet } from 'ui/utils'; -import { useForm } from 'react-hook-form'; -import { withPrefix, isValidEthereumAddress } from '../../../utils/address'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { Contract, ethers } from 'ethers'; +import React, { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { useHistory } from 'react-router-dom'; + import { storage } from '@/background/webapi'; -import AddCustomEvmForm from './CustomEvmForm'; import { EVM_ENDPOINT } from 'consts'; +import { useWallet } from 'ui/utils'; + +import { withPrefix, isValidEthereumAddress } from '../../../../shared/utils/address'; +import { LLPrimaryButton, LLFormHelperText } from '../../../FRWComponent'; + +import AddCustomEvmForm from './CustomEvmForm'; const StyledInput = styled(InputBase)(({ theme }) => ({ zIndex: 1, diff --git a/src/ui/views/Wallet/AddCustom/CustomEvmForm.tsx b/src/ui/views/Wallet/AddCustom/CustomEvmForm.tsx index e09396e6..2f2b2d75 100644 --- a/src/ui/views/Wallet/AddCustom/CustomEvmForm.tsx +++ b/src/ui/views/Wallet/AddCustom/CustomEvmForm.tsx @@ -1,5 +1,5 @@ -import React from 'react'; import { Typography, Box, Stack } from '@mui/material'; +import React from 'react'; const CustomEvmForm = ({ coinInfo }) => { const renderContent = () => ( diff --git a/src/ui/views/Wallet/Coinlist.tsx b/src/ui/views/Wallet/Coinlist.tsx index aba4cead..a09153a8 100644 --- a/src/ui/views/Wallet/Coinlist.tsx +++ b/src/ui/views/Wallet/Coinlist.tsx @@ -1,8 +1,3 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { useHistory } from 'react-router-dom'; -import theme from '../../style/LLTheme'; -import { formatLargeNumber } from 'ui/utils/number'; import { Typography, ListItem, @@ -14,7 +9,14 @@ import { List, IconButton, } from '@mui/material'; +import { Box } from '@mui/system'; +import React, { useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; + +import { formatLargeNumber } from 'ui/utils/number'; + import IconCreate from '../../../components/iconfont/IconCreate'; + import TokenDropdown from './TokenDropdown'; const CoinList = ({ data, ableFt, isActive, childType, coinLoading }) => { @@ -156,7 +158,7 @@ const CoinList = ({ data, ableFt, isActive, childType, coinLoading }) => { }; return ( - + <> {!childType && ( @@ -217,7 +219,11 @@ const CoinList = ({ data, ableFt, isActive, childType, coinLoading }) => { @@ -238,7 +244,7 @@ const CoinList = ({ data, ableFt, isActive, childType, coinLoading }) => { ); })} - + ); }; diff --git a/src/ui/views/Wallet/OnRampList.tsx b/src/ui/views/Wallet/OnRampList.tsx index 6c26bb22..4e3aec85 100644 --- a/src/ui/views/Wallet/OnRampList.tsx +++ b/src/ui/views/Wallet/OnRampList.tsx @@ -1,28 +1,31 @@ -import React, { useEffect, useState } from 'react'; +import { generateOnRampURL } from '@coinbase/cbpay-js'; +import CloseIcon from '@mui/icons-material/Close'; +import { Typography, ButtonBase, Grid, IconButton } from '@mui/material'; import { Box } from '@mui/system'; +import React, { useCallback, useEffect, useState } from 'react'; + import { useWallet } from 'ui/utils'; + // import theme from '../../style/LLTheme'; -import { Typography, ButtonBase, Grid, IconButton } from '@mui/material'; // import { initOnRamp } from '@coinbase/cbpay-js'; -import { generateOnRampURL } from '@coinbase/cbpay-js'; // import { LLHeader } from '@/ui/FRWComponent'; // import Coinbase from '../../FRWAssets/svg/coinbasepay-txt.svg'; -import CloseIcon from '@mui/icons-material/Close'; -import MoonPay from '../../FRWAssets/svg/moonpay.svg'; + import Coinbase from '../../FRWAssets/svg/coinbase-pay.svg'; +import MoonPay from '../../FRWAssets/svg/moonpay.svg'; const OnRampList = ({ close }) => { const wallet = useWallet(); const [address, setAddress] = useState(null); - const loadAddress = async () => { + const loadAddress = useCallback(async () => { const address = await wallet.getCurrentAddress(); setAddress(address); - }; + }, [wallet]); useEffect(() => { loadAddress(); - }, []); + }, [loadAddress]); const loadMoonPay = async () => { if (!address) { @@ -39,6 +42,8 @@ const OnRampList = ({ close }) => { url: response?.data?.url, }); } + + wallet.trackOnRampClicked('moonpay'); }; const loadCoinbasePay = async () => { @@ -56,6 +61,7 @@ const OnRampList = ({ close }) => { url: onRampURL, }); } + wallet.trackOnRampClicked('coinbase'); }; return ( diff --git a/src/ui/views/Wallet/TokenDropdown.tsx b/src/ui/views/Wallet/TokenDropdown.tsx index 9d6c77a0..b6c9d2b6 100644 --- a/src/ui/views/Wallet/TokenDropdown.tsx +++ b/src/ui/views/Wallet/TokenDropdown.tsx @@ -1,6 +1,7 @@ -import React, { useState } from 'react'; import { Box, IconButton, Menu, MenuItem } from '@mui/material'; +import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; + import IconCreate from '../../../components/iconfont/IconCreate'; const TokenDropdown = () => { diff --git a/src/ui/views/Wallet/TransferList.tsx b/src/ui/views/Wallet/TransferList.tsx index 9cc2c8fd..a46675ec 100644 --- a/src/ui/views/Wallet/TransferList.tsx +++ b/src/ui/views/Wallet/TransferList.tsx @@ -1,8 +1,6 @@ -import React, { useEffect, useState } from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { useWallet } from 'ui/utils'; -import { formatString } from 'ui/utils/address'; -import theme from '../../style/LLTheme'; +import CallMadeRoundedIcon from '@mui/icons-material/CallMadeRounded'; +import CallReceivedRoundedIcon from '@mui/icons-material/CallReceivedRounded'; +import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded'; import { Typography, ListItem, @@ -13,15 +11,17 @@ import { ListItemButton, CardMedia, Button, + Box, } from '@mui/material'; -import activity from 'ui/FRWAssets/svg/activity.svg'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; +import React, { useCallback, useEffect, useState } from 'react'; + +import { formatString } from '@/shared/utils/address'; +import activity from 'ui/FRWAssets/svg/activity.svg'; +import { useWallet } from 'ui/utils'; // import IconExec from '../../../components/iconfont/IconExec'; -import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded'; // import ExpandLessRoundedIcon from '@mui/icons-material/ExpandLessRounded'; -import CallMadeRoundedIcon from '@mui/icons-material/CallMadeRounded'; -import CallReceivedRoundedIcon from '@mui/icons-material/CallReceivedRounded'; dayjs.extend(relativeTime); const TransferList = ({ setCount }) => { @@ -34,7 +34,7 @@ const TransferList = ({ setCount }) => { const [address, setAddress] = useState('0x'); const [showButton, setShowButton] = useState(false); - const fetchTransaction = async () => { + const fetchTransaction = useCallback(async () => { setLoading(true); const monitor = await wallet.getMonitor(); setMonitor(monitor); @@ -52,17 +52,20 @@ const TransferList = ({ setCount }) => { setShowButton(data['count'] > 15); } setTx(data['list']); - } catch (e) { + } catch { setLoading(false); } - }; + }, [wallet, setCount]); - const extMessageHandler = (req) => { - if (req.msg === 'transferListReceived') { - fetchTransaction(); - } - return true; - }; + const extMessageHandler = useCallback( + (req) => { + if (req.msg === 'transferListReceived') { + fetchTransaction(); + } + return true; + }, + [fetchTransaction] + ); useEffect(() => { fetchTransaction(); @@ -71,7 +74,7 @@ const TransferList = ({ setCount }) => { return () => { chrome.runtime.onMessage.removeListener(extMessageHandler); }; - }, []); + }, [extMessageHandler, fetchTransaction]); const timeConverter = (timeStamp: number) => { let time = dayjs.unix(timeStamp); @@ -84,6 +87,14 @@ const TransferList = ({ setCount }) => { const EndListItemText = (props) => { const isReceive = props.txType === 2; const isFT = props.type === 1; + + const calculateMaxWidth = () => { + const textLength = + props.type === 1 ? `${props.amount}`.replace(/^-/, '').length : `${props.token}`.length; + const baseWidth = 30; + const additionalWidth = textLength * 8; + return `${Math.min(baseWidth + additionalWidth, 70)}px`; + }; return ( { - {props.type == 1 + {props.type === 1 ? (isReceive ? '+' : '-') + `${props.amount}`.replace(/^-/, '') : `${props.token}`} @@ -133,7 +148,7 @@ const TransferList = ({ setCount }) => { disableTypography={true} primary={ !isLoading ? ( - + {props.txType === 1 ? ( ) : ( @@ -141,7 +156,13 @@ const TransferList = ({ setCount }) => { )} {props.title} @@ -182,7 +203,7 @@ const TransferList = ({ setCount }) => { }; return ( - + <> {!isLoading ? ( {transaction && transaction.length ? ( @@ -209,9 +230,11 @@ const TransferList = ({ setCount }) => { dense={true} onClick={() => { { - monitor === 'flowscan' - ? window.open(`${flowscanURL}/tx/${tx.hash}`) - : window.open(`${viewSource}/${tx.hash}`); + const url = + monitor === 'flowscan' + ? `${flowscanURL}/tx/${tx.hash}` + : `${viewSource}/${tx.hash}`; + window.open(url); } }} > @@ -301,7 +324,7 @@ const TransferList = ({ setCount }) => { ); }) )} - + ); }; diff --git a/src/ui/views/Wallet/index.tsx b/src/ui/views/Wallet/index.tsx index b6bfe5a1..d47c396c 100644 --- a/src/ui/views/Wallet/index.tsx +++ b/src/ui/views/Wallet/index.tsx @@ -5,10 +5,10 @@ import { Box } from '@mui/system'; import React, { useCallback, useEffect, useState } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import SwipeableViews from 'react-swipeable-views'; -import ReactTextTransition from 'react-text-transition'; import eventBus from '@/eventBus'; import LLComingSoon from '@/ui/FRWComponent/LLComingSoonWarning'; +import { NumberTransition } from '@/ui/FRWComponent/NumberTransition'; import buyIcon from 'ui/FRWAssets/svg/buyIcon.svg'; import iconMove from 'ui/FRWAssets/svg/homeMove.svg'; import receiveIcon from 'ui/FRWAssets/svg/receiveIcon.svg'; @@ -17,8 +17,8 @@ import swapIcon from 'ui/FRWAssets/svg/swapIcon.svg'; import { useWallet } from 'ui/utils'; import { formatLargeNumber } from 'ui/utils/number'; +import { withPrefix } from '../../../shared/utils/address'; import theme from '../../style/LLTheme'; -import { withPrefix } from '../../utils/address'; import MoveBoard from '../MoveBoard'; import CoinList from './Coinlist'; @@ -105,7 +105,7 @@ const WalletTab = ({ network }) => { const currentTime = Date.now(); if (currentTime - lastManualAddressCallTime > 60000) { try { - await wallet.openapi.getManualAddress(); + // await wallet.openapi.getManualAddress(); setlastManualAddressCallTime(currentTime); } catch (error) { console.error('Error getting manual address:', error); @@ -401,15 +401,7 @@ const WalletTab = ({ network }) => { /> */} {`$${formatLargeNumber(balance)}`.split('').map((n, i) => ( - + ))} )} @@ -477,7 +469,6 @@ const WalletTab = ({ network }) => { onMouseEnter={() => setSwapHover(true)} onMouseLeave={() => setSwapHover(false)} onClick={() => { - // eslint-disable-next-line no-restricted-globals window.open(incLink, '_blank', 'noopener,noreferrer'); }} > diff --git a/src/ui/views/WelcomePage/index.tsx b/src/ui/views/WelcomePage/index.tsx index 819aa813..1dc94972 100644 --- a/src/ui/views/WelcomePage/index.tsx +++ b/src/ui/views/WelcomePage/index.tsx @@ -1,19 +1,18 @@ +import { Typography, Button, CardMedia } from '@mui/material'; +import { Box } from '@mui/system'; import React from 'react'; -import { Box, ThemeProvider } from '@mui/system'; -import { Typography, Button, CssBaseline, CardMedia } from '@mui/material'; -import theme from '../../style/LLTheme'; -import RegisterHeader from '../Register/RegisterHeader'; +import { Link } from 'react-router-dom'; + +import IconFlow from '../../../components/iconfont/IconFlow'; import appicon from '../../FRWAssets/image/appicon.png'; import create from '../../FRWAssets/svg/create.svg'; import importPng from '../../FRWAssets/svg/import.svg'; import qr from '../../FRWAssets/svg/scanIcon.svg'; -import { Link } from 'react-router-dom'; -import IconFlow from '../../../components/iconfont/IconFlow'; +import RegisterHeader from '../Register/RegisterHeader'; const WelcomePage = () => { return ( - - + <> { - + ); }; diff --git a/src/ui/views/index.tsx b/src/ui/views/index.tsx index 3c1fbd93..9b18799a 100644 --- a/src/ui/views/index.tsx +++ b/src/ui/views/index.tsx @@ -1,14 +1,13 @@ +import { CssBaseline } from '@mui/material'; import GlobalStyles from '@mui/material/GlobalStyles'; -import { ThemeProvider } from '@mui/material/styles'; -import { createMemoryHistory } from 'history'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; import React from 'react'; import { HashRouter as Router, Route } from 'react-router-dom'; +import themeOptions from '@/ui/style/LLTheme'; import { NewsProvider } from '@/ui/utils/NewsContext'; import { PrivateRoute } from 'ui/component'; -import { WalletProvider } from 'ui/utils'; - -import theme from '../style/LLTheme'; +import { WalletProvider, mixpanelBrowserService } from 'ui/utils'; import Approval from './Approval'; import InnerRoute from './InnerRoute'; @@ -18,11 +17,17 @@ import SortHat from './SortHat'; import SwitchUnlock from './SwitchUnlock'; import Unlock from './Unlock'; +const theme = createTheme(themeOptions); + function Main() { - const history = createMemoryHistory(); + React.useEffect(() => { + // Initialize mixpanel in the popup + // Note: Mixpanel is initialized in the constructor, just calling init here to make sure it is initialized + mixpanelBrowserService.init(); + }, []); + return ( - //@ts-ignore - + @@ -44,6 +49,7 @@ function Main() { const App = ({ wallet }: { wallet: any }) => { return ( + >; -} - -const t = (name) => chrome.i18n.getMessage(name); - -const format = (str, ...args) => { - return args.reduce((m, n) => m.replace('_s_', n), str); -}; - -export { Message, t, format }; - -// const chainsDict = keyBy(CHAINS, 'serverId'); -// export const getChain = (chainId?: string) => { -// if (!chainId) { -// return null; -// } -// return chainsDict[chainId]; -// }; - -export const getPeriodFrequency = (period: Period): PeriodFrequency => { - switch (period) { - case Period.oneDay: - return PeriodFrequency.halfHour; - case Period.oneWeek: - return PeriodFrequency.oneHour; - case Period.oneMonth: - return PeriodFrequency.oneDay; - case Period.threeMonth: - return PeriodFrequency.oneDay; - case Period.oneYear: - return PeriodFrequency.threeDay; - case Period.all: - return PeriodFrequency.oneWeek; - default: - return PeriodFrequency.oneDay; - } -}; diff --git a/tsconfig.json b/tsconfig.json index 4e9c12f7..b0b1a583 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,9 @@ "baseUrl": "./", "experimentalDecorators": true, "emitDecoratorMetadata": true, - "module": "ESNext", - "target": "ES2021", - "moduleResolution": "nodenext", + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "bundler", "noImplicitAny": false, "checkJs": true, "strict": true, diff --git a/webpack.config.js b/webpack.config.js index f78a9871..8e0e241d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,7 @@ +const webpack = require('webpack'); const webpackMerge = require('webpack-merge'); + const commonConfig = require('./build/webpack.common.config'); -const webpack = require('webpack'); -const path = require('path'); const configs = { dev: require('./build/webpack.dev.config'), @@ -27,9 +27,8 @@ const configs = { }), ], resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], fallback: { - http: require.resolve('stream-http'), - https: require.resolve('https-browserify'), buffer: require.resolve('buffer'), url: require.resolve('url/'), }, @@ -37,12 +36,12 @@ const configs = { }, }; -const config = (env) => { +const config = (env, argv) => { if (env.config) { - return webpackMerge.merge(commonConfig, configs[env.config]); + return webpackMerge.merge(commonConfig(env), configs[env.config]); } - return commonConfig; + return commonConfig(env); }; module.exports = config;