diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 034ec5dc..f439ee0e 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -3,19 +3,32 @@ runs: using: composite steps: - uses: actions/checkout@v3 + name: Checkout - uses: actions/setup-node@v3 + name: Install Node.js with: node-version: 16 - registry-url: https://registry.npmjs.org - cache: yarn + + - uses: pnpm/action-setup@v2 + name: Install pnpm + with: + version: 8 + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - uses: actions/cache@v3 - id: install-cache + name: Setup pnpm cache with: - path: node_modules/ - key: ${{ runner.os }}-install-${{ hashFiles('**/yarn.lock') }} + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- - - if: steps.install-cache.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile --ignore-scripts - shell: bash \ No newline at end of file + - name: Install dependencies + shell: bash + run: pnpm install diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2dce0bc5..dcdf76ab 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,13 +2,12 @@ name: CI on: pull_request: - push: + branches: [main, dev] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: ./.github/actions/setup - # - run: yarn build - # - run: yarn test - # - run: yarn make-badges + - run: pnpm -r lint + - run: pnpm -r test diff --git a/.husky/pre-commit b/.husky/pre-commit index fa54b87f..426534c3 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,6 +1,7 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -yarn test && yarn make-badges && git add 'README.md' +pnpm -r lint +pnpm -r test npx lint-staged diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..480303ce --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,206 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +const path = require('path'); +const { lstatSync, readdirSync } = require('fs'); +// get listing of packages in the mono repo +const basePath = path.resolve(__dirname, 'packages'); +const packages = readdirSync(basePath).filter((name: string) => lstatSync(path.join(basePath, name)).isDirectory()); + +const moduleNameMapper: any = {}; +packages.forEach((key: string) => { + moduleNameMapper[`@aelf-web-login/${key}/test/(.+)$`] = `/packages/${key}/test/$1`; + moduleNameMapper[`@aelf-web-login/${key}`] = `/packages/${key}/src`; +}); + +export default { + preset: 'ts-jest', + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/private/var/folders/r5/t47_1bgs5cldtw053qqg01hw0000gn/T/jest_dx", + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + coverageDirectory: 'coverage', + testEnvironment: 'jsdom', + // An array of regexp pattern strings used to skip coverage collection + coveragePathIgnorePatterns: ['/node_modules/', '/__generated__/'], + + // Indicates which provider should be used to instrument code for coverage + // coverageProvider: "babel", + coverageReporters: ['json-summary', 'text'], + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + moduleNameMapper, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: undefined, + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + // testEnvironment: "jest-environment-node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + // testMatch: [ + // "**/__tests__/**/*.[jt]s?(x)", + // "**/?(*.)+(spec|test).[tj]s?(x)" + // ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "/node_modules/" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; diff --git a/package.json b/package.json index 7c5580a0..5154d8e4 100644 --- a/package.json +++ b/package.json @@ -13,13 +13,14 @@ "postinstall": "husky install", "version": "yarn run bootstrap && yarn build", "prebuild": "yarn clean", - "login:dev": "pnpm --filter aelf-web-login dev", - "login:build": "pnpm --filter aelf-web-login build", - "login:pub": "pnpm --filter aelf-web-login pub", - "example": "pnpm --filter @aelf-web-login/example start", - "test": "jest", - "test:browser": "jest --config=jest.browser.config.ts", - "make-badges": "istanbul-badges-readme" + "core:dev": "pnpm --filter @aelf-web-login/core dev", + "core:build": "pnpm --filter @aelf-web-login/core build", + "react:dev": "pnpm --filter @aelf-web-login/react dev", + "react:build": "pnpm --filter @aelf-web-login/react build", + "web:dev": "pnpm --filter @aelf-web-login/web dev", + "web:build": "pnpm --filter @aelf-web-login/web build", + "lib:dev": "concurrently \"pnpm core:dev\" \"pnpm react:dev\"", + "example": "pnpm --filter @aelf-web-login/example start" }, "devDependencies": { "@babel/core": "^7.20.12", @@ -30,7 +31,9 @@ "@commitlint/config-conventional": "^17.1.0", "@jest/globals": "^29.3.1", "@next/bundle-analyzer": "^12.2.4", + "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-image": "^3.0.2", + "@rollup/plugin-node-resolve": "^15.1.0", "@rollup/plugin-url": "^8.0.1", "@tsconfig/recommended": "^1.0.1", "@types/elliptic": "^6.4.14", @@ -38,7 +41,10 @@ "@typescript-eslint/eslint-plugin": "^5.19.0", "@typescript-eslint/parser": "^5.19.0", "babel-jest": "^29.3.1", + "babel-loader": "^9.1.3", "browser-resolve": "^2.0.0", + "concurrently": "^8.2.0", + "css-loader": "^6.8.1", "esbuild": "^0.17.7", "eslint": "^7.32.0", "eslint-config-prettier": "^8.5.0", @@ -48,7 +54,8 @@ "istanbul-badges-readme": "^1.8.5", "jest": "^29.3.1", "jest-environment-jsdom": "^29.4.3", - "lint-staged": ">=13", + "less-loader": "^11.1.3", + "lint-staged": "^13.0.0", "node-fetch": "^3.3.0", "postcss": "^8.4.21", "postcss-url": "^10.1.3", @@ -63,13 +70,14 @@ "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-terser": "^7.0.2", "ts-jest": "^29.0.5", + "ts-loader": "^9.4.0", "ts-node": "^10.9.1", - "typescript": "^4.9.4" + "typescript": "^4.9.4", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4" }, "lint-staged": { "*.{js,jsx,ts,tsx}": "eslint --cache --fix" }, - "version": "0.0.0", - "dependencies": { - } + "version": "0.0.0" } diff --git a/packages/login/.eslintrc.json b/packages/core/.eslintrc.json similarity index 100% rename from packages/login/.eslintrc.json rename to packages/core/.eslintrc.json diff --git a/packages/login/.prettierrc b/packages/core/.prettierrc similarity index 100% rename from packages/login/.prettierrc rename to packages/core/.prettierrc diff --git a/packages/core/global.d.ts b/packages/core/global.d.ts new file mode 100644 index 00000000..bd1fc2cc --- /dev/null +++ b/packages/core/global.d.ts @@ -0,0 +1,2 @@ +declare module 'aelf-sdk'; +declare module 'aelf-bridge'; diff --git a/packages/core/jest.config.ts b/packages/core/jest.config.ts new file mode 100644 index 00000000..8c9c51ff --- /dev/null +++ b/packages/core/jest.config.ts @@ -0,0 +1,5 @@ +import base from '../../jest.config'; + +export default { + ...base, +}; diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 00000000..970690d7 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,71 @@ +{ + "name": "@aelf-web-login/core", + "version": "0.1.0", + "main": "dist/esm/index.js", + "types": "dist/types/index.d.ts", + "exports": { + ".": "./dist/esm/index.js", + "./dist/assets/index.css": "./dist/assets/index.css" + }, + "type": "module", + "module": "./dist/esm/index.js", + "keywords": [ + "antd", + "portkey" + ], + "description": "", + "author": "", + "license": "ISC", + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org" + }, + "files": [ + "dist/*" + ], + "repository": { + "type": "git", + "url": "https://github.com/AElf-devops/aelf-web-login.git", + "directory": "packages/login" + }, + "scripts": { + "prebuild": "rm -rf dist", + "start": "tsc --watch", + "test": "jest", + "lint": "eslint . --ext .tsx,.ts", + "dev": "pnpm run dev:tsc & pnpm run dev:types", + "dev:tsc": "tsc --p tsconfig.esm.json --watch", + "dev:types": "tsc --emitDeclarationOnly --p tsconfig.types.json --watch", + "build:clean": "rm -rf dist", + "build:types": "tsc --emitDeclarationOnly --p tsconfig.types.json", + "build:tsc": "tsc --p tsconfig.esm.json", + "build:cjs": "tsc --p tsconfig.cjs.json", + "build:umd": "rollup --silent --config rollup.config.js", + "build": "npm run build:clean; npm run build:types && npm run build:tsc && npm run build:umd", + "release": "yarn version && yarn build", + "pub": "npm publish" + }, + "dependencies": { + "@portkey/contracts": "^1.2.2", + "@portkey/detect-provider": "1.0.1-alpha.0", + "@portkey/did": "^1.2.2", + "@portkey/did-ui-react": "^1.2.2", + "@portkey/provider-types": "1.0.1-alpha.0", + "@portkey/services": "^1.2.2", + "@portkey/types": "^1.2.2", + "@portkey/utils": "^1.2.2", + "aelf-bridge": "^0.0.10", + "aelf-sdk": "^3.2.40", + "ahooks": "^3.7.7", + "antd": "^4.24.4", + "cancelable-promise": "^4.3.1", + "ismobilejs": "^1.1.1", + "typescript": "^4.9.5" + }, + "devDependencies": { + "@types/uuid": "^8.3.4", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "less": "^4.1.3" + } +} diff --git a/packages/login/rollup.config.js b/packages/core/rollup.config.js similarity index 100% rename from packages/login/rollup.config.js rename to packages/core/rollup.config.js diff --git a/packages/core/src/LoginBase.ts b/packages/core/src/LoginBase.ts new file mode 100644 index 00000000..79649825 --- /dev/null +++ b/packages/core/src/LoginBase.ts @@ -0,0 +1,48 @@ +import { CancelablePromise, EventType, ILogin, LoginState, WalletInfo, WalletType } from './types'; +import { EventEmitter } from 'events'; + +export abstract class LoginBase implements ILogin { + abstract walletInfo: W; + abstract walletType: WalletType; + abstract loginState: LoginState; + + protected _events: EventEmitter; + + constructor() { + this._events = new EventEmitter(); + } + + getLoginEagerlyKey(): string { + return `AElf.WebLogin.${this.walletType}.loginEagerly`; + } + + on(event: EventType, listener: (data: T) => void): void { + this._events.on(event, listener); + } + off(event: EventType, listener: (data: T) => void): void { + this._events.off(event, listener); + } + + emit(event: EventType, data: T) { + this._events.emit(event, data); + } + + canLoginEagerly(): boolean { + return !!localStorage.getItem(this.getLoginEagerlyKey()); + } + + setLoginEagerly(flag: boolean) { + const key = this.getLoginEagerlyKey(); + if (flag) { + localStorage.setItem(key, 'true'); + } else { + localStorage.removeItem(key); + } + } + + abstract loginEagerly(): Promise; + abstract login(): CancelablePromise; + abstract logout(): Promise; + abstract getWalletName(): Promise; + abstract getSignature(signInfo: string): Promise; +} diff --git a/packages/login/src/errors.ts b/packages/core/src/errors.ts similarity index 79% rename from packages/login/src/errors.ts rename to packages/core/src/errors.ts index 2f1a1cdd..50afa67b 100644 --- a/packages/login/src/errors.ts +++ b/packages/core/src/errors.ts @@ -1,14 +1,15 @@ export const ERR_CODE = { - DISCOVER_LOGIN_EAGERLY_FAIL: 10001, + LOGIN_EAGERLY_FAIL: 10001, NETWORK_TYPE_NOT_MATCH: 10002, ACCOUNTS_IS_EMPTY: 10003, USER_CANCEL: 10004, + PORTKEY_SDK_COMMON_ERROR: 10005, }; export const ERR_CODE_MSG: { [key: number]: string; } = { - 10001: 'Discover login eagerly fail', + 10001: 'Login eagerly fail', 10002: 'Network type not match', 10003: 'Accounts is empty', 10004: 'User cancel', diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 00000000..2ddfd0f9 --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,7 @@ +export * from './wallets/portkey'; +export * from './wallets/nightElf'; +export * from './wallets/discover'; +export * from './types'; +export * from './errors'; +export * from './webLogin'; +export * from './utils/newCancalablePromise'; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts new file mode 100644 index 00000000..15ca2a1d --- /dev/null +++ b/packages/core/src/types.ts @@ -0,0 +1,34 @@ +import CancelablePromiseImpl from 'cancelable-promise'; + +export type LoginState = 'initial' | 'logining' | 'logined' | 'logouting'; + +export type WalletType = 'Unknown' | 'Discover' | 'NightElf' | 'PortkeySDK'; + +export type WalletInfo = { + address: string; +}; + +export type EventType = 'logined' | 'cancelLogin' | 'commonError'; + +export interface ILogin { + walletType: WalletType; + walletInfo: W; + loginState: LoginState; + on(event: EventType, listener: (data: T) => void): void; + off(event: EventType, listener: (data: T) => void): void; + emit(event: EventType, data: T): void; + login(): CancelablePromise; + canLoginEagerly(): boolean; + loginEagerly(): Promise; + logout(): Promise; + getWalletName(): Promise; + getSignature(signInfo: string): Promise; +} + +export type CancelablePromise = CancelablePromiseImpl; + +export type CancelablePromiseExecutor = ( + resolve: (value: T | PromiseLike) => void, + reject: (reason?: any) => void, + onCancel: (cancelHandler: () => void) => void, +) => void; diff --git a/packages/core/src/utils/detectWebEnv.ts b/packages/core/src/utils/detectWebEnv.ts new file mode 100644 index 00000000..7cd88023 --- /dev/null +++ b/packages/core/src/utils/detectWebEnv.ts @@ -0,0 +1,28 @@ +import isAElfWallet from './isAElfWallet'; +import isPortkeyApp from './isPortkeyApp'; + +export type WebEnv = 'NightElf' | 'AElfWallet' | 'Discover'; + +export function detectWebEnv(): WebEnv[] { + const win = window as any; + const envList: WebEnv[] = []; + + if (isPortkeyApp()) { + envList.push('Discover'); + return envList; + } + + if (isAElfWallet()) { + envList.push('AElfWallet'); + return envList; + } + + if (win.NightElf) { + envList.push('NightElf'); + } + if (win.portkey) { + envList.push('Discover'); + } + + return envList; +} diff --git a/packages/core/src/utils/isAElfWallet.ts b/packages/core/src/utils/isAElfWallet.ts new file mode 100644 index 00000000..a5ddbb38 --- /dev/null +++ b/packages/core/src/utils/isAElfWallet.ts @@ -0,0 +1,11 @@ +import isMobile from 'ismobilejs'; + +export default function isAElfWallet() { + const mobile = isMobile(navigator); + if (!mobile.any) return false; + const win = window as any; + return ( + (win.android && mobile.android) || + (mobile.apple && win.webkit && win.webkit.messageHandlers && win.webkit.messageHandlers.JSCallback) + ); +} diff --git a/packages/login/src/utils/isPortkeyApp.ts b/packages/core/src/utils/isPortkeyApp.ts similarity index 100% rename from packages/login/src/utils/isPortkeyApp.ts rename to packages/core/src/utils/isPortkeyApp.ts diff --git a/packages/core/src/utils/newCancalablePromise.ts b/packages/core/src/utils/newCancalablePromise.ts new file mode 100644 index 00000000..a1c76190 --- /dev/null +++ b/packages/core/src/utils/newCancalablePromise.ts @@ -0,0 +1,6 @@ +import { CancelablePromise as CancelablePromiseImpl } from 'cancelable-promise'; +import { CancelablePromise, CancelablePromiseExecutor } from '../types'; + +export function newCancelablePromise(executor: CancelablePromiseExecutor): CancelablePromise { + return new CancelablePromiseImpl(executor); +} diff --git a/packages/core/src/wallets/discover/index.ts b/packages/core/src/wallets/discover/index.ts new file mode 100644 index 00000000..60dbaf6f --- /dev/null +++ b/packages/core/src/wallets/discover/index.ts @@ -0,0 +1,35 @@ +import { LoginBase } from '../../LoginBase'; +import { CancelablePromise, LoginState, WalletInfo, WalletType } from '../../types'; + +export type DiscoverWalletInfo = WalletInfo & {}; + +/** + * implement login feature based on detect provider + */ +export class Discover extends LoginBase { + walletInfo: DiscoverWalletInfo; + walletType: WalletType = 'Discover'; + loginState: LoginState = 'initial'; + + constructor() { + super(); + this.walletInfo = { address: '' }; + } + + loginEagerly(): Promise { + throw new Error('Method not implemented.'); + } + + login(): CancelablePromise { + throw new Error('Method not implemented.'); + } + logout(): Promise { + throw new Error('Method not implemented.'); + } + getWalletName(): Promise { + throw new Error('Method not implemented.'); + } + getSignature(signInfo: string): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/core/src/wallets/nightElf/index.ts b/packages/core/src/wallets/nightElf/index.ts new file mode 100644 index 00000000..46e37af1 --- /dev/null +++ b/packages/core/src/wallets/nightElf/index.ts @@ -0,0 +1,35 @@ +import { LoginBase } from '../../LoginBase'; +import { CancelablePromise, LoginState, WalletInfo, WalletType } from '../../types'; + +export type NightElfWalletInfo = WalletInfo & {}; + +/** + * implement login feature based on aelf-bridge + */ +export class NightElf extends LoginBase { + walletInfo: NightElfWalletInfo; + walletType: WalletType = 'NightElf'; + loginState: LoginState = 'initial'; + + constructor() { + super(); + this.walletInfo = { address: '' }; + } + + loginEagerly(): Promise { + throw new Error('Method not implemented.'); + } + + login(): CancelablePromise { + throw new Error('Method not implemented.'); + } + logout(): Promise { + throw new Error('Method not implemented.'); + } + getWalletName(): Promise { + throw new Error('Method not implemented.'); + } + getSignature(signInfo: string): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/core/src/wallets/portkey/PortkeySDK.ts b/packages/core/src/wallets/portkey/PortkeySDK.ts new file mode 100644 index 00000000..cec3051b --- /dev/null +++ b/packages/core/src/wallets/portkey/PortkeySDK.ts @@ -0,0 +1,29 @@ +import { DID } from '@portkey/did'; +import { LoginBase } from '../../LoginBase'; +import { CancelablePromise, LoginState, WalletInfo, WalletType } from '../../types'; + +export type PortkeySDKWalletInfo = WalletInfo & { + originChainId?: string; + did?: DID; +}; + +/** + * implement login feature based on portkey sdk + */ +export abstract class PortkeySDK extends LoginBase { + walletInfo: PortkeySDKWalletInfo; + walletType: WalletType = 'PortkeySDK'; + loginState: LoginState = 'initial'; + + constructor() { + super(); + this.walletInfo = { address: '' }; + } + + getWalletName(): Promise { + throw new Error('Method not implemented.'); + } + getSignature(signInfo: string): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/core/src/wallets/portkey/index.ts b/packages/core/src/wallets/portkey/index.ts new file mode 100644 index 00000000..9a75cb31 --- /dev/null +++ b/packages/core/src/wallets/portkey/index.ts @@ -0,0 +1 @@ +export * from './PortkeySDK'; diff --git a/packages/core/src/webLogin.ts b/packages/core/src/webLogin.ts new file mode 100644 index 00000000..3184eae8 --- /dev/null +++ b/packages/core/src/webLogin.ts @@ -0,0 +1,44 @@ +import { LoginBase } from './LoginBase'; +import { CancelablePromise, ILogin, LoginState, WalletInfo, WalletType } from './types'; +import { DiscoverWalletInfo } from './wallets/discover'; +import { NightElfWalletInfo } from './wallets/nightElf'; +import { PortkeySDKWalletInfo } from './wallets/portkey'; + +export type WebLoginWalletInfo = WalletInfo & { + nightElf?: NightElfWalletInfo | undefined; + portkey?: PortkeySDKWalletInfo | undefined; + discover?: DiscoverWalletInfo | undefined; +}; + +export abstract class WebLogin extends LoginBase { + walletInfo: WebLoginWalletInfo; + walletType: WalletType = 'Unknown'; + loginState: LoginState = 'initial'; + + protected _current: ILogin | undefined; + + constructor() { + super(); + this.walletInfo = { address: '' }; + } + + abstract setLoginEagerly(flag: boolean): void; + abstract canLoginEagerly(): boolean; + abstract loginEagerly(): Promise; + abstract login(): CancelablePromise; + abstract logout(): Promise; + + getWalletName(): Promise { + if (!this._current) { + throw new Error('No wallet logined'); + } + return this._current.getWalletName(); + } + + getSignature(signInfo: string): Promise { + if (!this._current) { + throw new Error('No wallet logined'); + } + return this._current.getSignature(signInfo); + } +} diff --git a/packages/core/test/utils.test.ts b/packages/core/test/utils.test.ts new file mode 100644 index 00000000..ef5f13a1 --- /dev/null +++ b/packages/core/test/utils.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from '@jest/globals'; +import isAElfWallet from '../src/utils/isAElfWallet'; +import isPortkeyApp from '../src/utils/isPortkeyApp'; + +describe('utils', () => { + test('isAElfWallet', () => { + expect(isAElfWallet()).toBe(false); + }); + + test('isPortkeyApp', () => { + expect(isPortkeyApp()).toBe(false); + }); +}); diff --git a/packages/login/tsconfig.cjs.json b/packages/core/tsconfig.cjs.json similarity index 100% rename from packages/login/tsconfig.cjs.json rename to packages/core/tsconfig.cjs.json diff --git a/packages/login/tsconfig.esm.json b/packages/core/tsconfig.esm.json similarity index 100% rename from packages/login/tsconfig.esm.json rename to packages/core/tsconfig.esm.json diff --git a/packages/login/tsconfig.json b/packages/core/tsconfig.json similarity index 100% rename from packages/login/tsconfig.json rename to packages/core/tsconfig.json diff --git a/packages/login/tsconfig.types.json b/packages/core/tsconfig.types.json similarity index 100% rename from packages/login/tsconfig.types.json rename to packages/core/tsconfig.types.json diff --git a/packages/example/package.json b/packages/example/package.json index e92b618b..eb8387e4 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -10,7 +10,8 @@ "@types/react-dom": "^18.0.0", "react-dom": "^18.0.0", "react-scripts": "^5.0.1", - "aelf-web-login": "workspace:*", + "@aelf-web-login/core": "workspace:*", + "@aelf-web-login/react": "workspace:*", "antd": "^4.24.4", "ahooks": "^3.7.7", "react": "^18.2.0", diff --git a/packages/example/src/App.tsx b/packages/example/src/App.tsx index d051cbad..ffe13e5f 100644 --- a/packages/example/src/App.tsx +++ b/packages/example/src/App.tsx @@ -1,13 +1,8 @@ -import { WalletType, WebLoginEvents, WebLoginState, getConfig, useWebLogin, useWebLoginEvent } from 'aelf-web-login'; import VConsole from 'vconsole'; -import MultiWallets from './components/MultiWallets'; -import CallContract from './components/CallContract'; import { useState } from 'react'; -import { usePortkeyLock } from 'aelf-web-login'; -import { Tabs } from 'antd'; +import { Button, Tabs } from 'antd'; import isMobile from './utils/isMobile'; -import Signature from './components/Signature'; -import Events from './components/Events'; +import { usePortkeyUISDK } from '@aelf-web-login/react'; const win = window as any; let showVConsole = () => {}; @@ -19,63 +14,14 @@ if (isMobile() || win.ReactNativeWebView) { } export default function App() { - const config = getConfig(); - const [selectedIndex, setSelectedIndex] = useState(0); - const { wallet, walletType, login, loginEagerly, logout, loginState } = useWebLogin(); - const { isUnlocking, lock } = usePortkeyLock(); - - console.log(loginState); + const portkeySDK = usePortkeyUISDK(); return ( -
-

Login

-
-
- {getConfig().chainId} wallet: {wallet.name} {wallet.address} -
-
login state: {loginState}
-
- - - - - +
+
+ +
- , - }, - { - label: 'Call contracts', - key: CallContract.name, - children: , - }, - { - label: 'Use multiple wallets', - key: MultiWallets.name, - children: , - }, - { - label: 'Signature', - key: Signature.name, - children: , - }, - ]} - />
); } diff --git a/packages/example/src/components/CallContract.tsx b/packages/example/src/components/CallContract.tsx deleted file mode 100644 index ee6f6538..00000000 --- a/packages/example/src/components/CallContract.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { CallContractParams, WebLoginState, useCallContract, useWebLogin } from 'aelf-web-login'; -import { useState } from 'react'; -import configJson from '../assets/config.json'; -import configTdvwJson from '../assets/config.tdvw.json'; -import { useGetAccount } from 'aelf-web-login'; -import { SendOptions } from '@portkey/types'; - -async function callContractWithLog( - callContract: (params: CallContractParams, sendOptions?: SendOptions | undefined) => Promise, - params: CallContractParams, -): Promise { - console.log('call', params); - const res = await callContract(params); - console.log('res', res); - return res; -} - -function useExampleCall(name: string, func: () => any) { - const [result, setResult] = useState({}); - const { loginState } = useWebLogin(); - - const onClick = async () => { - try { - const res = await func(); - if (res.error) { - console.error(res.error); - return; - } - console.log(name, 'res', res); - setResult(res); - } catch (error) { - console.log(error); - setResult({ error: error.message }); - } - }; - - return { - name, - render: () => { - return ( - <> -
-

{name}:

-
- -
-

Result

-
{JSON.stringify(result, null, '  ')}
-
-
- - ); - }, - }; -} - -export default function CallContract() { - const { wallet } = useWebLogin(); - console.log(wallet); - const getAccountTDVW = useGetAccount('tDVW'); - const { callViewMethod, callSendMethod } = useCallContract(); - const { callViewMethod: callViewMethodTDVW, callSendMethod: callSendMethodTDVW } = useCallContract({ - chainId: 'tDVW', - rpcUrl: 'https://tdvw-test-node.aelf.io', - }); - - const { callViewMethod: callViewMethodTDVV, callSendMethod: callSendMethodTDVV } = useCallContract({ - chainId: 'tDVV', - rpcUrl: 'http://192.168.66.106:8000', - }); - - const examples = [ - useExampleCall('call getBalance', async () => { - return callContractWithLog(callViewMethod, { - contractAddress: configJson.multiToken, - methodName: 'GetBalance', - args: { - symbol: 'ELF', - owner: wallet.address, - }, - }); - }), - - useExampleCall('Buy 1 WRITE', async () => { - return await callContractWithLog(callSendMethod, { - contractAddress: configJson.tokenConverter, - methodName: 'Buy', - args: { - symbol: configJson.resourceTokens[0].symbol, - amount: 1 * Math.pow(10, configJson.resourceTokens[0].decimals), - }, - }); - }), - - useExampleCall('call getBalance in tDVW', async () => { - return callContractWithLog(callViewMethodTDVW, { - contractAddress: configTdvwJson.multiToken, - methodName: 'GetBalance', - args: { - symbol: 'ELF', - owner: await getAccountTDVW(), - }, - }); - }), - - useExampleCall('Buy 1 WRITE in tDVW', async () => { - return await callContractWithLog(callSendMethod, { - contractAddress: configTdvwJson.tokenConverter, - methodName: 'Buy', - args: { - symbol: configJson.resourceTokens[0].symbol, - amount: 1 * Math.pow(10, configJson.resourceTokens[0].decimals), - }, - }); - }), - - useExampleCall('Approve in tDVW', async () => { - return await callContractWithLog(callSendMethodTDVW, { - contractAddress: configTdvwJson.multiToken, - methodName: 'Approve', - args: { - symbol: 'ELF', - spender: configTdvwJson.multiToken, - amount: '100000000', - }, - }); - }), - ]; - return ( -
- {examples.map((example, index) => { - return
{example.render()}
; - })} -
- ); -} diff --git a/packages/example/src/components/Events.tsx b/packages/example/src/components/Events.tsx deleted file mode 100644 index 606ae3b2..00000000 --- a/packages/example/src/components/Events.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { WebLoginEvents, useWebLoginEvent } from 'aelf-web-login'; -import { useState } from 'react'; - -export default function Events() { - const [events, setEvents] = useState([]); - for (const key in WebLoginEvents) { - useWebLoginEvent(WebLoginEvents[key], (data: any) => { - console.log(WebLoginEvents[key], data); - events.push({ - type: key, - data, - }); - setEvents([...events]); - }); - } - return ( - <> -
-
- {events.map((item, index) => { - return
{`${item.type} ${JSON.stringify(item.data)}`}
; - })} -
-
- - ); -} diff --git a/packages/example/src/components/MultiWallets.tsx b/packages/example/src/components/MultiWallets.tsx deleted file mode 100644 index 76cb80dc..00000000 --- a/packages/example/src/components/MultiWallets.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { WalletType, useMultiWallets, SwitchWalletType } from 'aelf-web-login'; - -export default function MultiWallets() { - const { wallets, switching, current, switchWallet } = useMultiWallets(); - - console.log('current', current); - console.log('wallets', wallets); - - return ( -
-
switching: {switching ? 'switching wallet' : ''}
-
- - - -
-
- ); -} diff --git a/packages/example/src/components/Signature.tsx b/packages/example/src/components/Signature.tsx deleted file mode 100644 index f74a79aa..00000000 --- a/packages/example/src/components/Signature.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { WalletType, useMultiWallets, SwitchWalletType, useWebLogin } from 'aelf-web-login'; -import { useState } from 'react'; - -export default function Signature() { - const { wallet, getSignature } = useWebLogin(); - const [signInfo, setSignInfo] = useState(''); - const [signed, setSigned] = useState(''); - - const sign = async () => { - const signature = await getSignature({ - signInfo, - appName: '', - address: '', - }); - console.log('signature', signature); - setSigned(signature.signature); - }; - - return ( -
-
- - setSignInfo(e.target.value)} /> -
-
- ); -} diff --git a/packages/example/src/config.ts b/packages/example/src/config.ts index 5aeebb99..1f0bfed1 100644 --- a/packages/example/src/config.ts +++ b/packages/example/src/config.ts @@ -1,64 +1,64 @@ -import { setGlobalConfig } from 'aelf-web-login'; +// import { setGlobalConfig } from 'aelf-web-login'; -const APPNAME = 'explorer.aelf.io'; -const WEBSITE_ICON = 'https://explorer.aelf.io/favicon.main.ico'; -const CHAIN_ID = 'tDVW'; -const NETWORK: string = 'TESTNET'; -const IS_MAINNET = NETWORK === 'MAIN'; +// const APPNAME = 'explorer.aelf.io'; +// const WEBSITE_ICON = 'https://explorer.aelf.io/favicon.main.ico'; +// const CHAIN_ID = 'tDVW'; +// const NETWORK: string = 'TESTNET'; +// const IS_MAINNET = NETWORK === 'MAIN'; -const RPC_SERVER = 'https://explorer-test.aelf.io/chain'; +// const RPC_SERVER = 'https://explorer-test.aelf.io/chain'; -const graphQLServer = !IS_MAINNET - ? 'https://dapp-portkey-test.portkey.finance' - : 'https://dapp-portkey.portkey.finance'; +// const graphQLServer = !IS_MAINNET +// ? 'https://dapp-portkey-test.portkey.finance' +// : 'https://dapp-portkey.portkey.finance'; -const portkeyApiServer = !IS_MAINNET - ? 'https://did-portkey-test.portkey.finance' - : 'https://did-portkey.portkey.finance'; +// const portkeyApiServer = !IS_MAINNET +// ? 'https://did-portkey-test.portkey.finance' +// : 'https://did-portkey.portkey.finance'; -// did.config.setConfig -export const connectUrl = !IS_MAINNET - ? 'https://auth-portkey-test.portkey.finance' - : 'https://auth-portkey.portkey.finance'; +// // did.config.setConfig +// export const connectUrl = !IS_MAINNET +// ? 'https://auth-portkey-test.portkey.finance' +// : 'https://auth-portkey.portkey.finance'; -let portkeyScanUrl = `${graphQLServer}/Portkey_DID/PortKeyIndexerCASchema/graphql`; -// portkeyScanUrl = '/AElfIndexer_DApp/PortKeyIndexerCASchema/graphql'; +// let portkeyScanUrl = `${graphQLServer}/Portkey_DID/PortKeyIndexerCASchema/graphql`; +// // portkeyScanUrl = '/AElfIndexer_DApp/PortKeyIndexerCASchema/graphql'; -setGlobalConfig({ - appName: APPNAME, - chainId: CHAIN_ID, - networkType: NETWORK as any, - defaultRpcUrl: RPC_SERVER, - portkey: { - useLocalStorage: true, - graphQLUrl: portkeyScanUrl, - connectUrl: connectUrl, - requestDefaults: { - baseURL: portkeyApiServer, - timeout: 30000, - }, - socialLogin: { - Portkey: { - websiteName: APPNAME, - websiteIcon: WEBSITE_ICON, - }, - }, - } as any, - aelfReact: { - appName: APPNAME, - nodes: { - AELF: { - chainId: 'AELF', - rpcUrl: RPC_SERVER, - }, - tDVW: { - chainId: 'tDVW', - rpcUrl: RPC_SERVER, - }, - tDVV: { - chainId: 'tDVV', - rpcUrl: 'http://192.168.66.106:8000', - }, - }, - }, -}); +// setGlobalConfig({ +// appName: APPNAME, +// chainId: CHAIN_ID, +// networkType: NETWORK as any, +// defaultRpcUrl: RPC_SERVER, +// portkey: { +// useLocalStorage: true, +// graphQLUrl: portkeyScanUrl, +// connectUrl: connectUrl, +// requestDefaults: { +// baseURL: portkeyApiServer, +// timeout: 30000, +// }, +// socialLogin: { +// Portkey: { +// websiteName: APPNAME, +// websiteIcon: WEBSITE_ICON, +// }, +// }, +// } as any, +// aelfReact: { +// appName: APPNAME, +// nodes: { +// AELF: { +// chainId: 'AELF', +// rpcUrl: RPC_SERVER, +// }, +// tDVW: { +// chainId: 'tDVW', +// rpcUrl: RPC_SERVER, +// }, +// tDVV: { +// chainId: 'tDVV', +// rpcUrl: 'http://192.168.66.106:8000', +// }, +// }, +// }, +// }); diff --git a/packages/example/src/index.css b/packages/example/src/index.css index 56d9c32d..fcb2e023 100644 --- a/packages/example/src/index.css +++ b/packages/example/src/index.css @@ -1,34 +1,10 @@ -.content { - width: 500px; - margin: 0 auto; - margin-top: 100px; - font-size: 14px; -} - -h2 { - padding: 10px; +.app-theme-switch { + position: absolute; + top: 10px; + right: 10px; } -h3 { - padding: 5px; -} - -.buttons, .contract { - padding: 20px; -} - -button { - padding: 5px; - margin: 10px; -} - -button:disabled { - color: #ccc; - cursor: not-allowed; +.example-app { + margin: 0 auto; } -.contract .result { - background: #eee; - padding: 5px; - min-height: 100px; -} diff --git a/packages/example/src/index.tsx b/packages/example/src/index.tsx index d7572401..861173e7 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -1,77 +1,38 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { createRoot } from 'react-dom/client'; +import { WebLoginProvider } from '@aelf-web-login/react'; +import { Switch } from 'antd'; import 'antd/dist/antd.css'; import '@portkey/did-ui-react/dist/assets/index.css'; -import 'aelf-web-login/dist/assets/index.css'; +import '@aelf-web-login/react/dist/assets/index.css'; import './index.css'; import './config'; -import { WebLoginProvider } from 'aelf-web-login'; -import { PortkeyProvider, SignIn, SignInInterface, SignInProps } from '@portkey/did-ui-react'; import App from './App'; -import { createPortal } from 'react-dom'; - -const SignInProxy = React.forwardRef(function SignInProxy(props: SignInProps, ref: React.Ref) { - const [renderRoot, setRenderRoot] = React.useState(); - useEffect(() => { - const container = (document.querySelector('#sign-in-container') || document.createElement('div')) as HTMLElement; - container.id = 'sign-in-container'; - document.body.appendChild(container); - setRenderRoot(container); - }, []); - if (!renderRoot) { - return <>; - } - return createPortal(, renderRoot!); -}); function Index() { + const [theme, setTheme] = useState<'dark' | 'light'>('light'); return ( - - { - console.log(123); - openStore(); - }, - onClick: continueDefaultBehaviour => { - continueDefaultBehaviour(); - }, - }} - portkey={{ - autoShowUnlock: false, - checkAccountInfoSync: true, - design: 'SocialDesign', - SignInComponent: React.forwardRef(function SignInProxy(props: SignInProps, ref: React.Ref) { - return ; - }), - }} - discover={{ - autoRequestAccount: false, - autoLogoutOnAccountMismatch: true, - autoLogoutOnChainMismatch: true, - autoLogoutOnDisconnected: true, - autoLogoutOnNetworkMismatch: true, - onClick: continueDefaultBehaviour => { - continueDefaultBehaviour(); - }, - onPluginNotFound: openStore => { - console.log(234); - openStore(); - }, - }}> - - - + + + setTheme(checked ? 'dark' : 'light')} + /> + ); } + const container = document.getElementById('root'); const root = createRoot(container!); root.render( diff --git a/packages/login/global.d.ts b/packages/login/global.d.ts deleted file mode 100644 index 09e9efb2..00000000 --- a/packages/login/global.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module 'aelf-sdk'; -declare module 'aelf-bridge'; -declare module '@aelf-react/core/dist/utils/NightElf/AelfBridgeCheck'; -declare module '@aelf-react/core/dist/utils/NightElf/NightElfCheck'; diff --git a/packages/login/index.less b/packages/login/index.less deleted file mode 100644 index ca3e3505..00000000 --- a/packages/login/index.less +++ /dev/null @@ -1,234 +0,0 @@ -.aelf-web-login.aelf-extra-wallets { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.aelf-web-login.aelf-extra-wallets .social-header { - width: 100%; -} -.aelf-web-login.aelf-extra-wallets .social-header .header { - display: flex; -} -.aelf-web-login.aelf-extra-wallets .social-header .header .header-btn { - padding: 0; - margin: 24px -8px 0 auto; -} -.aelf-web-login.aelf-extra-wallets .social-header .title-icon { - width: 56px; - height: 56px; - margin: 16px auto; -} -.aelf-web-login.aelf-extra-wallets .social-header .title { - text-align: center; - font-style: normal; - font-weight: 600; - font-size: 22px; - line-height: 28px; - color: #25272a; -} -.aelf-web-login.aelf-extra-wallets .default-header .title { - font-style: normal; - font-weight: 500; - font-size: 14px; - line-height: 22px; - color: #5c6764; -} -.aelf-web-login.aelf-extra-wallets .wallet-entries.social-content { - width: 100%; - display: flex; - flex-direction: column; - gap: 12px; - margin-top: 32px; - margin-bottom: 48px; -} - -.aelf-web-login.aelf-extra-wallets .wallet-entries.web2-content { - display: flex; - flex-direction: row; - gap: 8px; -} - -.aelf-web-login.aelf-extra-wallets .social-content .plugin-entry { - width: 100%; - height: 56px; - padding-left: 40px; - display: flex; - flex-direction: row; - align-items: center; - cursor: pointer; - user-select: none; - border-radius: 4px; - border: 1px solid #c5cbd5; - background: #fff; -} - -.aelf-web-login.aelf-extra-wallets .wallet-entries.web2-content .plugin-entry { - height: 48px; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - padding-left: 0; - padding-right: 0; -} - -.aelf-web-login.aelf-extra-wallets .social-content .plugin-entry .icon { - width: 28px; - height: 28px; - margin-right: 12px; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - cursor: pointer; - user-select: none; -} -.aelf-web-login.aelf-extra-wallets .social-content .plugin-entry .icon.elf { - background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9Ikljb24gLyBDb2luIj4KPGNpcmNsZSBpZD0iQ2lyY2xlIiBjeD0iMTIiIGN5PSIxMiIgcj0iMTEuNSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iI0U2RTdFOSIvPgo8cGF0aCBpZD0iU2hhcGUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTMuMDk1NiA3Ljc1MTI5QzEzLjkxMDYgNy43NTEyOSAxNC41NzEyIDcuMDkwNjMgMTQuNTcxMiA2LjI3NTY3QzE0LjU3MTIgNS40NjA3MSAxMy45MTA2IDQuODAwMDUgMTMuMDk1NiA0LjgwMDA1QzEyLjI4MDcgNC44MDAwNSAxMS42MiA1LjQ2MDcxIDExLjYyIDYuMjc1NjdDMTEuNjIgNy4wOTA2MyAxMi4yODA3IDcuNzUxMjkgMTMuMDk1NiA3Ljc1MTI5Wk0xOS43NjEzIDEyQzE5Ljc2MTMgMTMuNjU4MSAxOC40MTczIDE1LjAwMjIgMTYuNzU5MiAxNS4wMDIyQzE1LjEwMTIgMTUuMDAyMiAxMy43NTcxIDEzLjY1ODEgMTMuNzU3MSAxMkMxMy43NTcxIDEwLjM0MiAxNS4xMDEyIDguOTk3OTMgMTYuNzU5MiA4Ljk5NzkzQzE4LjQxNzMgOC45OTc5MyAxOS43NjEzIDEwLjM0MiAxOS43NjEzIDEyWk0xNC41NzEyIDE3LjcyNDRDMTQuNTcxMiAxOC41Mzk0IDEzLjkxMDYgMTkuMiAxMy4wOTU2IDE5LjJDMTIuMjgwNyAxOS4yIDExLjYyIDE4LjUzOTQgMTEuNjIgMTcuNzI0NEMxMS42MiAxNi45MDk1IDEyLjI4MDcgMTYuMjQ4OCAxMy4wOTU2IDE2LjI0ODhDMTMuOTEwNiAxNi4yNDg4IDE0LjU3MTIgMTYuOTA5NSAxNC41NzEyIDE3LjcyNDRaTTUuNTM5NDQgNy44NTMwNUM1LjEwNjkzIDguOTk3OTMgNS43MTc1MyAxMC4yOTU1IDYuODYyNDEgMTAuNzI4QzcuNjI1NjYgMTEuMDA3OCA4LjQzOTggMTAuODU1MiA5LjAyNDk1IDEwLjM3MThDOS41NTkyMyA5Ljk5MDE1IDEwLjI0NjIgOS44NjI5NSAxMC45MDc2IDEwLjExNzRDMTEuMzQwMSAxMC4yNyAxMS42NzA5IDEwLjU0OTkgMTEuODk5OSAxMC45MDYxTDExLjkyNTMgMTAuOTU2OUMxMi4wMjcxIDExLjEwOTYgMTIuMTc5NyAxMS4yNjIyIDEyLjM4MzMgMTEuMzEzMUMxMi44NDEyIDExLjQ5MTIgMTMuMzc1NSAxMS4yMzY4IDEzLjUyODEgMTAuNzc4OEMxMy43MDYyIDEwLjMyMDkgMTMuNDUxOCA5Ljc4NjYyIDEyLjk5MzkgOS42MzM5N0MxMi43OTAzIDkuNTU3NjUgMTIuNTg2OCA5LjU1NzY1IDEyLjM4MzMgOS42MzM5N0MxMS45NzYyIDkuNzYxMTggMTEuNTE4MiA5Ljc2MTE4IDExLjA4NTcgOS42MDg1M0MxMC40NDk3IDkuMzc5NTUgMTAuMDE3MiA4Ljg3MDcyIDkuODM5MDkgOC4yODU1Nkw5LjgxMzY1IDguMjM0NjhDOS44MTM2NSA4LjIwOTI0IDkuODEzNjUgOC4xODM3OSA5Ljc4ODIxIDguMTgzNzlWOC4xMzI5MUM5LjYxMDExIDcuNDIwNTQgOS4xMjY3MiA2LjgwOTk0IDguMzg4OTEgNi41NTU1M0M3LjI0NDA0IDYuMDk3NTggNS45NDY1MSA2LjY4MjczIDUuNTM5NDQgNy44NTMwNVpNNi44NjI0MSAxMy4yNzIxQzUuNzE3NTMgMTMuNzA0NiA1LjEwNjkzIDE1LjAwMjIgNS41Mzk0NCAxNi4xNDdDNS45NzE5NSAxNy4zMTc0IDcuMjQ0MDQgMTcuOTAyNSA4LjM4ODkxIDE3LjQ0NDZDOS4xMjY3MiAxNy4xOTAyIDkuNjEwMTEgMTYuNTc5NiA5Ljc4ODIxIDE1Ljg2NzJWMTUuODE2M0M5LjgxMzY1IDE1LjgxNjMgOS44MTM2NSAxNS43OTA5IDkuODEzNjUgMTUuNzY1NEw5LjgzOTA5IDE1LjcxNDVDMTAuMDE3MiAxNS4xMjk0IDEwLjQ0OTcgMTQuNjIwNSAxMS4wODU3IDE0LjM5MTZDMTEuNTE4MiAxNC4yMzg5IDExLjk3NjIgMTQuMjM4OSAxMi4zODMzIDE0LjM2NjFDMTIuNTg2OCAxNC40NDI1IDEyLjc5MDMgMTQuNDQyNSAxMi45OTM5IDE0LjM2NjFDMTMuNDUxOCAxNC4yMTM1IDEzLjcwNjIgMTMuNjc5MiAxMy41MjgxIDEzLjIyMTJDMTMuMzc1NSAxMi43NjMzIDEyLjg0MTIgMTIuNTA4OSAxMi4zODMzIDEyLjY4N0MxMi4xNzk3IDEyLjczNzkgMTIuMDI3MSAxMi44OTA1IDExLjkyNTMgMTMuMDQzMkwxMS44OTk5IDEzLjA5NEMxMS42NzA5IDEzLjQ1MDIgMTEuMzQwMSAxMy43MzAxIDEwLjkwNzYgMTMuODgyN0MxMC4yNDYyIDE0LjEzNzIgOS41NTkyMyAxNC4wMDk5IDkuMDI0OTUgMTMuNjI4M0M4LjQzOTggMTMuMTQ0OSA3LjYyNTY2IDEyLjk5MjMgNi44NjI0MSAxMy4yNzIxWiIgZmlsbD0iIzUwMkVBMiIvPgo8L2c+Cjwvc3ZnPgo='); - background-size: contain; - background-repeat: no-repeat; -} -.aelf-web-login.aelf-extra-wallets .social-content .plugin-entry .icon.discover { - background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9Ikljb24gLyBTcGVjaWFsIC8gUG9ydGtleSI+CjxnIGlkPSJJY29uIC8gU3BlY2lhbCAvIFBvcnRrZXlfMiI+CjxyZWN0IGlkPSJSZWN0YW5nbGUiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjEyIiBmaWxsPSJ3aGl0ZSIvPgo8ZyBpZD0iSWNvbiAvIEZpbGwgLyBBZWxmIENvcHkiPgo8cGF0aCBpZD0iU2hhcGUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTEuMzQ2NCA3LjM0NDI2QzkuMzQ5NyA4LjIyMDExIDguMDkzOTcgMTAuMzYyMiA4LjgyNTAxIDEyLjQ5MDlDOS4yNjcwOSAxMy43NzgyIDEwLjE1NzkgMTQuNjk1NiAxMS40NzkgMTUuMTY0NEMxMy43ODkyIDE1Ljk4NDUgMTYuMjAwOSAxNC4xODE0IDE1LjkzMDQgMTEuODM3N0MxNS44MTU2IDEwLjg0MTYgMTUuMzA5NyAxMC4wODMxIDE0LjI4MjMgOS43NjkyOEMxMy41MTgxIDkuNTM1ODEgMTIuNzg2OCA5LjY0NDg5IDEyLjE5IDEwLjIwMDJDMTEuNjgzNSAxMC42NzEgMTEuNDkxNSAxMS4yNTA4IDExLjY5NDMgMTEuOTI0OEMxMS44MDYzIDEyLjI5NTQgMTIuMDc1MiAxMi41MjYgMTIuNDQxIDEyLjYzNjFDMTIuNzYyMiAxMi43MzI0IDEzLjAxMDcgMTIuNTkzIDEzLjIwMiAxMi4zMjY0QzEzLjE2MzUgMTIuMjYxOSAxMy4xMjk2IDEyLjE5MTQgMTMuMDgyOCAxMi4xMzA4QzEyLjgzMyAxMS44MDggMTMuMDM1NSAxMS4zMzg1IDEzLjI1MTUgMTEuMTQzQzEzLjU0NDkgMTAuODc3MyAxNC4wMjAyIDEwLjg1MzEgMTQuMzMyNCAxMS4wNzMyQzE0LjgzODkgMTEuNDI5NCAxNS4wNjkyIDEyLjM3NzEgMTQuNzk0IDEyLjk3MTZDMTQuMzMzNCAxMy45NjYxIDEzLjE0OTEgMTQuNTQ1IDEyLjA2MjQgMTQuMjYzNEMxMC4zNDY4IDEzLjgxODcgOS41MDA4OCAxMi4xMjQ4IDEwLjA1NDYgMTAuNDg3M0MxMC43OTA0IDguMzExMzQgMTMuMjYzNiA3LjM1OTU3IDE1LjM3MTMgOC40MDMyQzE3LjA3NTEgOS4yNDY1MSAxNy43MDc2IDEwLjcxOTEgMTcuNjM5NyAxMi40NzIxQzE3LjUyODQgMTUuMzU4MyAxNC42MTYgMTcuNDk5NSAxMS42OTU2IDE2Ljk0MjlDOC44NjMyOSAxNi40MDMyIDYuNzYwMDkgMTMuNjkxMiA2LjkxMDk2IDExLjEyNjRDNi45NjY0NiAxMC4xNzk1IDcuMTc3MjkgOS4yOTI3NiA3LjY2MTc4IDguNDc5MTFDOC45MjIyOSA2LjM2MzE1IDEwLjg4NTggNS4zNjczNyAxMy4zNDE3IDUuMjA2M0MxMy45ODgzIDUuMTYzODggMTQuNjQwMiA1LjE5OTkyIDE1LjI1NjEgNS4yMDAyNEMxNS4yMjIzIDUuMTg1MjUgMTUuMTQ1MSA1LjE0NzI5IDE1LjA2NDcgNS4xMTczMUMxMy44NjU1IDQuNjY4MjIgMTIuNjI2IDQuNTI1MDEgMTEuMzU1OSA0LjcwNjE4QzEwLjU2ODQgNC44MDMxNCA5Ljg0MTUzIDUuMDE1ODggOS4xODA2NSA1LjMyMDE3QzkuMTY4NTMgNS4zMjIwOCA5LjE1NDE4IDUuMzI2MjMgOS4xMzY2MyA1LjMzMzU2QzguODM5MzcgNS40NjAxOSA4Ljc4OTYxIDUuMTY5MyA4LjY4NDAzIDUuMDgxMjdDOC41ODEzMyA0Ljk5NTc5IDguNTk0NzMgNS4xMDIgOC41OTQ3MyA1LjEwMkM4LjY4NDM1IDUuNTI4NDUgOC40NTk4MSA1LjcwMDM2IDguNDI5NTEgNS43MjE0MUM4LjI0MjI4IDUuODM3MiA4LjA2MjcxIDUuOTYyMjMgNy44ODkyIDYuMDkzNjRDNy44ODQwOSA2LjA5NTg3IDcuODgwMjcgNi4wOTU4NyA3Ljg3NDg0IDYuMDk4NDJDNy40NjQ5OCA2LjI4NTMzIDcuMjk0NjYgNS45Njk1NiA3LjEwNjE2IDUuODczNTZDNi45MDY4MSA1Ljc3MjEzIDYuOTgyMDkgNS45Mzg2MiA2Ljk4MjA5IDUuOTM4NjJDNy4yMjg5NiA2LjQyOTE4IDcuMDE1ODkgNi44NDg5MiA2Ljk3NjAzIDYuOTE5NzNDNi44MDEyNCA3LjEwODIzIDYuNjM3NjEgNy4zMDYzMSA2LjQ4NDUxIDcuNTEyMDNDNi40Njg1NyA3LjUyMjI0IDYuNDUyOTQgNy41MzE4MSA2LjQzNDc2IDcuNTQ4MDdDNi4wMzIyMyA3LjkxMiA1LjcxOTAyIDcuNjIzOTkgNS40NzAyMyA3LjU2OTc2QzUuMTk1OTMgNy41MTA0NCA1LjM1MTI2IDcuNjkwMDEgNS4zNTEyNiA3LjY5MDAxQzUuODU4NzIgOC4yMDk1OSA1LjY5ODI5IDguODM0NDIgNS42OTgyOSA4LjgzNDQyTDUuNjk5NTYgOC44MzUwNkM1LjA0NzYyIDEwLjI0MzkgNC44MTM1IDExLjg3NDQgNS4wODQzIDEzLjUxMTNDNS45NzQ1IDE4Ljg5MTcgMTIuNTkyNSAyMS40MzI5IDE2LjkzMDYgMTcuOTY2OEMxOC4zMzk1IDE2Ljg0MTIgMTkuMzE2NyAxNC42NzI5IDE5LjQxOTggMTIuODc5MUMxOS40OTMxIDExLjYwNTIgMTkuMDk5MiAxMC40NDkgMTguMzczIDkuNDAyMTZDMTYuODMyMSA3LjE4MDk2IDEzLjc1MjIgNi4yODg4NCAxMS4zNDY0IDcuMzQ0MjYiIGZpbGw9IiM1QjhFRjQiLz4KPC9nPgo8L2c+CjwvZz4KPC9zdmc+Cg=='); - background-size: contain; - background-repeat: no-repeat; -} -.aelf-web-login.aelf-extra-wallets .social-content .plugin-entry .name { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-size: 16px; - line-height: 24px; - display: flex; - text-align: center; - color: #5c6764; - flex-direction: row; - align-items: center; - justify-content: center; -} - -.aelf-web-login.aelf-extra-wallets .wallet-entries.default-content { - display: flex; - flex-direction: row; - gap: 56px; - margin-top: 16px; - margin-bottom: 40px; -} - -.aelf-web-login.aelf-extra-wallets .default-content .plugin-entry .icon { - width: 42px; - height: 42px; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - cursor: pointer; - user-select: none; -} - -.aelf-web-login.aelf-extra-wallets .default-content .plugin-entry .icon.elf { - background-image: url('data:image/png;base64,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'); - background-size: contain; - background-repeat: no-repeat; -} -.aelf-web-login.aelf-extra-wallets .default-content .plugin-entry .icon.discover { - background-image: url('data:image/png;base64,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'); - background-size: contain; - background-repeat: no-repeat; -} -.aelf-web-login.aelf-extra-wallets .default-content .plugin-entry .name { - font-family: 'Poppins'; - font-style: normal; - font-weight: 400; - font-size: 12px; - line-height: 20px; - display: flex; - align-items: center; - text-align: center; - color: #5c6764; - flex-direction: row; - align-items: center; - justify-content: center; -} - -.aelf-web-logout-dialog { - display: flex; - flex-direction: column; - font-family: 'Roboto'; - &-content { - padding: 0 32px 24px; - display: flex; - flex-direction: column; - - &:first-child { - border-bottom: 1px solid #dee2e8; - } - - &-mobile { - padding: 0px 16px 24px; - - .aelf-web-logout-dialog-close { - margin-right: 9px; - } - } - } - - &-close { - height: 24px; - margin-top: 20px; - margin-right: -11px; - display: flex; - justify-content: flex-end; - align-items: center; - - > i { - width: 16px; - height: 16px; - background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNyAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjczMTQ3IDUuNDU0OTlMMTMuNjU5OSAwLjUyNzAwMkMxNC4xMTQ1IDAuMDcyNDYzOCAxNC43NzcgLTAuMTA1MDU0IDE1LjM5NzkgMC4wNjEzMTg5QzE2LjAxODggMC4yMjc2OTIgMTYuNTAzOCAwLjcxMjY3OCAxNi42NzAxIDEuMzMzNTlDMTYuODM2NSAxLjk1NDUgMTYuNjU5IDIuNjE3IDE2LjIwNDUgMy4wNzE1NEwxMS4yNzU1IDcuOTk4OTlMMTYuMjA0NSAxMi45Mjg1QzE2Ljg2ODEgMTMuNTkyMSAxNi45MDQ5IDE0LjY0NTEgMTYuMzE1MSAxNS4zNTJMMTYuMjA0NSAxNS40NzNDMTUuNTAxOCAxNi4xNzU3IDE0LjM2MjYgMTYuMTc1NyAxMy42NTk5IDE1LjQ3M0w4LjczMTQ3IDEwLjU0NUwzLjgwMzAyIDE1LjQ3M0MzLjEzOTQgMTYuMTM2NiAyLjA4NjM2IDE2LjE3MzUgMS4zNzk0OCAxNS41ODM2TDEuMjU4NDggMTUuNDczQzAuNTU1ODIzIDE0Ljc3MDMgMC41NTU4MjMgMTMuNjMxMSAxLjI1ODQ4IDEyLjkyODVMNi4xODY0NyA3Ljk5OTk5TDEuMjU4NDggMy4wNzE1NEMwLjg0MTgxNyAyLjY1NDg4IDAuNjU3OTMyIDIuMDYzNDcgMC43NTgzMjcgMS40ODk1NEwwLjc5Mjc5NCAxLjMzMzU5QzAuOTU5MTY3IDAuNzEyNjc4IDEuNDQ0MTUgMC4yMjc2OTIgMi4wNjUwNiAwLjA2MTMxODlDMi42ODU5NyAtMC4xMDUwNTQgMy4zNDg0OCAwLjA3MjQ2MzggMy44MDMwMiAwLjUyNzAwMkw4LjczMTQ3IDUuNDU0OTlaIiBmaWxsPSIjNTE1QTYyIi8+Cjwvc3ZnPgo='); - background-size: 100% 100%; - } - } - - &-title { - margin: 12px 0; - line-height: 32px; - font-size: 24px; - text-align: center; - font-weight: 500; - color: #252525; - letter-spacing: -1px; - } - - &-sub-title { - margin-top: 12px; - line-height: 24px; - font-size: 16px; - text-align: center; - color: #515a62; - word-spacing: -2px; - } - - &-btn { - margin: 16px 0 0 0; - border-radius: 4px; - padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - height: 48px; - margin-top: 16px; - font-size: 16px; - } - - .ok-btn { - background-color: #e7383a; - color: #fff; - } - - .cancel-btn { - color: #5b8ef4; - border: 1px solid #5b8ef4; - } -} diff --git a/packages/login/src/components/CofirmLogoutDialog/ConfirmLogoutDialog.tsx b/packages/login/src/components/CofirmLogoutDialog/ConfirmLogoutDialog.tsx deleted file mode 100644 index aca3303d..00000000 --- a/packages/login/src/components/CofirmLogoutDialog/ConfirmLogoutDialog.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import React, { useMemo } from 'react'; -import { Modal, Button, Row } from 'antd'; -import isMobile from '../../utils/isMobile'; - -export interface ConfirmLogoutDialogProps { - title: string; - subTitle: string[]; - okTxt: string; - cancelTxt: string; - visible: boolean; - onOk: () => void; - onCancel: () => void; - width: number; - mobileWidth: number; -} - -const defaultProps: Partial = { - title: 'Are you sure you want to exit your wallet?', - subTitle: [ - 'Your current wallet and assets will be removed from this app permanently. This action cannot be undone.', - 'You can ONLY recover this wallet with your guardians.', - ], - okTxt: 'I Understand,Confirm Exit', - cancelTxt: 'Cancel', - visible: false, - onOk: () => void 0, - onCancel: () => void 0, - width: 430, - mobileWidth: 343, -}; - -export default function ConfirmLogoutDialog(props: Partial) { - const { title, subTitle, okTxt, cancelTxt, visible, onOk, onCancel, width, mobileWidth } = { - ...defaultProps, - ...props, - }; - - const isMobileDevice = isMobile(); - - const renderContent = useMemo( - () => - subTitle?.map((t) => ( - - {t} - - )), - [subTitle], - ); - - const bodyStyle = useMemo( - () => ({ - borderRadius: isMobileDevice ? '8px' : '6px', - padding: '0', - }), - [isMobileDevice], - ); - - return ( - - - - - - - {title} - {renderContent} - - - - - - - - ); -} diff --git a/packages/login/src/components/CofirmLogoutDialog/index.ts b/packages/login/src/components/CofirmLogoutDialog/index.ts deleted file mode 100644 index 76cdd243..00000000 --- a/packages/login/src/components/CofirmLogoutDialog/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ConfirmLogoutDialog'; diff --git a/packages/login/src/components/PluginEntry.tsx b/packages/login/src/components/PluginEntry.tsx deleted file mode 100644 index b3a0bc09..00000000 --- a/packages/login/src/components/PluginEntry.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -export default function PluginEntry({ icon, name, onClick }: { icon: string; name: string; onClick: () => void }) { - return ( -
-
-
{name}
-
- ); -} diff --git a/packages/login/src/config.ts b/packages/login/src/config.ts deleted file mode 100644 index 9001c787..00000000 --- a/packages/login/src/config.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { ReactNode } from 'react'; -import { ConfigProvider } from '@portkey/did-ui-react'; -import { IStorageSuite } from '@portkey/types'; -import { NetworkType } from '@portkey/provider-types'; -// import type { AElfReactProviderProps } from '@aelf-react/types'; -import { GlobalConfigProps } from '@portkey/did-ui-react/dist/_types/src/components/config-provider/types'; - -// copy from @aelf-react/core, cause it's not exported -export type AelfNode = { - rpcUrl: string; - chainId: string; -}; -export type AElfReactProviderProps = { - children: ReactNode; - appName: string; - nodes?: { - [key: string]: AelfNode; - }; -}; - -export type WebLoginConfig = { - appName: string; - chainId: string; - defaultRpcUrl: string; - networkType: NetworkType; - portkey: GlobalConfigProps & { useLocalStorage?: boolean }; - aelfReact: Omit; -}; - -export class Store implements IStorageSuite { - async getItem(key: string) { - return localStorage.getItem(key); - } - async setItem(key: string, value: string) { - return localStorage.setItem(key, value); - } - async removeItem(key: string) { - return localStorage.removeItem(key); - } -} - -let globalConfig: WebLoginConfig; - -export function setGlobalConfig(config: WebLoginConfig) { - globalConfig = config; - if (config.portkey.useLocalStorage) { - config.portkey.storageMethod = new Store(); - } - ConfigProvider.setGlobalConfig(config.portkey); -} - -export function getConfig() { - return globalConfig; -} diff --git a/packages/login/src/constants.ts b/packages/login/src/constants.ts deleted file mode 100644 index 8c9d0915..00000000 --- a/packages/login/src/constants.ts +++ /dev/null @@ -1,33 +0,0 @@ -export enum WalletType { - unknown = 'unknown', - discover = 'discover', - elf = 'elf', - portkey = 'portkey', -} - -export enum WebLoginState { - initial = 'initial', - lock = 'lock', - eagerly = 'eagerly', - logining = 'logining', - logined = 'logined', - logouting = 'logouting', -} - -export enum WebLoginEvents { - ERROR = 'commonError', - LOGIN_ERROR = 'loginError', - LOGINED = 'logined', - LOGOUT = 'logout', - LOCK = 'lock', - USER_CANCEL = 'userCancel', - MODAL_CANCEL = 'modalCancel', - BRIDGE_CANCEL = 'bridgeCancel', - DISCOVER_DISCONNECTED = 'discoverDisconnected', - NETWORK_MISMATCH = 'networkMismatch', - ACCOUNTS_MISMATCH = 'accountsMismatch', - CHAINID_MISMATCH = 'chainIdMismatch', -} - -export const CloseIcon = - 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9Ikljb24gLyBMaW5lIC8gTGVmdCI+CjxwYXRoIGlkPSJTaGFwZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjAwMDAyIDUuNDU0OTlMMTIuOTI4NSAwLjUyNzAwMkMxMy4zODMgMC4wNzI0NjM4IDE0LjA0NTUgLTAuMTA1MDU0IDE0LjY2NjQgMC4wNjEzMTg5QzE1LjI4NzMgMC4yMjc2OTIgMTUuNzcyMyAwLjcxMjY3OCAxNS45Mzg3IDEuMzMzNTlDMTYuMTA1MSAxLjk1NDUgMTUuOTI3NiAyLjYxNyAxNS40NzMgMy4wNzE1NEwxMC41NDQgNy45OTg5OUwxNS40NzMgMTIuOTI4NUMxNi4xMzY2IDEzLjU5MjEgMTYuMTczNSAxNC42NDUxIDE1LjU4MzYgMTUuMzUyTDE1LjQ3MyAxNS40NzNDMTQuNzcwNCAxNi4xNzU3IDEzLjYzMTEgMTYuMTc1NyAxMi45Mjg1IDE1LjQ3M0w4LjAwMDAyIDEwLjU0NUwzLjA3MTU3IDE1LjQ3M0MyLjQwNzk1IDE2LjEzNjYgMS4zNTQ5MiAxNi4xNzM1IDAuNjQ4MDMzIDE1LjU4MzZMMC41MjcwMzEgMTUuNDczQy0wLjE3NTYyMyAxNC43NzAzIC0wLjE3NTYyMyAxMy42MzExIDAuNTI3MDMxIDEyLjkyODVMNS40NTUwMiA3Ljk5OTk5TDAuNTI3MDMxIDMuMDcxNTRDMC4xMTAzNzIgMi42NTQ4OCAtMC4wNzM1MTMxIDIuMDYzNDcgMC4wMjY4ODE4IDEuNDg5NTRMMC4wNjEzNDkyIDEuMzMzNTlDMC4yMjc3MjEgMC43MTI2NzggMC43MTI3MDcgMC4yMjc2OTIgMS4zMzM2MiAwLjA2MTMxODlDMS45NTQ1MyAtMC4xMDUwNTQgMi42MTcwMyAwLjA3MjQ2MzggMy4wNzE1NyAwLjUyNzAwMkw4LjAwMDAyIDUuNDU0OTlaIiBmaWxsPSIjNTE1QTYyIi8+CjwvZz4KPC9zdmc+Cg=='; diff --git a/packages/login/src/context.tsx b/packages/login/src/context.tsx deleted file mode 100644 index ee644eb2..00000000 --- a/packages/login/src/context.tsx +++ /dev/null @@ -1,407 +0,0 @@ -import { EventEmitter } from 'events'; -import React, { createContext, useEffect, useContext, useCallback, useMemo, useState } from 'react'; -import { AElfReactProvider } from '@aelf-react/core'; -import { WalletHookInterface } from './types'; -import { WebLoginProviderProps } from './types'; -import { usePortkey } from './wallets/portkey/usePortkey'; -import NightElfPlugin from './wallets/elf/NightElfPlugin'; -import Portkey from './wallets/portkey/Portkey'; -import { useElf } from './wallets/elf/useElf'; -import { getConfig } from './config'; -import { CloseIcon, WalletType, WebLoginState } from './constants'; -import { PortkeyLoading } from '@portkey/did-ui-react'; -import { check } from './wallets/elf/utils'; -import isMobile from './utils/isMobile'; -import isPortkeyApp from './utils/isPortkeyApp'; -import DiscoverPlugin from './wallets/discover/DiscoverPlugin'; -import { LOGIN_EARGLY_KEY as DISCOVER_LOGIN_EARGERLY_KEY, useDiscover } from './wallets/discover/useDiscover'; -import ConfirmLogoutDialog from './components/CofirmLogoutDialog/ConfirmLogoutDialog'; -import { useDebounceFn } from 'ahooks'; - -const INITIAL_STATE = { - loginState: WebLoginState.initial, - loginError: undefined, - eventEmitter: new EventEmitter(), -}; - -export enum LogoutConfirmResult { - default, - cancel, - ok, -} - -export type WebLoginInterface = WalletHookInterface & { - loginId: number; - loginState: WebLoginState; - loginError: any | unknown; - eventEmitter: EventEmitter; - walletType: WalletType; -}; - -export type WebLoginInternalInterface = { - _api: { - nigthElf: WalletHookInterface; - portkey: WalletHookInterface; - discover: WalletHookInterface; - }; -}; - -export type WebLoginContextType = WebLoginInterface & WebLoginInternalInterface; - -export const WebLoginContext = createContext(INITIAL_STATE as WebLoginContextType); - -export const useWebLoginContext = () => useContext(WebLoginContext); -export const useWebLogin: () => WebLoginInterface = () => { - return useWebLoginContext() as WebLoginInterface; -}; - -function WebLoginProvider({ - nightElf: nightEflOpts, - portkey: portkeyOpts, - discover: discoverOpts, - extraWallets, - children, - commonConfig, -}: WebLoginProviderProps) { - const eventEmitter = useMemo(() => new EventEmitter(), []); - const [loginState, setLoginState] = useState(WebLoginState.initial); - const [loginError, setLoginError] = useState(); - const [walletType, setWalletType] = useState(WalletType.unknown); - - const [logoutConfirmOpen, setLogoutConfirmOpen] = useState(false); - const [logoutConfirmResult, setLogoutConfirmResult] = useState(LogoutConfirmResult.default); - const [loading, setLoading] = useState(false); - const [noLoading, setNoLoading] = useState(true); - const [modalOpen, setModalOpen] = useState(false); - const [bridgeType, setBridgeType] = useState('unknown'); - const [loginId, setLoginId] = useState(0); - - useEffect(() => { - // SSR support - if (typeof window !== 'undefined') { - check() - .then((type) => { - setBridgeType(type); - }) - .catch((error) => { - console.warn(error); - }); - } - }, []); - - const setLoginStateInternal = useCallback( - (newLoginState: WebLoginState) => { - const prevState = loginState; - setLoginState(newLoginState); - if (newLoginState === WebLoginState.logined) { - if (prevState !== newLoginState) { - setLoginId(loginId + 1); - } - setModalOpen(false); - } - }, - [loginId, loginState], - ); - - const elfApi = useElf({ - options: nightEflOpts, - loginState, - walletType, - eventEmitter, - setLoginError, - setLoginState: setLoginStateInternal, - setWalletType, - setLoading, - }); - const discoverApi = useDiscover({ - options: discoverOpts, - loginState, - walletType, - eventEmitter, - setLoginError, - setLoginState: setLoginStateInternal, - setWalletType, - setLoading, - }); - const portkeyApi = usePortkey({ - options: portkeyOpts, - loginState, - walletType, - eventEmitter, - setLoginError, - setLoginState: setLoginStateInternal, - setModalOpen, - setWalletType, - setLoading, - }); - - const login = useCallback(async () => { - setLoginStateInternal(WebLoginState.logining); - try { - if (isPortkeyApp()) { - setNoLoading(false); - discoverApi.login(); - return; - } else { - const type = await check(); - if (type === 'AelfBridge') { - setNoLoading(false); - elfApi.login(); - return; - } - } - } catch (error) { - console.warn(error); - } - setModalOpen(true); - }, [discoverApi, elfApi, setLoginStateInternal]); - - const createInvalidFunc = (name: string, loginState: WebLoginState) => () => { - console.log(`Call method '${name}' on invalid state '${loginState}'`); - }; - - const invalidApi = useMemo(() => { - return { - wallet: { address: '', accountInfoSync: { syncCompleted: false, holderInfo: undefined } }, - login: createInvalidFunc('login', loginState), - loginEagerly: createInvalidFunc('loginEagerly', loginState), - logout: createInvalidFunc('logout', loginState), - callContract: createInvalidFunc('callContract', loginState) as any, - } as unknown as WalletHookInterface; - }, [loginState]); - - // adapt api - const walletApi = useMemo(() => { - if (loginState === WebLoginState.initial) { - return { - ...invalidApi, - login, - }; - } - if (loginState === WebLoginState.eagerly) { - const isDiscoverEagerly = !!localStorage.getItem(DISCOVER_LOGIN_EARGERLY_KEY); - return { ...invalidApi, loginEagerly: isDiscoverEagerly ? discoverApi.loginEagerly : elfApi.loginEagerly }; - } - if (loginState === WebLoginState.lock) { - return { ...invalidApi, login: portkeyApi.login, loginEagerly: portkeyApi.loginEagerly }; - } - if (loginState === WebLoginState.logining) { - return { ...invalidApi }; - } - if (loginState === WebLoginState.logined) { - if (walletType === WalletType.elf) { - return elfApi; - } else if (walletType === WalletType.portkey) { - return portkeyApi; - } else if (walletType === WalletType.discover) { - return discoverApi; - } - return invalidApi; - } - return invalidApi; - }, [loginState, invalidApi, login, elfApi, portkeyApi, walletType, discoverApi]); - - const { run: loginInternal } = useDebounceFn( - useCallback(async () => { - if (loginState === WebLoginState.logined) { - console.warn('login failed: loginState is logined'); - return; - } - walletApi.login(); - }, [loginState, walletApi]), - { - wait: 500, - maxWait: 500, - leading: true, - }, - ); - - const logout = useCallback(async () => { - await walletApi.logout(); - try { - await discoverApi.logoutSilently(); - } catch (e) { - console.warn(e); - } - try { - await elfApi.logoutSilently(); - } catch (e) { - console.warn(e); - } - try { - await portkeyApi.logoutSilently(); - } catch (e) { - console.warn(e); - } - }, [discoverApi, elfApi, portkeyApi, walletApi]); - - const { run: logoutInternal } = useDebounceFn( - useCallback(async () => { - if (loginState !== WebLoginState.logined) { - console.warn('logout failed: loginState is not logined'); - return; - } - if (walletType === WalletType.portkey) { - setLogoutConfirmResult(LogoutConfirmResult.default); - setLogoutConfirmOpen(true); - } else { - await logout(); - } - }, [loginState, logout, walletType]), - { - wait: 500, - maxWait: 500, - leading: true, - }, - ); - - useEffect(() => { - if (logoutConfirmResult === LogoutConfirmResult.ok) { - setLogoutConfirmOpen(false); - setLogoutConfirmResult(LogoutConfirmResult.default); - logout(); - } else if (logoutConfirmResult === LogoutConfirmResult.cancel) { - setLogoutConfirmOpen(false); - } - }, [logout, logoutConfirmResult, walletApi]); - - const ConfirmLogoutDialogComponent = portkeyOpts.ConfirmLogoutDialog || ConfirmLogoutDialog; - - const state = useMemo( - () => ({ - loginId, - loginState, - loginError, - eventEmitter, - walletType, - _api: { - nigthElf: elfApi, - portkey: portkeyApi, - discover: discoverApi, - }, - ...walletApi, - login: loginInternal, - logout: logoutInternal, - }), - [ - loginId, - discoverApi, - elfApi, - eventEmitter, - loginError, - loginInternal, - loginState, - logoutInternal, - portkeyApi, - walletApi, - walletType, - ], - ); - - const renderExtraWallets = () => { - const isMobileDevice = isMobile(); - const isBridgeNotExist = bridgeType === 'unknown' || (bridgeType === 'none' && isMobileDevice); - const isDiscoverMobileNotExist = - discoverApi.discoverDetected === 'unknown' || (discoverApi.discoverDetected === 'not-detected' && isMobileDevice); - - const isShowDiscoverButton = isMobile() && !isPortkeyApp(); - - let headerClassName = 'default-header'; - let contentClassName = 'default-content'; - - if (portkeyOpts.design === 'Web2Design') { - headerClassName = 'social-header web2-header'; - contentClassName = 'social-content web2-content'; - } else if (portkeyOpts.design === 'SocialDesign') { - headerClassName = 'social-header'; - contentClassName = 'social-content'; - } - - // hide extra wallets when bridge and discover mobile not exist - if (isBridgeNotExist && isDiscoverMobileNotExist && !isShowDiscoverButton) { - return; - } - return ( -
-
- {portkeyOpts.design === 'SocialDesign' && ( -
- {commonConfig?.showClose && ( -
- -
- )} - {commonConfig?.iconSrc && ( -
- -
- )} -
- )} - -
Crypto wallet
-
-
- {extraWallets - // hide specific wallet when bridge or discover mobile not exist - ?.filter((wallet) => { - if (wallet === WalletType.elf) { - return !isBridgeNotExist; - } else if (wallet === WalletType.discover) { - return !isDiscoverMobileNotExist || isShowDiscoverButton; - } - return true; - }) - .map((wallet) => { - if (wallet === WalletType.elf) { - return ; - } else if (wallet === WalletType.discover) { - return ( - - ); - } - })} -
-
- ); - }; - - return ( - - {children} - - setLogoutConfirmResult(LogoutConfirmResult.cancel)} - onOk={() => setLogoutConfirmResult(LogoutConfirmResult.ok)} - /> - - - ); -} - -export default function Provider({ children, ...props }: WebLoginProviderProps) { - const aelfReactConfig = getConfig().aelfReact; - return ( - - {children} - - ); -} diff --git a/packages/login/src/hooks/internal/useEnvChecks.ts b/packages/login/src/hooks/internal/useEnvChecks.ts deleted file mode 100644 index 0598590c..00000000 --- a/packages/login/src/hooks/internal/useEnvChecks.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useState } from 'react'; -import isMobile from 'src/utils/isMobile'; -import isPortkeyApp from 'src/utils/isPortkeyApp'; -import NightElfCheck from 'src/wallets/elf/NightElfCheck'; - -export type EnvType = 'unknown' | 'detected' | 'no-detected'; -export type EnvChecks = { - nightElf: EnvType; - aelfBridge: EnvType; - portkey: EnvType; - discover: EnvType; -}; - -function check(onChange: (envChecks: EnvChecks) => void) { - const envChecks: EnvChecks = { - nightElf: 'unknown', - aelfBridge: 'unknown', - portkey: 'unknown', - discover: 'unknown', - }; - - if (isPortkeyApp()) { - envChecks.nightElf = 'no-detected'; - envChecks.aelfBridge = 'no-detected'; - envChecks.portkey = 'no-detected'; - envChecks.discover = 'detected'; - onChange(envChecks); - return; - } - - const win = window as any; - if (win.NightElf) { - envChecks.nightElf = 'no-detected'; - envChecks.aelfBridge = 'no-detected'; - envChecks.portkey = 'no-detected'; - envChecks.discover = 'detected'; - onChange(envChecks); - } -} - -// eslint-disable-next-line @typescript-eslint/no-empty-function -export default function useEnvChecks() {} diff --git a/packages/login/src/hooks/useCallContract.ts b/packages/login/src/hooks/useCallContract.ts deleted file mode 100644 index 8022f0a9..00000000 --- a/packages/login/src/hooks/useCallContract.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { useCallback } from 'react'; -import AElf from 'aelf-sdk'; -import { ChainId } from '@portkey/provider-types'; -import { did } from '@portkey/did-ui-react'; -import { useWebLogin } from '../context'; -import { CallContractHookInterface, CallContractHookOptions, CallContractParams } from '../types'; -import { getConfig } from '../config'; -import { WalletType, WebLoginEvents } from '../constants'; -import { getContractBasic } from '@portkey/contracts'; -import { SendOptions } from '@portkey/types'; -import useWebLoginEvent from './useWebLoginEvent'; - -const getAElfInstance = (() => { - const instances = new Map(); - return (rpcUrl: string) => { - if (!instances.has(rpcUrl)) { - instances.set(rpcUrl, new AElf(new AElf.providers.HttpProvider(rpcUrl))); - } - return instances.get(rpcUrl); - }; -})(); - -const getViewWallet = (() => { - let wallet: any; - return () => { - if (!wallet) { - wallet = AElf.wallet.createNewWallet(); - } - return wallet; - }; -})(); - -const contractCache = new Map(); - -function useGetContractWithCache(loginId: number, chainId: string, cache: boolean) { - useWebLoginEvent(WebLoginEvents.LOGINED, () => { - contractCache.clear(); - }); - return useCallback( - async (walletType: WalletType, key: string, createContract: () => Promise) => { - if (!cache) { - return await createContract(); - } - const cacheId = `${loginId}-${chainId}-${walletType}-${key}`; - let contract = contractCache.get(cacheId); - if (!contract) { - contract = await createContract(); - contractCache.set(cacheId, contract); - } - return contract as T; - }, - [cache, chainId, loginId], - ); -} - -export default function useCallContract(options?: CallContractHookOptions): CallContractHookInterface { - options = options || {}; - options = { - cache: true, - chainId: getConfig().chainId, - rpcUrl: getConfig().defaultRpcUrl, - ...options, - }; - - const chainId = options.chainId!; - const viewWallet = getViewWallet(); - const aelfInstance = getAElfInstance(options.rpcUrl!); - const { loginId, wallet, walletType } = useWebLogin(); - const getContractWithCache = useGetContractWithCache(loginId, chainId, options.cache!); - - const callViewMethod = useCallback( - async function callContractViewFunc(params: CallContractParams): Promise { - const contract = await getContractWithCache(WalletType.unknown, params.contractAddress, async () => { - return await aelfInstance.chain.contractAt(params.contractAddress, viewWallet); - }); - return await contract[params.methodName].call(params.args); - }, - [aelfInstance.chain, getContractWithCache, viewWallet], - ); - const callSendMethod = useCallback( - async function callContractSendFunc( - params: CallContractParams, - sendOptions: SendOptions | undefined = undefined, - ): Promise { - if (walletType === WalletType.unknown) { - throw new Error('Wallet not login'); - } - switch (walletType) { - case WalletType.discover: { - const discoverInfo = wallet.discoverInfo!; - const contract = await getContractWithCache(WalletType.discover, params.contractAddress, async () => { - const chain = await discoverInfo.provider!.getChain(chainId as ChainId); - return getContractBasic({ - contractAddress: params.contractAddress, - chainProvider: chain, - }); - }); - const accounts = discoverInfo.accounts; - const accountsInChain = accounts[chainId as ChainId]; - if (!accountsInChain || accountsInChain.length === 0) { - throw new Error(`Account not found in chain: ${chainId}`); - } - const address = accountsInChain[0]; - const result = contract.callSendMethod(params.methodName, address, params.args, sendOptions); - return result as R; - } - case WalletType.elf: { - const bridges = wallet.nightElfInfo!.aelfBridges; - if (!bridges) { - throw new Error('NightElf bridges not found'); - } - if (!bridges[chainId] || !bridges[chainId]!.chain) { - throw new Error(`Bridge of ${chainId} not found in NightElf`); - } - const bridge = bridges[chainId]!; - const contract = await getContractWithCache(WalletType.elf, params.contractAddress, async () => { - return getContractBasic({ - contractAddress: params.contractAddress, - aelfInstance: bridge, - account: { - address: wallet.nightElfInfo!.account!, - }, - }); - }); - return contract.callSendMethod(params.methodName, wallet.address, params.args, sendOptions) as R; - } - case WalletType.portkey: { - // TODO cache chains info - const chainsInfo = await did.services.getChainsInfo(); - const chainInfo = chainsInfo.find((chain) => chain.chainId === chainId); - if (!chainInfo) { - throw new Error(`Chain is not running: ${chainId}`); - } - const didWalletInfo = wallet.portkeyInfo!; - const cacheKey = `${chainInfo.caContractAddress}-${didWalletInfo.walletInfo.address}-${chainInfo.endPoint}`; - const caContract = await getContractWithCache(WalletType.portkey, cacheKey, async () => { - return await getContractBasic({ - contractAddress: chainInfo.caContractAddress, - account: didWalletInfo.walletInfo, - rpcUrl: chainInfo.endPoint, - }); - }); - const result = await caContract.callSendMethod( - 'ManagerForwardCall', - didWalletInfo.walletInfo.address, - { - caHash: didWalletInfo.caInfo.caHash, - contractAddress: params.contractAddress, - methodName: params.methodName, - args: params.args, - }, - sendOptions, - ); - // compatible with aelf-sdk result of contract - if (result.transactionId) { - const anyResult = result as any; - anyResult.TransactionId = result.transactionId; - } - return result as R; - } - } - }, - [ - chainId, - getContractWithCache, - wallet.address, - wallet.discoverInfo, - wallet.nightElfInfo, - wallet.portkeyInfo, - walletType, - ], - ); - - return { - contractHookId: `${loginId}_${chainId}_${walletType}}`, - callViewMethod, - callSendMethod, - }; -} diff --git a/packages/login/src/hooks/useContract.ts b/packages/login/src/hooks/useContract.ts deleted file mode 100644 index 76969a47..00000000 --- a/packages/login/src/hooks/useContract.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ContractHookOptions } from '../types'; - -// export default function useContract(options?: ContractHookOptions) { - -// } diff --git a/packages/login/src/hooks/useGetAccount.ts b/packages/login/src/hooks/useGetAccount.ts deleted file mode 100644 index 37526c67..00000000 --- a/packages/login/src/hooks/useGetAccount.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { useCallback } from 'react'; -import { WalletType, WebLoginState } from '../constants'; -import { useWebLogin } from '../context'; -import { ChainId } from '@portkey/provider-types'; -import { did } from '@portkey/did-ui-react'; - -export default function useGetAccount(chainId: string) { - const { loginState, walletType, wallet } = useWebLogin(); - return useCallback(async () => { - if (loginState !== WebLoginState.logined) { - throw new Error('Please login first'); - } - if (walletType === WalletType.unknown) { - throw new Error(`Invalid wallet type: ${walletType}`); - } - switch (walletType) { - case WalletType.elf: - return wallet.address; - case WalletType.discover: { - const chainIdTyped = chainId as ChainId; - let accounts = wallet.discoverInfo?.accounts; - if (!accounts || !accounts[chainIdTyped] || accounts![chainIdTyped]!.length === 0) { - const provider = await wallet.discoverInfo?.provider; - if (!provider) { - throw new Error('Discover provider is null'); - } - accounts = await provider.request({ method: 'accounts' }); - if (!accounts || !accounts[chainIdTyped] || accounts![chainIdTyped]!.length === 0) { - throw new Error(`Account not found in chain: ${chainIdTyped}`); - } - } - return accounts![chainIdTyped]![0]; - } - case WalletType.portkey: { - let accounts = wallet.portkeyInfo!.accounts; - if (!accounts || !accounts[chainId]) { - const caInfo = await did.didWallet.getHolderInfoByContract({ - caHash: wallet.portkeyInfo!.caInfo.caHash, - chainId: chainId as ChainId, - }); - wallet.portkeyInfo!.accounts = { - ...accounts, - [chainId]: caInfo.caAddress, - }; - accounts = wallet.portkeyInfo!.accounts; - } - if (!accounts[chainId]) { - throw new Error(`Account not found in chain: ${chainId}`); - } - return accounts[chainId]; - } - } - }, [ - chainId, - loginState, - wallet.address, - wallet.discoverInfo?.accounts, - wallet.discoverInfo?.provider, - wallet.portkeyInfo, - walletType, - ]); -} diff --git a/packages/login/src/hooks/useLoginState.ts b/packages/login/src/hooks/useLoginState.ts deleted file mode 100644 index 2a465cbe..00000000 --- a/packages/login/src/hooks/useLoginState.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useState, useEffect } from 'react'; -import { WebLoginState } from '../constants'; -import { useWebLogin } from '../context'; - -export default function useLoginState(onChanged: (loginState: WebLoginState) => void) { - const [prevLoginState, setPrevLoginState] = useState(WebLoginState.initial); - const { loginState } = useWebLogin(); - - useEffect(() => { - if (loginState !== prevLoginState) { - setPrevLoginState(loginState); - onChanged(loginState); - } - }, [prevLoginState, loginState, onChanged]); -} diff --git a/packages/login/src/hooks/useMultiWallets.ts b/packages/login/src/hooks/useMultiWallets.ts deleted file mode 100644 index cc712061..00000000 --- a/packages/login/src/hooks/useMultiWallets.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { SwitchWalletFunc, WalletInfo } from 'src/types'; -import { useWebLoginContext } from '../context'; -import { WalletType, WebLoginEvents } from '../constants'; -import { useCallback, useState } from 'react'; -import useWebLoginEvent from './useWebLoginEvent'; -import { ERR_CODE, makeError } from '../errors'; - -export type SwitchWalletType = 'elf' | 'portkey' | 'discover'; - -export type SwitchWalletsHook = { - current: WalletType; - switching: boolean; - switchingWallet: WalletType; - wallets: { - nightElf: WalletInfo; - portkey: WalletInfo; - discover: WalletInfo; - }; - switchWallet: (walletType: SwitchWalletType) => Promise; -}; - -type PromiseCallbacks = { - resolve: () => void; - reject: (reason?: any) => void; -}; - -function useLoginBySwitch() { - const webLoginContext = useWebLoginContext(); - const { nigthElf, portkey, discover } = webLoginContext._api; - const [promise, setPromise] = useState(); - - useWebLoginEvent(WebLoginEvents.LOGINED, () => { - promise?.resolve(); - }); - useWebLoginEvent(WebLoginEvents.LOGIN_ERROR, (error: any) => { - promise?.reject(error); - }); - useWebLoginEvent(WebLoginEvents.USER_CANCEL, () => { - promise?.reject(makeError(ERR_CODE.USER_CANCEL)); - }); - - return useCallback( - async (walletType: SwitchWalletType) => { - const promise = new Promise((resolve, reject) => { - setPromise({ resolve, reject }); - }); - switch (walletType) { - case 'elf': - nigthElf.loginBySwitch(); - break; - case 'portkey': - portkey.loginBySwitch(); - break; - case 'discover': - discover.loginBySwitch(); - break; - default: - throw new Error(`Invalid wallet type: ${walletType}`); - } - return promise; - }, - [discover, nigthElf, portkey], - ); -} - -export default function useMultiWallets(): SwitchWalletsHook { - const webLoginContext = useWebLoginContext(); - const [switchingWalletType, setSwitchingWalletType] = useState(WalletType.unknown); - const { nigthElf, portkey, discover } = webLoginContext._api; - const currentWalletType = webLoginContext.walletType; - - const loginBySwitch = useLoginBySwitch(); - - const switchWallet = useCallback( - async (walletType: SwitchWalletType) => { - if (currentWalletType === WalletType.unknown) { - throw new Error('Please login first'); - } - setSwitchingWalletType(walletType as WalletType); - let switchWalletFunc: SwitchWalletFunc; - switch (currentWalletType) { - case 'elf': - switchWalletFunc = nigthElf.switchWallet; - break; - case 'portkey': - switchWalletFunc = portkey.switchWallet; - break; - case 'discover': - switchWalletFunc = discover.switchWallet; - break; - default: - throw new Error('Please login first'); - } - - await switchWalletFunc(async (commit, rollback) => { - try { - await loginBySwitch(walletType); - await commit(); - } catch (e: any) { - await rollback(); - throw e; - } - }); - - setSwitchingWalletType(WalletType.unknown); - }, - [currentWalletType, discover.switchWallet, loginBySwitch, nigthElf.switchWallet, portkey.switchWallet], - ); - - return { - current: webLoginContext.walletType, - switchingWallet: switchingWalletType, - switching: switchingWalletType !== WalletType.unknown, - wallets: { - nightElf: nigthElf.wallet, - portkey: portkey.wallet, - discover: discover.wallet, - }, - switchWallet, - }; -} diff --git a/packages/login/src/hooks/usePortkeyLock.ts b/packages/login/src/hooks/usePortkeyLock.ts deleted file mode 100644 index 2dc0a832..00000000 --- a/packages/login/src/hooks/usePortkeyLock.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useWebLoginContext } from '../context'; -import { PortkeyInterface } from '../wallets/portkey/usePortkey'; - -export default function usePortkeyLock() { - const webLoginContext = useWebLoginContext(); - const portkey = webLoginContext._api.portkey as PortkeyInterface; - return { - isUnlocking: portkey.isUnlocking, - lock: portkey.lock, - }; -} diff --git a/packages/login/src/hooks/usePortkeyPreparing.ts b/packages/login/src/hooks/usePortkeyPreparing.ts deleted file mode 100644 index 2e1dff8f..00000000 --- a/packages/login/src/hooks/usePortkeyPreparing.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useWebLoginContext } from '../context'; -import { PortkeyInterface } from '../wallets/portkey/usePortkey'; - -export default function usePortkeyPreparing() { - const webLoginContext = useWebLoginContext(); - const portkey = webLoginContext._api.portkey as PortkeyInterface; - return { - isPreparing: portkey.isPreparing, - }; -} diff --git a/packages/login/src/hooks/useWebLoginEvent.ts b/packages/login/src/hooks/useWebLoginEvent.ts deleted file mode 100644 index b7fe4606..00000000 --- a/packages/login/src/hooks/useWebLoginEvent.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useEffect } from 'react'; -import { Accounts, ChainIds, NetworkType } from '@portkey/provider-types'; -import { useWebLogin } from '../context'; -import { WebLoginEvents } from '../constants'; - -export default function useWebLoginEvent(eventType: WebLoginEvents.ERROR, callback: (error: any) => void): void; -export default function useWebLoginEvent(eventType: WebLoginEvents.DISCOVER_DISCONNECTED, callback: () => void): void; -export default function useWebLoginEvent(eventType: WebLoginEvents.USER_CANCEL, callback: () => void): void; -export default function useWebLoginEvent(eventType: WebLoginEvents.LOGINED, callback: () => void): void; -export default function useWebLoginEvent(eventType: WebLoginEvents.LOGOUT, callback: () => void): void; -export default function useWebLoginEvent(eventType: WebLoginEvents.LOGIN_ERROR, callback: (error: any) => void): void; -export default function useWebLoginEvent( - eventType: WebLoginEvents.NETWORK_MISMATCH, - callback: (networkType: NetworkType) => void, -): void; -export default function useWebLoginEvent( - eventType: WebLoginEvents.ACCOUNTS_MISMATCH, - callback: (accounts: Accounts) => void, -): void; -export default function useWebLoginEvent( - eventType: WebLoginEvents.CHAINID_MISMATCH, - callback: (chainIds: ChainIds) => void, -): void; - -export default function useWebLoginEvent(eventType: WebLoginEvents, callback: (data: T) => void) { - const { eventEmitter } = useWebLogin(); - useEffect(() => { - eventEmitter.addListener(eventType, callback); - return () => { - eventEmitter.removeListener(eventType, callback); - }; - }, [callback, eventEmitter, eventType]); -} diff --git a/packages/login/src/index.ts b/packages/login/src/index.ts deleted file mode 100644 index 0f0261ef..00000000 --- a/packages/login/src/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import WebLoginProvider, { useWebLogin, WebLoginContext } from './context'; -import useLoginState from './hooks/useLoginState'; -import useWebLoginEvent from './hooks/useWebLoginEvent'; -import useMultiWallets from './hooks/useMultiWallets'; -import useCallContract from './hooks/useCallContract'; -import usePortkeyLock from './hooks/usePortkeyLock'; -import usePortkeyPreparing from './hooks/usePortkeyPreparing'; -import useGetAccount from './hooks/useGetAccount'; - -import getContractBasicAsync from './utils/getContractBasicAsync'; -import detectDiscoverProvider from './wallets/discover/detectProvider'; -import detectNightElf from './wallets/elf/detectNightElf'; - -export * from './utils/pluginPages'; -export * from './wallets/types'; -export * from './types'; -export * from './constants'; -export * from './config'; -export * from './errors'; -export * from './hooks/useMultiWallets'; -export * from './hooks/useCallContract'; -export * from './context'; -export type { ConfirmLogoutDialogProps } from './components/CofirmLogoutDialog'; - -export { - WebLoginContext, - WebLoginProvider, - useWebLogin, - useLoginState, - useWebLoginEvent, - useMultiWallets, - useCallContract, - usePortkeyLock, - usePortkeyPreparing, - useGetAccount, - getContractBasicAsync, - detectDiscoverProvider, - detectNightElf, -}; diff --git a/packages/login/src/types.ts b/packages/login/src/types.ts deleted file mode 100644 index fe8ebb33..00000000 --- a/packages/login/src/types.ts +++ /dev/null @@ -1,161 +0,0 @@ -import type { AElfContextType } from '@aelf-react/core/dist/types'; -import { DIDWalletInfo } from '@portkey/did-ui-react'; -import type { IHolderInfo } from '@portkey/services'; -import type { Accounts, ChainIds, IPortkeyProvider } from '@portkey/provider-types'; -import type { RefAttributes } from 'react'; -import { ConfirmLogoutDialogProps } from './components/CofirmLogoutDialog'; -import { SendOptions } from '@portkey/types'; -import { SignInProps, TDesign } from '@portkey/did-ui-react'; - -/** - * WebLoginProvider types - */ -export type ExtraWalletNames = 'discover' | 'elf'; - -export type NightElfOptions = { - connectEagerly: boolean; - useMultiChain?: boolean; - onClick?: OnClickCryptoWallet; - onPluginNotFound?: PluginNotFoundCallback; -}; - -export type PortkeyOptions = { - autoShowUnlock: boolean; - checkAccountInfoSync: boolean; - SignInComponent?: React.FC>; - ConfirmLogoutDialog?: React.FC>; - design?: TDesign; -}; - -export type PluginNotFoundCallback = (openPluginStorePage: () => void) => void; -export type OnClickCryptoWallet = (continueDefaultBehaviour: () => void) => void; - -export type DiscoverOptions = { - autoRequestAccount: boolean; - autoLogoutOnDisconnected: boolean; - autoLogoutOnNetworkMismatch: boolean; - autoLogoutOnAccountMismatch: boolean; - autoLogoutOnChainMismatch: boolean; - onClick?: OnClickCryptoWallet; - onPluginNotFound?: PluginNotFoundCallback; -}; -interface ICommonConfig { - showClose?: boolean; - iconSrc?: string; -} -export type WebLoginProviderProps = { - nightElf: NightElfOptions; - portkey: PortkeyOptions; - discover: DiscoverOptions; - extraWallets: Array; - children: React.ReactNode; - commonConfig?: ICommonConfig; -}; - -/** - * callContract - */ - -export interface CallContractParams { - contractAddress: string; - methodName: string; - args: T; -} - -export type CallContractFunc = (params: CallContractParams) => Promise; - -/** - * getSignature - */ -export type SignatureParams = { - appName: string; - address: string; - signInfo: string; - hexToBeSign?: string; -}; -export type SignatureData = { - signature: string; - error: number; - errorMessage: string; - from: string; -}; - -export type GetSignatureFunc = (params: SignatureParams) => Promise; - -/** - * wallet - */ - -export type PortkeyInfo = DIDWalletInfo & { - nickName: string; - accounts: { - [key: string]: string; - }; -}; - -export type DiscoverInfo = { - address: string; - accounts: Accounts; - nickName?: string; - provider?: IPortkeyProvider; -}; - -export type WalletInfo = { - name?: string; - address: string; - publicKey?: string; - nightElfInfo?: AElfContextType; - portkeyInfo?: PortkeyInfo; - discoverInfo?: DiscoverInfo; - accountInfoSync: { - syncCompleted: boolean; - holderInfo?: IHolderInfo; - chainIds?: ChainIds; - }; -}; - -/** - * switch wallet - */ -export type DoSwitchFunc = (commit: () => Promise, rollback: () => Promise) => Promise; -export type SwitchWalletFunc = (doSwitch: DoSwitchFunc) => Promise; - -/** - * useWebLogin - */ -export type WalletHookInterface = { - wallet: WalletInfo; - loginEagerly: () => void; - login: () => void; - loginBySwitch: () => void; - logout: () => void; - logoutSilently: () => Promise; - switchWallet: SwitchWalletFunc; - // TODO: move this to new hook - callContract(params: CallContractParams): Promise; - getSignature(params: SignatureParams): Promise; -}; - -/** - * useCallContract - */ -export type CallContractHookOptions = { - chainId?: string; - rpcUrl?: string; - cache?: boolean; -}; - -export type CallContractHookInterface = { - contractHookId: string; - callViewMethod(params: CallContractParams): Promise; - callSendMethod(params: CallContractParams, sendOptions: SendOptions | undefined): Promise; -}; - -/** - * useContract - */ -export type ContractHookOptions = { - chainId?: string; - rpcUrl?: string; - cache?: boolean; -}; diff --git a/packages/login/src/utils/getContractBasicAsync.ts b/packages/login/src/utils/getContractBasicAsync.ts deleted file mode 100644 index e32b78cc..00000000 --- a/packages/login/src/utils/getContractBasicAsync.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { WalletInfo } from '../types'; - -import { getContractBasic as getContractBasicInternal } from '@portkey/contracts'; -import { did } from '@portkey/did-ui-react'; -import { getConfig } from '../config'; -import { WalletType } from '../constants'; -import { ChainId } from '@portkey/provider-types'; -import { IContract } from '@portkey/types'; - -export default async function getContractBasicAsync( - walletType: WalletType, - wallet: WalletInfo, - contractAddress: string, -): Promise { - const chainId = getConfig().chainId; - switch (walletType) { - case WalletType.discover: { - const chain = await wallet.discoverInfo!.provider!.getChain(chainId as ChainId); - return getContractBasicInternal({ - contractAddress, - chainProvider: chain, - }); - } - case WalletType.elf: - return getContractBasicInternal({ - contractAddress, - aelfInstance: wallet.nightElfInfo!.aelfBridges![getConfig().chainId], - account: { - address: wallet.nightElfInfo!.account!, - }, - }); - case WalletType.portkey: { - const chainsInfo = await did.services.getChainsInfo(); - const chainInfo = chainsInfo.find((chain) => chain.chainId === chainId); - if (!chainInfo) { - throw new Error(`Chain is not running: ${chainId}`); - } - return getContractBasicInternal({ - contractAddress, - callType: 'ca', - caHash: wallet.portkeyInfo!.caInfo.caHash, - caContractAddress: chainInfo.caContractAddress, - account: wallet.portkeyInfo!.walletInfo, - }); - } - default: - throw new Error('Unknown wallet type: ' + walletType); - } -} diff --git a/packages/login/src/utils/isMobile.ts b/packages/login/src/utils/isMobile.ts deleted file mode 100644 index 897297fa..00000000 --- a/packages/login/src/utils/isMobile.ts +++ /dev/null @@ -1,24 +0,0 @@ -const mobileRE = - /(android|bb\d+|meego).+mobile|armv7l|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series[46]0|samsungbrowser.*mobile|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i; -const notMobileRE = /CrOS/; - -const tabletRE = /android|ipad|playbook|silk/i; - -export default function isMobile() { - const ua = navigator.userAgent; - if (typeof ua !== 'string') return false; - - let result = mobileRE.test(ua) && !notMobileRE.test(ua); - - if ( - !result && - navigator && - navigator.maxTouchPoints > 1 && - ua.indexOf('Macintosh') !== -1 && - ua.indexOf('Safari') !== -1 - ) { - result = true; - } - - return result; -} diff --git a/packages/login/src/utils/pluginPages.ts b/packages/login/src/utils/pluginPages.ts deleted file mode 100644 index 3f90022f..00000000 --- a/packages/login/src/utils/pluginPages.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function openNightElfPluginPage() { - const win = window as any; - win.open('https://chrome.google.com/webstore/search/AELF', '_blank').focus(); -} - -export function openPortkeyPluginPage() { - const win = window as any; - win - .open('https://chrome.google.com/webstore/detail/portkey-did-crypto-nft/hpjiiechbbhefmpggegmahejiiphbmij', '_blank') - .focus(); -} diff --git a/packages/login/src/utils/signatureParams.ts b/packages/login/src/utils/signatureParams.ts deleted file mode 100644 index e1f5774c..00000000 --- a/packages/login/src/utils/signatureParams.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { SignatureParams } from '../types'; - -export default function (params: SignatureParams) { - if (params.hexToBeSign) { - console.error( - 'getSignature: hexToBeSign is deprecated, please use signInfo instead, signInfo is utf-8 string not hex', - ); - } -} diff --git a/packages/login/src/utils/waitForSeconds.ts b/packages/login/src/utils/waitForSeconds.ts deleted file mode 100644 index 52271ce9..00000000 --- a/packages/login/src/utils/waitForSeconds.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default function wait(time: number) { - return new Promise((resolve) => { - setTimeout(resolve, time); - }); -} diff --git a/packages/login/src/wallets/discover/DiscoverPlugin.tsx b/packages/login/src/wallets/discover/DiscoverPlugin.tsx deleted file mode 100644 index 551585e3..00000000 --- a/packages/login/src/wallets/discover/DiscoverPlugin.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import PluginEntry from '../../components/PluginEntry'; -import { DiscoverDetectState } from './useDiscover'; -import isMobile from '../../utils/isMobile'; -import { useDebounceFn } from 'ahooks'; -import { DiscoverOptions } from '../../types'; -import { openPortkeyPluginPage } from '../../utils/pluginPages'; -import isPortkeyApp from '../../utils/isPortkeyApp'; -import openPageInDiscover from './openDiscoverPage'; - -export default function DiscoverPlugin({ - detectState, - discoverOpts, - onClick, -}: { - detectState: DiscoverDetectState; - discoverOpts: DiscoverOptions; - onClick: () => void; -}) { - const { run: onClickInternal } = useDebounceFn( - async () => { - if (isMobile() && !isPortkeyApp()) { - openPageInDiscover(); - return; - } - - if (detectState === 'not-detected' && !isMobile()) { - if (discoverOpts?.onPluginNotFound) { - discoverOpts?.onPluginNotFound(openPortkeyPluginPage); - } else { - openPortkeyPluginPage(); - } - return; - } - if (detectState === 'unknown') return; - onClick(); - }, - { - wait: 500, - maxWait: 500, - leading: true, - trailing: false, - }, - ); - - const onClickButton = () => { - if (discoverOpts.onClick) { - discoverOpts.onClick(onClickInternal); - } else { - onClickInternal(); - } - }; - return ; -} diff --git a/packages/login/src/wallets/discover/detectProvider.ts b/packages/login/src/wallets/discover/detectProvider.ts deleted file mode 100644 index d95446bd..00000000 --- a/packages/login/src/wallets/discover/detectProvider.ts +++ /dev/null @@ -1,10 +0,0 @@ -import detectProvider from '@portkey/detect-provider'; - -export default async function detectDiscoverProvider() { - let detectProviderFunc = detectProvider; - if (typeof detectProvider !== 'function') { - const detectProviderModule = detectProvider as any; - detectProviderFunc = detectProviderModule.default; - } - return await detectProviderFunc(); -} diff --git a/packages/login/src/wallets/discover/openDiscoverPage.ts b/packages/login/src/wallets/discover/openDiscoverPage.ts deleted file mode 100644 index 36d50eaa..00000000 --- a/packages/login/src/wallets/discover/openDiscoverPage.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { scheme } from '@portkey/utils'; - -export default function openPageInDiscover(url?: string) { - try { - window.location.href = scheme.formatScheme({ - action: 'linkDapp', - domain: window.location.host, - custom: { - url: url || window.location.href, - }, - }); - } catch (error) { - console.warn(error); - window.open('https://portkey.finance', '_blank'); - } -} diff --git a/packages/login/src/wallets/discover/useChainIdsSync.ts b/packages/login/src/wallets/discover/useChainIdsSync.ts deleted file mode 100644 index 3b3b9dad..00000000 --- a/packages/login/src/wallets/discover/useChainIdsSync.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { useState, useCallback, useEffect } from 'react'; -import { WebLoginState } from '../../constants'; -import { useInterval } from 'ahooks'; -import type { ChainId } from '@portkey/types'; -import type { IPortkeyProvider, ChainIds } from '@portkey/provider-types'; - -export default function useChainIdsSync( - chainId: string, - loginState: WebLoginState, - shouldSync: boolean, - discoverProvider?: IPortkeyProvider, -) { - const currentChainId = chainId as ChainId; - const [syncCompleted, setSyncCompleted] = useState(false); - const [chainIds, setChainIds] = useState(); - - const checkChainIds = useCallback(async () => { - if (loginState !== WebLoginState.logined) { - setSyncCompleted(false); - setChainIds(undefined); - return; - } - if (!shouldSync) return; - if (!discoverProvider) return; - if (syncCompleted) return; - const chainIds = await discoverProvider.request({ method: 'chainIds' }); - setChainIds(chainIds); - setSyncCompleted(chainIds?.includes(currentChainId)); - }, [currentChainId, discoverProvider, loginState, shouldSync, syncCompleted]); - - useEffect(() => { - if (loginState !== WebLoginState.logined) { - setChainIds(undefined); - setSyncCompleted(false); - } else { - checkChainIds(); - } - }, [checkChainIds, loginState]); - useInterval(checkChainIds, 10000, { - immediate: true, - }); - - return { - syncCompleted, - chainIds, - }; -} diff --git a/packages/login/src/wallets/discover/useDiscover.ts b/packages/login/src/wallets/discover/useDiscover.ts deleted file mode 100644 index 3e1b2bed..00000000 --- a/packages/login/src/wallets/discover/useDiscover.ts +++ /dev/null @@ -1,397 +0,0 @@ -import React, { useState, useMemo, useRef, useEffect, useCallback } from 'react'; -import { ChainId } from '@portkey/types'; -import { IPortkeyProvider, Accounts, ChainIds, NetworkType, ProviderError } from '@portkey/provider-types'; -import detectProvider from '@portkey/detect-provider'; -import { getConfig } from '../../config'; -import { - CallContractParams, - DiscoverInfo, - DoSwitchFunc, - SignatureParams, - SwitchWalletFunc, - WalletHookInterface, -} from '../../types'; -import { WalletHookParams } from '../types'; -import { WalletType, WebLoginEvents, WebLoginState } from '../../constants'; -import checkSignatureParams from '../../utils/signatureParams'; -import { DiscoverOptions } from 'src/types'; -import useChainIdsSync from './useChainIdsSync'; -import { ERR_CODE, makeError } from '../../errors'; -import wait from '../../utils/waitForSeconds'; - -export type DiscoverDetectState = 'unknown' | 'detected' | 'not-detected'; -export type DiscoverInterface = WalletHookInterface & { - discoverDetected: DiscoverDetectState; -}; - -export const LOGIN_EARGLY_KEY = 'discover.loginEargly'; - -export function useDiscover({ - options, - eventEmitter, - loginState, - walletType, - setWalletType, - setLoginError, - setLoginState, - setLoading, -}: WalletHookParams) { - const chainId = getConfig().chainId as ChainId; - - const autoRequestAccountCheck = useRef(false); - const [discoverProvider, setDiscoverProvider] = useState(); - const [discoverInfo, setDiscoverInfo] = useState(); - const [discoverDetected, setDiscoverDetected] = useState('unknown'); - const [switching, setSwitching] = useState(false); - - const chainIdsSync = useChainIdsSync(chainId, loginState, true, discoverProvider); - - const detect = useCallback(async (): Promise => { - if (discoverProvider?.isConnected()) { - return discoverProvider!; - } - // TODO: detects in once issue - let detectProviderFunc = detectProvider; - if (typeof detectProvider !== 'function') { - const detectProviderModule = detectProvider as any; - detectProviderFunc = detectProviderModule.default; - } - let provider: IPortkeyProvider | null; - try { - provider = await detectProviderFunc(); - } catch (error) { - setDiscoverDetected('not-detected'); - throw error; - } - if (provider) { - if (!provider.isPortkey) { - setDiscoverDetected('not-detected'); - throw new Error('Discover provider found, but check isPortkey failed'); - } - setDiscoverProvider(provider); - setDiscoverDetected('detected'); - return provider; - } else { - setDiscoverDetected('not-detected'); - throw new Error('Discover provider not found'); - } - }, [discoverProvider]); - - useEffect(() => { - detect().catch((error: any) => { - console.log(error.message); - }); - }, []); - - const onAccountsSuccess = useCallback( - async (provider: IPortkeyProvider, accounts: Accounts) => { - setLoginError(undefined); - let nickName = 'Wallet 01'; - const address = accounts[chainId]![0].split('_')[1]; - try { - nickName = await provider.request({ method: 'wallet_getWalletName' }); - } catch (error) { - console.warn(error); - } - localStorage.setItem(LOGIN_EARGLY_KEY, 'true'); - setDiscoverInfo({ - address, - accounts, - nickName, - provider, - }); - setWalletType(WalletType.discover); - setLoginState(WebLoginState.logined); - setLoading(false); - eventEmitter.emit(WebLoginEvents.LOGINED); - }, - [chainId, eventEmitter, setLoading, setLoginError, setLoginState, setWalletType], - ); - - const onAccountsFail = useCallback( - (error: any) => { - localStorage.removeItem(LOGIN_EARGLY_KEY); - setLoading(false); - setLoginError(error); - setDiscoverInfo(undefined); - setWalletType(WalletType.unknown); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGIN_ERROR, error); - }, - [eventEmitter, setLoading, setLoginError, setLoginState, setWalletType], - ); - - const loginEagerly = useCallback(async () => { - setLoginState(WebLoginState.logining); - try { - const provider = await detect(); - const network = await provider.request({ method: 'network' }); - if (network !== getConfig().networkType) { - onAccountsFail(makeError(ERR_CODE.NETWORK_TYPE_NOT_MATCH)); - return; - } - const accounts = await provider.request({ method: 'accounts' }); - if (accounts[chainId] && accounts[chainId]!.length > 0) { - onAccountsSuccess(provider, accounts); - } else { - onAccountsFail(makeError(ERR_CODE.DISCOVER_LOGIN_EAGERLY_FAIL)); - } - } catch (error: any) { - onAccountsFail({ - code: 10001, - message: error?.message || 'unknown error', - nativeError: error, - }); - } - }, [chainId, detect, onAccountsFail, onAccountsSuccess, setLoginState]); - - const login = useCallback(async () => { - setLoading(true); - setLoginState(WebLoginState.logining); - try { - const provider = await detect(); - const network = await provider.request({ method: 'network' }); - if (network !== getConfig().networkType) { - onAccountsFail(makeError(ERR_CODE.NETWORK_TYPE_NOT_MATCH)); - return; - } - let accounts = await provider.request({ method: 'accounts' }); - if (accounts[chainId] && accounts[chainId]!.length > 0) { - onAccountsSuccess(provider, accounts); - return; - } - accounts = await provider.request({ method: 'requestAccounts' }); - if (accounts[chainId] && accounts[chainId]!.length > 0) { - onAccountsSuccess(provider, accounts); - } else { - setLoading(false); - onAccountsFail(makeError(ERR_CODE.ACCOUNTS_IS_EMPTY)); - } - } catch (error) { - setLoading(false); - onAccountsFail(error); - } - }, [chainId, detect, onAccountsFail, onAccountsSuccess, setLoading, setLoginState]); - - const logout = useCallback(async () => { - if (walletType !== WalletType.discover) { - try { - localStorage.removeItem(LOGIN_EARGLY_KEY); - } catch (e) { - console.warn(e); - } - setDiscoverInfo(undefined); - return; - } - - setLoginState(WebLoginState.logouting); - await wait(500); - try { - localStorage.removeItem(LOGIN_EARGLY_KEY); - } catch (e) { - console.warn(e); - } - setLoginError(undefined); - setDiscoverInfo(undefined); - setWalletType(WalletType.unknown); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGOUT); - }, [eventEmitter, setLoginError, setLoginState, setWalletType, walletType]); - - const logoutSilently = useCallback(async () => { - try { - localStorage.removeItem(LOGIN_EARGLY_KEY); - } catch (e) { - console.warn(e); - } - setDiscoverInfo(undefined); - }, []); - - const switchWallet: SwitchWalletFunc = useCallback( - async (doSwitch: DoSwitchFunc) => { - if (loginState !== WebLoginState.logined) { - throw new Error(`Switch wallet on invalid state: ${loginState}`); - } - if (switching) { - throw new Error('Switching wallet'); - } - setSwitching(true); - await doSwitch( - async () => { - try { - localStorage.removeItem(LOGIN_EARGLY_KEY); - } catch (e) { - console.warn(e); - } - setDiscoverInfo(undefined); - setSwitching(false); - }, - async () => { - setSwitching(false); - setWalletType(WalletType.discover); - setLoginState(WebLoginState.logined); - }, - ); - }, - [loginState, setLoginState, setWalletType, switching], - ); - - const callContract = useCallback( - async function callContractFunc(params: CallContractParams): Promise { - if (!discoverInfo || !discoverProvider) { - throw new Error('Discover not connected'); - } - const chain = await discoverProvider.getChain(chainId); - const contract = chain.getContract(params.contractAddress); - const result = contract.callSendMethod(params.methodName, discoverInfo.address, params.args); - return result as R; - }, - [chainId, discoverInfo, discoverProvider], - ); - - const getSignature = useCallback( - async (params: SignatureParams) => { - checkSignatureParams(params); - if (!discoverInfo) { - throw new Error('Discover not connected'); - } - const provider = discoverProvider! as IPortkeyProvider; - const signInfo = params.signInfo; - const signedMsgObject = await provider.request({ - method: 'wallet_getSignature', - payload: { - data: signInfo || params.hexToBeSign, - }, - }); - const signedMsgString = [ - signedMsgObject.r.toString(16, 64), - signedMsgObject.s.toString(16, 64), - `0${signedMsgObject.recoveryParam!.toString()}`, - ].join(''); - return { - error: 0, - errorMessage: '', - signature: signedMsgString, - from: 'discover', - }; - }, - [discoverInfo, discoverProvider], - ); - - useEffect(() => { - if (autoRequestAccountCheck.current) { - return; - } - autoRequestAccountCheck.current = true; - const canLoginEargly = !!localStorage.getItem(LOGIN_EARGLY_KEY); - if (canLoginEargly) { - if (options.autoRequestAccount) { - if (loginState === WebLoginState.initial) { - loginEagerly(); - } - } else { - setLoginState(WebLoginState.eagerly); - } - } - }, [loginEagerly, setLoginState, loginState, options.autoRequestAccount]); - - useEffect(() => { - if (discoverProvider) { - const onDisconnected = (error: ProviderError) => { - if (!discoverInfo) return; - eventEmitter.emit(WebLoginEvents.DISCOVER_DISCONNECTED, error); - if (options.autoLogoutOnDisconnected) { - logout(); - } - }; - const onNetworkChanged = (networkType: NetworkType) => { - if (networkType !== getConfig().networkType) { - eventEmitter.emit(WebLoginEvents.NETWORK_MISMATCH, networkType); - if (options.autoLogoutOnNetworkMismatch) { - logout(); - } - } - }; - const onAccountsChanged = (accounts: Accounts) => { - if (!discoverInfo) return; - if ( - !accounts[chainId] || - accounts[chainId]!.length === 0 || - accounts[chainId]!.find((addr) => addr !== discoverInfo!.address) - ) { - eventEmitter.emit(WebLoginEvents.ACCOUNTS_MISMATCH, accounts); - if (options.autoLogoutOnAccountMismatch) { - logout(); - } - } - }; - const onChainChanged = (chainIds: ChainIds) => { - if (chainIds.find((id) => id === chainId)) { - eventEmitter.emit(WebLoginEvents.CHAINID_MISMATCH, chainIds); - if (options.autoLogoutOnChainMismatch) { - logout(); - } - } - }; - discoverProvider.on('disconnected', onDisconnected); - discoverProvider.on('networkChanged', onNetworkChanged); - discoverProvider.on('accountsChanged', onAccountsChanged); - discoverProvider.on('chainChanged', onChainChanged); - return () => { - discoverProvider.removeListener('disconnected', onDisconnected); - discoverProvider.removeListener('networkChanged', onNetworkChanged); - discoverProvider.removeListener('networkChanged', onAccountsChanged); - discoverProvider.removeListener('chainChanged', onChainChanged); - }; - } - }, [ - chainId, - discoverInfo, - discoverProvider, - eventEmitter, - logout, - options.autoLogoutOnAccountMismatch, - options.autoLogoutOnChainMismatch, - options.autoLogoutOnDisconnected, - options.autoLogoutOnNetworkMismatch, - ]); - - return useMemo( - () => ({ - wallet: { - name: discoverInfo?.nickName || '', - address: discoverInfo?.address || '', - publicKey: '', - discoverInfo, - accountInfoSync: { - syncCompleted: chainIdsSync.syncCompleted, - chainIds: chainIdsSync.chainIds, - holderInfo: undefined, - }, - }, - discoverDetected, - loginEagerly, - login, - logout, - logoutSilently, - switchWallet, - loginBySwitch: login, - logoutBySwitch: logout, - callContract, - getSignature, - }), - [ - discoverInfo, - chainIdsSync.syncCompleted, - chainIdsSync.chainIds, - discoverDetected, - loginEagerly, - login, - logout, - logoutSilently, - switchWallet, - callContract, - getSignature, - ], - ); -} diff --git a/packages/login/src/wallets/elf/AelfBridgeCheck.ts b/packages/login/src/wallets/elf/AelfBridgeCheck.ts deleted file mode 100644 index 6850f2de..00000000 --- a/packages/login/src/wallets/elf/AelfBridgeCheck.ts +++ /dev/null @@ -1,40 +0,0 @@ -import AElfBridge from 'aelf-bridge'; - -let aelfBridgeInstance: AelfBridgeCheck | undefined = undefined; - -export default class AelfBridgeCheck { - public check?: () => Promise; - constructor() { - this.check = async () => { - return new Promise((resolve, reject) => { - let timeout = false; - const bridgeInstance = new AElfBridge({ - timeout: 3000, - }); - bridgeInstance.connect().then((isConnected: boolean) => { - if (timeout) return; - if (isConnected) { - resolve(true); - } else { - reject({ - error: 200001, - message: 'timeout, please use AELF Wallet APP or open the page in PC', - }); - } - }); - setTimeout(() => { - timeout = true; - reject({ - error: 200001, - message: 'timeout, please use AELF Wallet APP or open the page in PC', - }); - }, 3000); - }); - }; - } - static getInstance() { - if (aelfBridgeInstance) return aelfBridgeInstance; - aelfBridgeInstance = new AelfBridgeCheck(); - return aelfBridgeInstance; - } -} diff --git a/packages/login/src/wallets/elf/NightElfCheck.ts b/packages/login/src/wallets/elf/NightElfCheck.ts deleted file mode 100644 index 13c2e1d2..00000000 --- a/packages/login/src/wallets/elf/NightElfCheck.ts +++ /dev/null @@ -1,35 +0,0 @@ -let nightElfInstance: NightElfCheck | undefined = undefined; - -export default class NightElfCheck { - public check: () => Promise; - constructor() { - let resolveTemp = (value: boolean) => { - console.log('resolveTemp', value); - }; - this.check = async () => { - return new Promise((resolve, reject) => { - const win = window as any; - if (win.NightElf) { - console.log('There is NightElf'); - resolve(true); - return; - } - setTimeout(() => { - reject({ - error: 200001, - message: 'timeout, please download and install the NightELF explorer extension', - }); - }, 5000); - resolveTemp = resolve; - }); - }; - document.addEventListener('NightElf', () => { - resolveTemp(true); - }); - } - static getInstance() { - if (nightElfInstance) return nightElfInstance; - nightElfInstance = new NightElfCheck(); - return nightElfInstance; - } -} diff --git a/packages/login/src/wallets/elf/NightElfPlugin.tsx b/packages/login/src/wallets/elf/NightElfPlugin.tsx deleted file mode 100644 index a69d8b56..00000000 --- a/packages/login/src/wallets/elf/NightElfPlugin.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { useDebounceFn } from 'ahooks'; -import PluginEntry from '../../components/PluginEntry'; -import isMobile from '../../utils/isMobile'; -import { check } from './utils'; -import { NightElfOptions } from '../../types'; -import { openNightElfPluginPage } from '../../utils/pluginPages'; - -export default function NightElfPlugin({ - nightEflOpts, - onClick, -}: { - nightEflOpts: NightElfOptions; - onClick: () => void; -}) { - const { run: onClickInternal } = useDebounceFn( - async () => { - const type = await check(); - if (type === 'none' && !isMobile()) { - if (nightEflOpts?.onPluginNotFound) { - nightEflOpts?.onPluginNotFound(openNightElfPluginPage); - } else { - openNightElfPluginPage(); - } - return; - } - if (type === 'unknown') return; - onClick(); - }, - { - wait: 500, - maxWait: 500, - leading: true, - trailing: false, - }, - ); - - const onClickButton = () => { - if (nightEflOpts.onClick) { - nightEflOpts.onClick(onClickInternal); - } else { - onClickInternal(); - } - }; - - return ; -} diff --git a/packages/login/src/wallets/elf/detectNightElf.ts b/packages/login/src/wallets/elf/detectNightElf.ts deleted file mode 100644 index 94946bd9..00000000 --- a/packages/login/src/wallets/elf/detectNightElf.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { check } from './utils'; - -export default function detectNightElf() { - return check(); -} diff --git a/packages/login/src/wallets/elf/useElf.ts b/packages/login/src/wallets/elf/useElf.ts deleted file mode 100644 index 948926af..00000000 --- a/packages/login/src/wallets/elf/useElf.ts +++ /dev/null @@ -1,326 +0,0 @@ -import { useRef, useMemo, useCallback, useEffect, useState } from 'react'; -import { useAElfReact } from '@aelf-react/core'; -import { getConfig } from '../../config'; -import { CallContractParams, DoSwitchFunc, SignatureParams, SwitchWalletFunc, WalletHookInterface } from '../../types'; -import { WalletHookParams } from '../types'; -import { NightElfOptions } from '../../types'; -import { WalletType, WebLoginState, WebLoginEvents } from '../../constants'; -import isMobile from '../../utils/isMobile'; -import checkSignatureParams from '../../utils/signatureParams'; -import detectNightElf from './detectNightElf'; - -export function useElf({ - options, - loginState, - eventEmitter, - setLoading, - setLoginError, - setLoginState, - setWalletType, -}: WalletHookParams) { - const chainId = getConfig().chainId; - const nodes = getConfig().aelfReact.nodes; - - const timeoutLoginingRef = useRef<() => void>(() => { - console.log('timeoutLoginingRef'); - }); - const eagerlyCheckRef = useRef(false); - const initializingRef = useRef(false); - const { isActive, account, pubKey, name, aelfBridges, activate, deactivate } = useAElfReact(); - const nightElfInfo = useAElfReact(); - const [switching, setSwitching] = useState(false); - - const bridge = useMemo(() => { - return aelfBridges?.[chainId]; - }, [aelfBridges, chainId]); - - const chain = useMemo(() => { - const bridge = aelfBridges?.[chainId]; - return bridge?.chain; - }, [aelfBridges, chainId]); - - const initialWallet = useCallback(async () => { - if (initializingRef.current) return; - initializingRef.current = true; - setLoading(true); - try { - const type = await detectNightElf(); - - if (type !== 'AelfBridge') { - if (options.useMultiChain) { - if (aelfBridges) { - await Promise.all( - Object.values(aelfBridges).map((bridge) => { - return bridge.chain.getChainStatus(); - }), - ); - } - } else { - await chain!.getChainStatus(); - } - } - setWalletType(WalletType.elf); - setLoginState(WebLoginState.logined); - eventEmitter.emit(WebLoginEvents.LOGINED); - } catch (error) { - setWalletType(WalletType.unknown); - setLoginError(error); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGIN_ERROR, error); - } finally { - setLoading(false); - } - initializingRef.current = false; - }, [ - setLoading, - setWalletType, - setLoginState, - eventEmitter, - options.useMultiChain, - aelfBridges, - chain, - setLoginError, - ]); - - useEffect(() => { - if (switching) return; - if (isActive && loginState === WebLoginState.logining) { - initialWallet(); - } - }, [isActive, loginState, initialWallet, switching]); - - const timeoutLogining = useCallback(() => { - if (loginState !== WebLoginState.logining) return; - if (!isActive) { - console.log('cancel login: timeout'); - localStorage.removeItem('aelf-connect-eagerly'); - setLoginState(WebLoginState.initial); - setLoading(false); - eventEmitter.emit(WebLoginEvents.USER_CANCEL); - eventEmitter.emit(WebLoginEvents.BRIDGE_CANCEL); - } - }, [eventEmitter, isActive, loginState, setLoading, setLoginState]); - timeoutLoginingRef.current = timeoutLogining; - - const login = useCallback(async () => { - let timer; - try { - setLoginState(WebLoginState.logining); - timer = setTimeout(() => { - timeoutLoginingRef.current(); - }, 8000); - console.log('activate'); - await activate(nodes); - console.log('activated'); - } catch (e) { - setLoading(false); - setLoginError(e); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGIN_ERROR, e); - } finally { - clearTimeout(timer); - } - }, [activate, eventEmitter, nodes, setLoading, setLoginError, setLoginState]); - - const loginEagerly = useCallback(async () => { - setLoading(true); - try { - console.log('connectEagerly', loginState); - setLoginState(WebLoginState.logining); - await login(); - } catch (e) { - localStorage.removeItem('aelf-connect-eagerly'); - setLoading(false); - setLoginError(e); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGIN_ERROR, e); - } - }, [eventEmitter, login, loginState, setLoading, setLoginError, setLoginState]); - - const logout = useCallback(async () => { - setLoginState(WebLoginState.logouting); - try { - localStorage.removeItem('aelf-connect-eagerly'); - await deactivate(); - } catch (e) { - console.warn(e); - } - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGOUT); - }, [deactivate, eventEmitter, setLoginState]); - - const logoutSilently = useCallback(async () => { - try { - localStorage.removeItem('aelf-connect-eagerly'); - if (isActive) { - await deactivate(); - } - } catch (e) { - console.warn(e); - } - }, [deactivate, isActive]); - - const switchWallet: SwitchWalletFunc = useCallback( - async (doSwitch: DoSwitchFunc) => { - if (loginState !== WebLoginState.logined) { - throw new Error(`Switch wallet on invalid state: ${loginState}`); - } - if (switching) { - throw new Error('Switching wallet'); - } - setSwitching(true); - await doSwitch( - async () => { - // logout silent - try { - localStorage.removeItem('aelf-connect-eagerly'); - await deactivate(); - } catch (e) { - console.warn(e); - } finally { - setSwitching(false); - } - }, - async () => { - setSwitching(false); - setWalletType(WalletType.elf); - setLoginState(WebLoginState.logined); - }, - ); - }, - [deactivate, loginState, setLoginState, setWalletType, switching], - ); - - const callContract = useCallback( - async function callContractFunc(params: CallContractParams): Promise { - if (!isActive || !account || !chain) { - throw new Error('Elf not login'); - } - // TODO: fixes cache contract - const contract = await chain.contractAt(params.contractAddress, { - address: account!, - }); - return await contract[params.methodName](params.args); - }, - [isActive, chain, account], - ); - - const getSignatureInMobileApp = useCallback( - async (params: SignatureParams) => { - if (!bridge || !isActive) { - throw new Error('Elf not login'); - } - if (!bridge.sendMessage) { - throw new Error('bridge.sendMessage is not a function'); - } - let hex = ''; - if (params.hexToBeSign) { - hex = params.hexToBeSign!; - } else { - hex = params.signInfo; - } - const signedMsgObject = await bridge.sendMessage('keyPairUtils', { - method: 'sign', - arguments: [hex], - }); - if (!signedMsgObject) { - throw new Error('signedMsgObject is null'); - } - if (signedMsgObject?.error) { - throw new Error( - signedMsgObject.errorMessage.message || signedMsgObject.errorMessage || signedMsgObject.message, - ); - } - const signedMsgString = [ - signedMsgObject.r.toString(16, 64), - signedMsgObject.s.toString(16, 64), - `0${signedMsgObject.recoveryParam.toString()}`, - ].join(''); - return { - error: 0, - errorMessage: '', - signature: signedMsgString, - from: 'aelf-bridge', - }; - }, - [bridge, isActive], - ); - - const getSignature = useCallback( - async (params: SignatureParams) => { - checkSignatureParams(params); - if (!bridge || !isActive) { - throw new Error('Elf not login'); - } - if (!bridge.getSignature) { - return await getSignatureInMobileApp(params); - } - let hex = ''; - if (params.hexToBeSign) { - hex = params.hexToBeSign!; - } else { - hex = params.signInfo; - } - const signature = await bridge!.getSignature({ - address: params.address, - hexToBeSign: hex, - }); - return signature; - }, - [bridge, getSignatureInMobileApp, isActive], - ); - - useEffect(() => { - if (eagerlyCheckRef.current) { - return; - } - eagerlyCheckRef.current = true; - const canEagerly = localStorage.getItem('aelf-connect-eagerly') === 'true'; - if (canEagerly) { - if (options.connectEagerly) { - if (loginState === WebLoginState.initial) { - loginEagerly(); - } - } else { - setLoginState(WebLoginState.eagerly); - } - } - }, [loginState, loginEagerly, setLoginState, options.connectEagerly]); - - return useMemo( - () => ({ - wallet: { - name, - address: account || '', - publicKey: pubKey, - nightElfInfo, - accountInfoSync: { - syncCompleted: loginState === WebLoginState.logined, - holderInfo: undefined, - }, - }, - loginEagerly, - login, - logout, - switchWallet, - loginBySwitch: login, - logoutSilently, - callContract, - getSignature, - }), - [ - name, - account, - pubKey, - nightElfInfo, - loginState, - loginEagerly, - login, - logout, - logoutSilently, - switchWallet, - callContract, - getSignature, - ], - ); -} diff --git a/packages/login/src/wallets/elf/utils.ts b/packages/login/src/wallets/elf/utils.ts deleted file mode 100644 index cba0098e..00000000 --- a/packages/login/src/wallets/elf/utils.ts +++ /dev/null @@ -1,50 +0,0 @@ -import AelfBridgeCheck from './AelfBridgeCheck'; -import NightElfCheck from './NightElfCheck'; - -let checking = 0; -let type = 'unknown'; - -export function check() { - return new Promise((resolve) => { - if (type !== 'unknown') { - resolve(type); - return; - } - - if (checking <= 0) { - checking++; - NightElfCheck.getInstance() - .check() - .then(() => { - type = 'NightElf'; - }) - .catch((error) => { - console.log(error.message); - }) - .finally(() => { - checking--; - }); - checking++; - AelfBridgeCheck.getInstance().check!() - .then(() => { - type = 'AelfBridge'; - }) - .catch((error) => { - console.log(error.message); - }) - .finally(() => { - checking--; - }); - } - - const interval = setInterval(() => { - if (checking <= 0) { - if (type === 'unknown') { - type = 'none'; - } - clearInterval(interval); - resolve(type); - } - }, 100); - }); -} diff --git a/packages/login/src/wallets/portkey/Portkey.tsx b/packages/login/src/wallets/portkey/Portkey.tsx deleted file mode 100644 index 79a4ee89..00000000 --- a/packages/login/src/wallets/portkey/Portkey.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { ReactNode, useCallback, useRef, useEffect, useState, useMemo } from 'react'; -import { DIDWalletInfo, SignIn, Unlock, SignInInterface } from '@portkey/did-ui-react'; -import { getConfig } from '../../config'; -import { WebLoginState } from '../../constants'; -import { PortkeyOptions } from '../../types'; - -export default function Portkey({ - open, - loginState, - isManagerExists, - portkeyOpts, - onCancel, - onFinish, - onError, - onUnlock, - extraWallets, -}: { - open: boolean; - loginState: WebLoginState; - isManagerExists: boolean; - portkeyOpts: PortkeyOptions; - onCancel: () => void; - onError: (error: any) => void; - onFinish: (didWalletInfo: DIDWalletInfo) => void; - onUnlock: (password: string) => Promise; - extraWallets: ReactNode; -}) { - const signInRef = useRef(null); - const [password, setPassword] = useState(''); - const [isWrongPassword, setIsWrongPassword] = useState(false); - const chainId = getConfig().chainId; - - useEffect(() => { - if (signInRef.current) { - signInRef.current.setOpen(open); - } - }, [open]); - - const onFinishInternal = useCallback( - (didWallet: DIDWalletInfo) => { - onFinish(didWallet); - }, - [onFinish], - ); - - const onErrorInternal = useCallback( - (error: any) => { - onError(error); - }, - [onError], - ); - - const onUnlockInternal = useCallback(async () => { - const success = await onUnlock(password); - if (!success) { - setIsWrongPassword(true); - } else { - setIsWrongPassword(false); - setPassword(''); - } - }, [onUnlock, password]); - - if (isManagerExists && (loginState === WebLoginState.logining || loginState === WebLoginState.lock)) { - return ( - - ); - } - - const SignInComponent = portkeyOpts.SignInComponent || SignIn; - return ( - - ); -} diff --git a/packages/login/src/wallets/portkey/useAccountInfoSync.ts b/packages/login/src/wallets/portkey/useAccountInfoSync.ts deleted file mode 100644 index 7d2cf88a..00000000 --- a/packages/login/src/wallets/portkey/useAccountInfoSync.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { useState, useCallback, useEffect } from 'react'; -import { WebLoginState } from '../../constants'; -import { useInterval } from 'ahooks'; -import { ChainId } from '@portkey/types'; -import type { IHolderInfo } from '@portkey/services'; -import { DIDWalletInfo, did } from '@portkey/did-ui-react'; - -export default function useAccountInfoSync( - chainId: string, - loginState: WebLoginState, - shouldSync: boolean, - didWalletInfo?: DIDWalletInfo, -) { - const currentChainId = chainId as ChainId; - const [syncCompleted, setSyncCompleted] = useState(false); - const [holderInfo, setHolderInfo] = useState(); - - const checkHolderInfo = useCallback(async () => { - if (loginState !== WebLoginState.logined) { - setSyncCompleted(false); - setHolderInfo(undefined); - return; - } - if (!shouldSync) return; - if (syncCompleted) return; - const holder = await did.didWallet.getHolderInfoByContract({ - chainId: currentChainId, - caHash: didWalletInfo?.caInfo.caHash, - // manager: did.didWallet.managementAccount!.address, - }); - const filteredHolders = holder.managerInfos.filter( - (manager) => manager?.address === didWalletInfo?.walletInfo?.address, - ); - setHolderInfo(holder); - setSyncCompleted(filteredHolders.length > 0); - }, [ - currentChainId, - didWalletInfo?.caInfo.caHash, - didWalletInfo?.walletInfo?.address, - loginState, - shouldSync, - syncCompleted, - ]); - - useEffect(() => { - if (loginState !== WebLoginState.logined) { - setHolderInfo(undefined); - setSyncCompleted(false); - } else { - checkHolderInfo(); - } - }, [checkHolderInfo, loginState]); - - useInterval(checkHolderInfo, 10000, { - immediate: true, - }); - - return { - syncCompleted, - holderInfo, - }; -} diff --git a/packages/login/src/wallets/portkey/usePortkey.ts b/packages/login/src/wallets/portkey/usePortkey.ts deleted file mode 100644 index e3af47b8..00000000 --- a/packages/login/src/wallets/portkey/usePortkey.ts +++ /dev/null @@ -1,392 +0,0 @@ -import { useState, useMemo, useRef, useEffect, useCallback } from 'react'; -import { getContractBasic } from '@portkey/contracts'; -import { DIDWalletInfo, did } from '@portkey/did-ui-react'; -import { ChainId } from '@portkey/types'; -import { getConfig } from '../../config'; -import { - CallContractParams, - DoSwitchFunc, - PortkeyInfo, - SignatureParams, - SwitchWalletFunc, - WalletHookInterface, -} from '../../types'; -import { WalletHookParams } from '../types'; -import { WalletType, WebLoginEvents, WebLoginState } from '../../constants'; -import useAccountInfoSync from './useAccountInfoSync'; -import checkSignatureParams from '../../utils/signatureParams'; -import { PortkeyOptions } from 'src/types'; - -const PORTKEY_ORIGIN_CHAIN_ID_KEY = 'PortkeyOriginChainId'; - -export type PortkeyInterface = WalletHookInterface & { - isManagerExists: boolean; - isUnlocking: boolean; - isPreparing: boolean; - lock: () => void; - onUnlock: (password: string) => Promise; - onError: (error: any) => void; - onFinished: (didWalletInfo: DIDWalletInfo) => void; - onCancel: () => void; -}; - -export function usePortkey({ - options, - loginState, - eventEmitter, - setWalletType, - setLoginError, - setLoginState, - setModalOpen, - setLoading, -}: WalletHookParams & { - setModalOpen: (open: boolean) => void; -}) { - const appName = getConfig().appName; - const chainId = getConfig().chainId as ChainId; - - const autoUnlockCheckRef = useRef(false); - const [didWalletInfo, setDidWalletInfo] = useState(); - - const [switching, setSwitching] = useState(false); - const [isUnlocking, setUnlocking] = useState(false); - const [isPreparing, setPreparing] = useState(false); - const isManagerExists = useMemo(() => { - return loginState && !!localStorage.getItem(appName); - }, [appName, loginState]); - - const shouldCheckAccountInfoSync = - !!didWalletInfo && (options.checkAccountInfoSync === undefined || options.checkAccountInfoSync); - const accountInfoSync = useAccountInfoSync(chainId, loginState, shouldCheckAccountInfoSync, didWalletInfo); - - const loginEagerly = useCallback(async () => { - setLoginState(WebLoginState.logining); - setModalOpen(true); - }, [setLoginState, setModalOpen]); - - const login = useCallback(async () => { - setLoginState(WebLoginState.logining); - setModalOpen(true); - }, [setLoginState, setModalOpen]); - - const logout = useCallback(async () => { - setLoginState(WebLoginState.logouting); - try { - const originChainId = localStorage.getItem(PORTKEY_ORIGIN_CHAIN_ID_KEY); - localStorage.removeItem(PORTKEY_ORIGIN_CHAIN_ID_KEY); - if (originChainId) { - await did.logout({ - chainId: originChainId as ChainId, - }); - } - } catch (e) { - console.warn(e); - } - localStorage.removeItem(appName); - setDidWalletInfo(undefined); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGOUT); - }, [appName, eventEmitter, setLoginState]); - - const logoutSilently = useCallback(async () => { - setDidWalletInfo(undefined); - localStorage.removeItem(appName); - const originChainId = localStorage.getItem(PORTKEY_ORIGIN_CHAIN_ID_KEY); - localStorage.removeItem(PORTKEY_ORIGIN_CHAIN_ID_KEY); - try { - if (originChainId) { - await did.logout({ - chainId: originChainId as ChainId, - }); - } - } catch (e) { - console.warn(e); - } - }, [appName]); - - const switchWallet: SwitchWalletFunc = useCallback( - async (doSwitch: DoSwitchFunc) => { - if (loginState !== WebLoginState.logined) { - throw new Error(`Switch wallet on invalid state: ${loginState}`); - } - if (switching) { - throw new Error('Switching wallet'); - } - setSwitching(true); - await doSwitch( - async () => { - setDidWalletInfo(undefined); - setSwitching(false); - }, - async () => { - setSwitching(false); - setWalletType(WalletType.portkey); - setLoginState(WebLoginState.logined); - }, - ); - }, - [loginState, setLoginState, setWalletType, switching], - ); - - const lock = useCallback(async () => { - if (!didWalletInfo) { - throw new Error(`lock on invalid didWalletInfo: ${didWalletInfo}`); - } - if (loginState !== WebLoginState.logined) { - throw new Error(`lock on invalid login state: ${loginState}`); - } - try { - await did.reset(); - } catch (e) { - console.warn(e); - } - setDidWalletInfo(undefined); - setLoginState(WebLoginState.lock); - eventEmitter.emit(WebLoginEvents.LOCK); - }, [didWalletInfo, eventEmitter, loginState, setLoginState]); - - const callContract = useCallback( - async function callContractFunc(params: CallContractParams): Promise { - if (!didWalletInfo) { - throw new Error('Portkey not login'); - } - // TODO: fixes cache contract - const chainsInfo = await did.services.getChainsInfo(); - const chainInfo = chainsInfo.find((chain) => chain.chainId === chainId); - if (!chainInfo) { - throw new Error(`chain is not running: ${chainId}`); - } - const caContract = await getContractBasic({ - contractAddress: chainInfo.caContractAddress, - account: didWalletInfo.walletInfo, - rpcUrl: chainInfo.endPoint, - }); - const result = await caContract.callSendMethod('ManagerForwardCall', didWalletInfo.walletInfo.address, { - caHash: didWalletInfo.caInfo.caHash, - contractAddress: params.contractAddress, - methodName: params.methodName, - args: params.args, - }); - return result as R; - }, - [chainId, didWalletInfo], - ); - - const getSignature = useCallback( - async (params: SignatureParams) => { - checkSignatureParams(params); - if (!didWalletInfo) { - throw new Error('Portkey not login'); - } - let signInfo = ''; - if (params.hexToBeSign) { - signInfo = params.hexToBeSign; - } else { - signInfo = params.signInfo; - } - const signature = did.sign(signInfo).toString('hex'); - return { - error: 0, - errorMessage: '', - signature, - from: 'portkey', - }; - }, - [didWalletInfo], - ); - - useEffect(() => { - if (autoUnlockCheckRef.current) { - return; - } - autoUnlockCheckRef.current = true; - const canShowUnlock = isManagerExists; - if (canShowUnlock) { - if (options.autoShowUnlock && loginState === WebLoginState.initial) { - loginEagerly(); - } else { - setLoginState(WebLoginState.lock); - } - } - }, [isManagerExists, loginEagerly, setLoginState, loginState, options.autoShowUnlock]); - - const onUnlock = useCallback( - async (password: string) => { - setUnlocking(true); - try { - const localWallet = await did.load(password, appName); - if (!localWallet.didWallet.accountInfo.loginAccount) { - return Promise.resolve(false); - } - - setLoading(true); - let caInfo = localWallet.didWallet.caInfo[chainId]; - let caHash = caInfo?.caHash; - if (!caInfo) { - const key = Object.keys(localWallet.didWallet.caInfo)[0]; - caHash = localWallet.didWallet.caInfo[key].caHash; - caInfo = await did.didWallet.getHolderInfoByContract({ - caHash: caHash, - chainId: chainId as ChainId, - }); - } - - const originChainId = localStorage.getItem(PORTKEY_ORIGIN_CHAIN_ID_KEY); - let nickName = localWallet.didWallet.accountInfo.nickName || 'Wallet 01'; - if (originChainId) { - try { - const holderInfo = await did.getCAHolderInfo(originChainId as ChainId); - nickName = holderInfo.nickName; - } catch (error) { - console.warn(error); - } - } - - const didWalletInfo: DIDWalletInfo = { - caInfo, - pin: password, - chainId: originChainId as ChainId, - walletInfo: localWallet.didWallet.managementAccount!.wallet as any, - accountInfo: localWallet.didWallet.accountInfo as any, - }; - setLoading(false); - setDidWalletInfo({ - ...didWalletInfo, - accounts: { - [chainId]: caInfo.caAddress, - }, - nickName, - }); - setWalletType(WalletType.portkey); - setLoginState(WebLoginState.logined); - eventEmitter.emit(WebLoginEvents.LOGINED); - return Promise.resolve(true); - } catch (error) { - localStorage.removeItem(PORTKEY_ORIGIN_CHAIN_ID_KEY); - setLoading(false); - setLoginError(error); - setWalletType(WalletType.unknown); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGIN_ERROR, error); - return Promise.resolve(false); - } finally { - setUnlocking(false); - } - }, - [appName, chainId, eventEmitter, setLoading, setLoginError, setLoginState, setWalletType], - ); - - const onFinished = useCallback( - async (didWalletInfo: DIDWalletInfo) => { - setPreparing(true); - try { - localStorage.setItem(PORTKEY_ORIGIN_CHAIN_ID_KEY, didWalletInfo.chainId); - if (didWalletInfo.chainId !== chainId) { - const caInfo = await did.didWallet.getHolderInfoByContract({ - caHash: didWalletInfo.caInfo.caHash, - chainId: chainId, - }); - didWalletInfo.caInfo = { - caAddress: caInfo.caAddress, - caHash: caInfo.caHash, - }; - } - - let nickName = 'Wallet 01'; - try { - const holderInfo = await did.getCAHolderInfo(didWalletInfo.chainId); - nickName = holderInfo.nickName; - } catch (error) { - console.warn(error); - } - try { - await did.save(didWalletInfo.pin, appName); - } catch (error) { - console.warn(error); - } - setDidWalletInfo({ - ...didWalletInfo, - accounts: { - [chainId]: didWalletInfo.caInfo.caAddress, - }, - nickName, - }); - setWalletType(WalletType.portkey); - setLoginState(WebLoginState.logined); - eventEmitter.emit(WebLoginEvents.LOGINED); - } catch (error) { - setLoading(false); - setDidWalletInfo(undefined); - setWalletType(WalletType.unknown); - setLoginError(error); - setLoginState(WebLoginState.initial); - eventEmitter.emit(WebLoginEvents.LOGIN_ERROR, error); - } finally { - setPreparing(false); - } - }, - [appName, chainId, eventEmitter, setLoading, setLoginError, setLoginState, setWalletType], - ); - - const onError = useCallback( - (error: any) => { - eventEmitter.emit(WebLoginEvents.ERROR, error); - }, - [eventEmitter], - ); - - const onCancel = useCallback(() => { - setModalOpen(false); - setLoginState(isManagerExists ? WebLoginState.lock : WebLoginState.initial); - setLoginError(undefined); - eventEmitter.emit(WebLoginEvents.USER_CANCEL); - eventEmitter.emit(WebLoginEvents.MODAL_CANCEL); - }, [setModalOpen, setLoginState, isManagerExists, setLoginError, eventEmitter]); - - return useMemo( - () => ({ - isManagerExists, - isUnlocking, - isPreparing, - wallet: { - name: didWalletInfo?.nickName || 'Wallet 01', - address: didWalletInfo?.caInfo.caAddress || '', - publicKey: didWalletInfo?.walletInfo.keyPair.getPublic('hex') || '', - portkeyInfo: didWalletInfo, - accountInfoSync, - }, - loginEagerly, - login, - logout, - switchWallet, - loginBySwitch: login, - logoutSilently, - lock, - callContract, - onFinished, - onUnlock, - getSignature, - onError, - onCancel, - }), - [ - isManagerExists, - isUnlocking, - isPreparing, - didWalletInfo, - accountInfoSync, - loginEagerly, - login, - logout, - switchWallet, - logoutSilently, - lock, - callContract, - onFinished, - onUnlock, - getSignature, - onError, - onCancel, - ], - ); -} diff --git a/packages/login/src/wallets/types.ts b/packages/login/src/wallets/types.ts deleted file mode 100644 index 397ddead..00000000 --- a/packages/login/src/wallets/types.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { EventEmitter } from 'events'; -import type { WalletType, WebLoginState } from '../constants'; -import { WalletHookInterface } from '../types'; - -export type WalletHookParams = { - options: T; - walletType: WalletType; - loginState: WebLoginState; - eventEmitter: EventEmitter; - setLoginState: (state: WebLoginState) => void; - setLoginError: (error: any | unknown) => void; - setWalletType: (wallet: WalletType) => void; - setLoading: (loading: boolean) => void; -}; - -export type WalletHook = (params: WalletHookParams) => WalletHookInterface; - -export interface WalletContextType extends WalletHookInterface { - loginError?: any | unknown; - loginState: WebLoginState; -} diff --git a/packages/react/.eslintrc.json b/packages/react/.eslintrc.json new file mode 100644 index 00000000..e6ca75e2 --- /dev/null +++ b/packages/react/.eslintrc.json @@ -0,0 +1,49 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended", + "eslint-config-prettier", + "plugin:prettier/recommended" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 2021, + "sourceType": "module", + "allowImportExportEverywhere": true + }, + "settings": { + "react": { + "version": "18.2.0" + } + }, + "rules": { + "react/prop-types": 0, + "react/display-name": 0, + "react/react-in-jsx-scope": 0, + "no-async-promise-executor": 0, + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": 1, + "@typescript-eslint/explicit-module-boundary-types": 0, + "@typescript-eslint/ban-types": 0, + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-non-null-assertion": 0 + }, + "env": { + "browser": true, + "node": true + }, + "globals": { + "globalThis": "writable", + "chrome": "writable", + "browser": "readonly" + }, + + "plugins": ["react"], + "ignorePatterns": ["dist"] +} diff --git a/packages/react/.prettierrc b/packages/react/.prettierrc new file mode 100644 index 00000000..727dd3f3 --- /dev/null +++ b/packages/react/.prettierrc @@ -0,0 +1,21 @@ +{ + "jsxBracketSameLine": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "endOfLine": "lf", + "overrides": [ + { + "files": "*.css", + "options": { + "parser": "css" + } + }, + { + "files": "*.scss", + "options": { + "parser": "scss" + } + } + ] +} diff --git a/packages/react/global.d.ts b/packages/react/global.d.ts new file mode 100644 index 00000000..bd1fc2cc --- /dev/null +++ b/packages/react/global.d.ts @@ -0,0 +1,2 @@ +declare module 'aelf-sdk'; +declare module 'aelf-bridge'; diff --git a/packages/react/index.less b/packages/react/index.less new file mode 100644 index 00000000..26defaac --- /dev/null +++ b/packages/react/index.less @@ -0,0 +1,117 @@ +.aelf-web-login-extra { + + .aelf-web-login-btn { + align-items: center; + border: 1px solid var(--portkey-ui-border-1); + border-radius: var(--portkey-ui-primary-border-radius); + color: var(--portkey-ui-text-secondary); + display: flex; + font-size: 14px; + justify-content: center; + line-height: var(--portkey-ui-default-btn-h); + + > svg { + margin-right: 16px; + } + } + + &.web2-design { + .title { + color: var(--portkey-ui-font-2); + font-size: 14px; + font-weight: 500; + text-align: center; + margin-top: 24px; + margin-bottom: 16px; + } + + .buttons { + display: flex; + flex-direction: row; + gap: 8px; + margin-bottom: 24px; + + .aelf-web-login-btn { + justify-content: center; + + > svg { + margin-right: 12px; + } + } + } + } + + &.social-design { + .logo { + margin-top: 56px; + } + .title { + color: --portkey-ui-text-primary; + font-size: 22px; + font-weight: 600; + text-align: center; + line-height: 28px; + margin-top: 16px; + } + + .buttons { + margin-top: 32px; + display: flex; + flex-direction: column; + gap: 12px; + + .aelf-web-login-btn { + justify-content: start; + + > svg { + margin-left: 40px; + } + } + } + } + + &.crypto-design { + .title { + color: var(--portkey-ui-font-2); + font-size: 14px; + font-weight: 500; + text-align: center; + } + + .buttons { + margin-top: 16px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + margin-bottom: 42px; + gap: 50px; + + > .button { + width: 50px; + height: 64px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0; + margin: 0; + cursor: pointer; + + > svg { + width: 40px; + height: 40px; + } + + > span { + color: var(--portkey-ui-font-2); + text-align: center; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 20px; + } + } + } + } +} diff --git a/packages/react/jest.config.ts b/packages/react/jest.config.ts new file mode 100644 index 00000000..8c9c51ff --- /dev/null +++ b/packages/react/jest.config.ts @@ -0,0 +1,5 @@ +import base from '../../jest.config'; + +export default { + ...base, +}; diff --git a/packages/login/package.json b/packages/react/package.json similarity index 93% rename from packages/login/package.json rename to packages/react/package.json index e4416257..1b14bfec 100644 --- a/packages/login/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { - "name": "aelf-web-login", - "version": "1.0.11-alpha", + "name": "@aelf-web-login/react", + "version": "0.1.0", "main": "dist/esm/index.js", "types": "dist/types/index.d.ts", "exports": { @@ -33,6 +33,7 @@ "start": "tsc --watch", "lint": "eslint . --ext .tsx,.ts", "lint:md": "remark . -f -q", + "test": "jest", "dev": "pnpm run dev:tsc & pnpm run dev:types", "dev:tsc": "tsc --p tsconfig.esm.json --watch", "dev:types": "tsc --emitDeclarationOnly --p tsconfig.types.json --watch", @@ -47,14 +48,15 @@ "pub": "npm publish" }, "dependencies": { - "@aelf-react/core": "^0.1.19", "@portkey/contracts": "^1.2.2", "@portkey/detect-provider": "1.0.1-alpha.0", + "@portkey/did": "^1.2.2", "@portkey/did-ui-react": "^1.2.2", "@portkey/provider-types": "1.0.1-alpha.0", "@portkey/services": "^1.2.2", "@portkey/types": "^1.2.2", "@portkey/utils": "^1.2.2", + "@aelf-web-login/core": "workspace:*", "aelf-bridge": "^0.0.10", "aelf-sdk": "^3.2.40", "ahooks": "^3.7.7", diff --git a/packages/react/rollup.config.js b/packages/react/rollup.config.js new file mode 100644 index 00000000..e6a4c775 --- /dev/null +++ b/packages/react/rollup.config.js @@ -0,0 +1,3 @@ +import createConfig from '../../rollup.config.mjs'; + +export default createConfig('aelf-web-login', './tsconfig.cjs.json'); diff --git a/packages/react/src/context.tsx b/packages/react/src/context.tsx new file mode 100644 index 00000000..4ca5489b --- /dev/null +++ b/packages/react/src/context.tsx @@ -0,0 +1,42 @@ +import React, { createContext, useContext, useMemo } from 'react'; +import { NightElfProvider, useNightElf } from './nightElf/context'; +import { PortkeySDKProvider, PortkeySDKProviderProps, usePortkeyUISDK } from './portkey/context'; +import { DiscoverProvider, useDiscover } from './discover/context'; +import { ReactWebLogin } from './webLogin'; + +type WebLoginContextType = { + webLogin: ReactWebLogin; +}; + +const WebLoginContext = createContext({} as WebLoginContextType); + +export function useWebLogin() { + return useContext(WebLoginContext).webLogin; +} + +export type WebLoginProps = { + portkey: Omit; + children: React.ReactNode; +}; + +export function WebLoginContextWrapper({ children }: { children: React.ReactNode }) { + const portkeySDK = usePortkeyUISDK(); + const nightElf = useNightElf(); + const discover = useDiscover(); + const webLogin = useMemo(() => { + return new ReactWebLogin({ portkeySDK, nightElf, discover }); + }, [portkeySDK, nightElf, discover]); + return {children}; +} + +export function WebLoginProvider(props: WebLoginProps) { + return ( + + + + {props.children} + + + + ); +} diff --git a/packages/react/src/discover/context.tsx b/packages/react/src/discover/context.tsx new file mode 100644 index 00000000..a82f9077 --- /dev/null +++ b/packages/react/src/discover/context.tsx @@ -0,0 +1,21 @@ +import { Discover } from '@aelf-web-login/core'; +import { createContext, useContext, useMemo } from 'react'; + +export type DiscoverProviderProps = { + children: React.ReactNode; +}; + +type DiscoverContextType = { + discover: Discover; +}; + +const DiscoverContext = createContext({} as DiscoverContextType); + +export function useDiscover(): Discover { + return useContext(DiscoverContext).discover; +} + +export function DiscoverProvider({ children }: DiscoverProviderProps) { + const discover = useMemo(() => new Discover(), []); + return {children}; +} diff --git a/packages/react/src/hooks/useExtraWalletLogin.tsx b/packages/react/src/hooks/useExtraWalletLogin.tsx new file mode 100644 index 00000000..aa2f3daf --- /dev/null +++ b/packages/react/src/hooks/useExtraWalletLogin.tsx @@ -0,0 +1,10 @@ +import { ILogin, WalletInfo } from '@aelf-web-login/core'; + +export type CryptoWalletType = 'discover' | 'nightElf'; + +export function useExtraWalletLogin(login: ILogin) { + const handleLogin = () => login.login(); + // TODO debounce + // TODO check env + return handleLogin; +} diff --git a/packages/react/src/icons/IconNightElf.tsx b/packages/react/src/icons/IconNightElf.tsx new file mode 100644 index 00000000..84bd7a4e --- /dev/null +++ b/packages/react/src/icons/IconNightElf.tsx @@ -0,0 +1,32 @@ +export default function IconNightElf(props: { type: 'circle' | 'plain' }) { + if (props.type === 'circle') { + return ( + + + + + + + ); + } + + return ( + + + + + + ); +} diff --git a/packages/react/src/icons/IconPortkey.tsx b/packages/react/src/icons/IconPortkey.tsx new file mode 100644 index 00000000..f51929be --- /dev/null +++ b/packages/react/src/icons/IconPortkey.tsx @@ -0,0 +1,49 @@ +export default function IconPortkey(props: { type: 'circle' | 'plain' }) { + if (props.type === 'circle') { + return ( + + + + + + + + + + + ); + } + return ( + + + + + + + + ); +} + +/** + * white theme & circle + + + + + */ diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts new file mode 100644 index 00000000..1424ca9c --- /dev/null +++ b/packages/react/src/index.ts @@ -0,0 +1,6 @@ +export * from './portkey/context'; +export * from './portkey/PortkeyUISDK'; +export * from './portkey/ExtraElement'; +export * from './context'; +export * from './webLogin'; +export * from './types'; diff --git a/packages/react/src/nightElf/context.tsx b/packages/react/src/nightElf/context.tsx new file mode 100644 index 00000000..0e6649f8 --- /dev/null +++ b/packages/react/src/nightElf/context.tsx @@ -0,0 +1,21 @@ +import { NightElf } from '@aelf-web-login/core'; +import { createContext, useContext, useMemo } from 'react'; + +export type NightElfProviderProps = { + children: React.ReactNode; +}; + +type NightElfContextType = { + nightElf: NightElf; +}; + +const NightElfContext = createContext({} as NightElfContextType); + +export function useNightElf(): NightElf { + return useContext(NightElfContext).nightElf; +} + +export function NightElfProvider({ children }: NightElfProviderProps) { + const nightElf = useMemo(() => new NightElf(), []); + return {children}; +} diff --git a/packages/react/src/portkey/ExtraElement.tsx b/packages/react/src/portkey/ExtraElement.tsx new file mode 100644 index 00000000..f854ed51 --- /dev/null +++ b/packages/react/src/portkey/ExtraElement.tsx @@ -0,0 +1,83 @@ +import { Button } from 'antd'; +import { PortkeyStyleProvider } from '@portkey/did-ui-react'; +import { PortkeySDKProviderProps, usePortkeyState } from './context'; +import IconPortkey from '../icons/IconPortkey'; +import IconNightElf from '../icons/IconNightElf'; +import { useExtraWalletLogin } from '../hooks/useExtraWalletLogin'; +import { useDiscover } from '../discover/context'; +import { useNightElf } from '../nightElf/context'; + +export default function ExtraElement(props: PortkeySDKProviderProps) { + const portkeyState = usePortkeyState(); + const design = portkeyState.design; + const showDiscover = props.showDiscover !== false; + const showNightElf = props.showNightElf !== false; + + const discoverLogin = useExtraWalletLogin(useDiscover()); + const nightElfLogin = useExtraWalletLogin(useNightElf()); + + if (!showDiscover && !showDiscover) return <>; + + const renderButtons = ({ iconType }: { iconType: 'circle' | 'plain' }) => { + return ( + <> + {showDiscover && ( + + )} + {showNightElf && ( + + )} + + ); + }; + + if (design === 'SocialDesign') { + const socialDesign = props.socialDesign || {}; + return ( + +
+
{socialDesign.logo && }
+
{socialDesign.title || 'Select Login Method'}
+
{renderButtons({ iconType: 'plain' })}
+
+
+ ); + } + + if (design === 'Web2Design') { + return ( + +
+
Crypto wallet
+
{renderButtons({ iconType: 'circle' })}
+
+
+ ); + } + + return ( + +
+
Crypto wallet
+
+ {showDiscover && ( +
+ + Portkey +
+ )} + {showNightElf && ( +
+ + Night Elf +
+ )} +
+
+
+ ); +} diff --git a/packages/react/src/portkey/PortkeyUISDK.ts b/packages/react/src/portkey/PortkeyUISDK.ts new file mode 100644 index 00000000..aa457ca0 --- /dev/null +++ b/packages/react/src/portkey/PortkeyUISDK.ts @@ -0,0 +1,131 @@ +import { DIDWalletInfo, SignInInterface, did } from '@portkey/did-ui-react'; +import { PortkeySDK, makeError, ERR_CODE, CancelablePromise, newCancelablePromise } from '@aelf-web-login/core'; +import { RefObject } from 'react'; +import { PortkeyState, PromiseHolder } from '../types'; +import { ChainId } from '@portkey/types'; + +const ORIGIN_CHAIN_ID_KEY = `AElf.PortkeyUISDK.OriginChainId`; + +export class PortkeyUISDK extends PortkeySDK { + readonly portkeyState: PortkeyState; + readonly signInfRef: RefObject; + setUnlockOpen: (open: boolean) => void; + + private _promiseHolder: PromiseHolder; + + constructor( + portkeyState: PortkeyState, + signInfRef: RefObject, + setUnlockOpen: (open: boolean) => void, + ) { + super(); + this.portkeyState = portkeyState; + this.signInfRef = signInfRef; + this.setUnlockOpen = setUnlockOpen; + } + + loginEagerly(): Promise { + if (this.canLoginEagerly()) { + Promise.reject(makeError(ERR_CODE.LOGIN_EAGERLY_FAIL)); + } + this.loginState = 'logining'; + this.setUnlockOpen(true); + return new Promise((resolve, reject) => { + this._promiseHolder = { + resolve: () => { + this.setUnlockOpen(false); + resolve(); + }, + reject, + }; + }); + } + + login(): CancelablePromise { + if (this.portkeyState.uiType !== 'Modal') { + throw new Error('login only support Modal uiType'); + } + if (this.loginState !== 'initial') { + throw new Error(`call login when loginState is not initial ${this.loginState}`); + } + this.loginState = 'logining'; + const signIn = this.signInfRef.current!; + signIn.setOpen(true); + + return newCancelablePromise((resolve, reject, onCancel) => { + onCancel(() => { + this.loginState = 'initial'; + this._promiseHolder = undefined; + signIn.setOpen(false); + }); + this._promiseHolder = { + resolve: () => { + signIn.setOpen(false); + resolve(); + }, + reject: (error: any) => { + reject(error); + }, + }; + }); + } + + async logout(): Promise { + if (this.loginState !== 'logined') { + throw new Error(`call logout when loginState is ${this.loginState}`); + } + const originChainId = localStorage.getItem(ORIGIN_CHAIN_ID_KEY); + if (originChainId && this.walletInfo.did) { + await this.walletInfo.did.logout({ + chainId: originChainId as ChainId, + }); + } + this.setLoginEagerly(false); + localStorage.removeItem(ORIGIN_CHAIN_ID_KEY); + this.loginState = 'initial'; + } + + onFinish(didWalletInfo: DIDWalletInfo) { + if (this.loginState !== 'logining') { + console.warn('onFinish called when loginState is not logining', this.loginState); + return; + } + this.loginState = 'logined'; + this.walletInfo = { + address: didWalletInfo?.caInfo.caAddress || '', + originChainId: didWalletInfo.chainId, + did: did, + }; + localStorage.setItem(ORIGIN_CHAIN_ID_KEY, didWalletInfo.chainId); + this.setLoginEagerly(true); + this._promiseHolder?.resolve(); + } + + onError(error: any) { + console.error(error); + console.warn('onError called when loginState is not logining', this.loginState); + this.emit('commonError', { + code: ERR_CODE.PORTKEY_SDK_COMMON_ERROR, + error: error, + }); + } + + onUnlock() { + this.loginState = 'logined'; + this.walletInfo = { + address: did.didWallet!.caInfo[this.portkeyState.defaultChainId]?.caAddress || '', + originChainId: localStorage.getItem(ORIGIN_CHAIN_ID_KEY) || undefined, + did: did, + }; + this._promiseHolder?.resolve(); + } + + onCancel() { + if (this.loginState !== 'logining') { + console.warn('onCancel called when loginState is not logining', this.loginState); + return; + } + this.loginState = 'initial'; + this._promiseHolder?.reject(makeError(ERR_CODE.USER_CANCEL)); + } +} diff --git a/packages/react/src/portkey/context.tsx b/packages/react/src/portkey/context.tsx new file mode 100644 index 00000000..42dca821 --- /dev/null +++ b/packages/react/src/portkey/context.tsx @@ -0,0 +1,136 @@ +import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { PortkeyProvider, SignIn, SignInInterface, Unlock, did } from '@portkey/did-ui-react'; +import { PortkeyUISDK } from './PortkeyUISDK'; +import ExtraElement from './ExtraElement'; +import { PortkeyState } from '../types'; + +export type PortkeySDKProviderProps = PortkeyState & { + appName: string; + customPortkeySDK?: PortkeyUISDK | (() => PortkeyUISDK); + customPortkeyUI?: boolean; + showNightElf?: boolean; + showDiscover?: boolean; + socialDesign?: + | { + logo?: string | undefined; + title?: string | undefined; + } + | undefined; + children: React.ReactNode; +}; + +type PortkeySDKContextType = PortkeyState & { + portkeySDK: PortkeyUISDK; +}; + +const PortkeySDKContext = createContext({} as PortkeySDKContextType); + +export function usePortkeyUISDK() { + return useContext(PortkeySDKContext).portkeySDK; +} + +export function usePortkeyState(): PortkeyState { + return useContext(PortkeySDKContext); +} + +export function PortkeySDKProvider(props: PortkeySDKProviderProps) { + const { customPortkeySDK, customPortkeyUI, children, chainType, networkType, theme, uiType, design, defaultChainId } = + props; + const signInRef = useRef(null); + const [password, setPassword] = useState(''); + const [unlockOpen, setUnlockOpen] = useState(false); + const [isWrongPassword, setIsWrongPassword] = useState(false); + + const portkeySDK = useMemo( + () => { + if (customPortkeySDK) { + if (typeof customPortkeySDK === 'function') { + return customPortkeySDK(); + } + return customPortkeySDK; + } + const sdk = new PortkeyUISDK( + { + chainType, + networkType, + theme, + uiType, + defaultChainId, + design, + }, + signInRef, + setUnlockOpen, + ); + return sdk; + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ); + + const value = useMemo( + () => ({ defaultChainId, chainType, networkType, theme, uiType, design, portkeySDK }), + [chainType, defaultChainId, design, networkType, portkeySDK, theme, uiType], + ); + + const onUnlockInternal = async () => { + let localWallet; + try { + localWallet = await did.load(password, props.appName); + if (!localWallet) { + setIsWrongPassword(true); + return; + } + if (!localWallet.didWallet.accountInfo.loginAccount) { + setIsWrongPassword(true); + return; + } + setIsWrongPassword(false); + setPassword(''); + + portkeySDK.onUnlock(); + } catch (error) { + setIsWrongPassword(true); + return; + } + }; + + useEffect(() => { + portkeySDK.setUnlockOpen = setUnlockOpen; + }, [portkeySDK, setUnlockOpen]); + + const renderChildren = () => { + if (customPortkeyUI) { + return children; + } + + return ( + <> + {children} + } + onCancel={() => portkeySDK.onCancel()} + onError={(error) => portkeySDK.onError(error)} + onFinish={(didWalletInfo) => portkeySDK.onFinish(didWalletInfo)} + /> + portkeySDK.onCancel()} + onUnlock={onUnlockInternal} + /> + + ); + }; + + return ( + + {renderChildren()}; + + ); +} diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts new file mode 100644 index 00000000..eed49a3b --- /dev/null +++ b/packages/react/src/types.ts @@ -0,0 +1,20 @@ +import type { TDesign, Theme, UI_TYPE } from '@portkey/did-ui-react'; +import type { ChainId, ChainType, NetworkType } from '@portkey/provider-types'; + +export type { Theme } from '@portkey/did-ui-react'; + +export type PortkeyState = { + defaultChainId: ChainId; + theme?: Theme; + networkType: NetworkType; + chainType: ChainType; + uiType: UI_TYPE; + design: TDesign; +}; + +export type PromiseHolder = + | { + resolve: () => void; + reject: (error: any) => void; + } + | undefined; diff --git a/packages/react/src/webLogin.ts b/packages/react/src/webLogin.ts new file mode 100644 index 00000000..0faeb770 --- /dev/null +++ b/packages/react/src/webLogin.ts @@ -0,0 +1,122 @@ +import { + NightElf, + Discover, + WebLogin, + CancelablePromise, + newCancelablePromise, + makeError, + ERR_CODE, +} from '@aelf-web-login/core'; +import { PortkeyUISDK } from './portkey/PortkeyUISDK'; + +export class ReactWebLogin extends WebLogin { + private _portkeySDK: PortkeyUISDK; + private _nightElf: NightElf; + private _discover: Discover; + + constructor({ + portkeySDK, + nightElf, + discover, + }: { + portkeySDK: PortkeyUISDK; + nightElf: NightElf; + discover: Discover; + }) { + super(); + this._portkeySDK = portkeySDK; + this._nightElf = nightElf; + this._discover = discover; + } + + canLoginEagerly(): boolean { + return this._portkeySDK.canLoginEagerly() || this._discover.canLoginEagerly() || this._nightElf.canLoginEagerly(); + } + + setLoginEagerly(flag: boolean): void { + this._portkeySDK.setLoginEagerly(flag); + this._nightElf.setLoginEagerly(flag); + this._discover.setLoginEagerly(flag); + } + + loginEagerly(): Promise { + if (this._discover.canLoginEagerly()) { + return this._discover.loginEagerly(); + } + if (this._nightElf.canLoginEagerly()) { + return this._nightElf.loginEagerly(); + } + if (this._portkeySDK.canLoginEagerly()) { + this._portkeySDK.loginEagerly(); + } + return Promise.resolve(); + } + + login(): CancelablePromise { + if (this.loginState !== 'initial') { + throw new Error(`call login when loginState is not initial ${this.loginState}`); + } + if (!this._portkeySDK.signInfRef.current) { + throw new Error('call login on invalid state, portkeySDK.signInfRef.current is null'); + } + this.loginState = 'logining'; + return newCancelablePromise((resolve, reject, onCancel) => { + const loginPromise: CancelablePromise = this._portkeySDK.login(); + + const onLogined = () => { + const isPortkeySDKLogined = this._portkeySDK.loginState === 'logined'; + if (!isPortkeySDKLogined) { + loginPromise.cancel(); + } + + this._portkeySDK.off('logined', onLogined); + this._discover.off('logined', onLogined); + this._nightElf.off('logined', onLogined); + + if (this._discover.loginState === 'logined') { + this._current = this._discover; + } else if (this._portkeySDK.loginState === 'logined') { + this._current = this._portkeySDK; + } else if (this._nightElf.loginState === 'logined') { + this._current = this._nightElf; + } else { + this.reset(); + reject(makeError(ERR_CODE.USER_CANCEL)); + return; + } + this.loginState = 'logined'; + this.walletInfo = this._current.walletInfo; + this.walletType = this._current.walletType; + + resolve(); + }; + + this._portkeySDK.on('logined', onLogined); + this._discover.on('logined', onLogined); + this._nightElf.on('logined', onLogined); + + // TODO cancel event + + onCancel(() => { + this.loginState = 'initial'; + this._portkeySDK.off('logined', onLogined); + this._discover.off('logined', onLogined); + this._nightElf.off('logined', onLogined); + }); + }); + } + + logout(): Promise { + if (this._current) { + return this._current.logout(); + } + return Promise.reject(new Error('No wallet logined')); + } + + private reset(): void { + this.loginState = 'initial'; + this.walletInfo = { address: '' }; + this.walletType = 'Unknown'; + this._current = undefined; + } +} diff --git a/packages/react/test/index.test.ts b/packages/react/test/index.test.ts new file mode 100644 index 00000000..4e148ef7 --- /dev/null +++ b/packages/react/test/index.test.ts @@ -0,0 +1,7 @@ +import { describe, expect, test } from '@jest/globals'; + +describe('index', () => { + test('test', () => { + expect(1).toBe(1); + }); +}); diff --git a/packages/react/tsconfig.cjs.json b/packages/react/tsconfig.cjs.json new file mode 100644 index 00000000..a41760de --- /dev/null +++ b/packages/react/tsconfig.cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/cjs", + "declaration": false + } +} diff --git a/packages/react/tsconfig.esm.json b/packages/react/tsconfig.esm.json new file mode 100644 index 00000000..b75c80a8 --- /dev/null +++ b/packages/react/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/esm", + "declaration": false + } +} diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json new file mode 100644 index 00000000..43528897 --- /dev/null +++ b/packages/react/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "target": "ES2020", + "lib": ["DOM", "DOM.Iterable", "ES2021"], + "module": "ES2020", + "allowJs": false, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "moduleResolution": "Node", + "noImplicitReturns": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "baseUrl": "./", + "rootDir": "./src", + "allowSyntheticDefaultImports": true, + "noFallthroughCasesInSwitch": true, + "isolatedModules": true, + "allowUnreachableCode": false, + "experimentalDecorators": true + }, + "include": ["global.d.ts", "src", "src/index.ts"], + "exclude": ["dist", "node_modules"] +} diff --git a/packages/react/tsconfig.types.json b/packages/react/tsconfig.types.json new file mode 100644 index 00000000..b1c3478e --- /dev/null +++ b/packages/react/tsconfig.types.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/types", + "declaration": true + } +} diff --git a/packages/web/package.json b/packages/web/package.json new file mode 100644 index 00000000..bffd7c58 --- /dev/null +++ b/packages/web/package.json @@ -0,0 +1,38 @@ +{ + "private": true, + "name": "@aelf-web-login/web", + "version": "0.0.1-alpha.1", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": "./dist/index.js", + "./dist/index.css": "./dist/index.css" + }, + "scripts": { + "dev": "webpack --watch --config webpack.config.js", + "build": "webpack --config webpack.config.js" + }, + "dependencies": { + }, + "devDependencies": { + "@types/react-dom": "^18.0.0", + "react": "^18.2.0", + "react-dom": "^18.0.0", + "@aelf-web-login/core": "workspace:*", + "@aelf-web-login/react": "workspace:*", + "cross-env": "^7.0.3", + "vconsole": "^3.15.1" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/packages/web/rollup.config.js b/packages/web/rollup.config.js new file mode 100644 index 00000000..886ad29a --- /dev/null +++ b/packages/web/rollup.config.js @@ -0,0 +1,88 @@ +import esbuild from 'rollup-plugin-esbuild'; +import litCss from 'rollup-plugin-lit-css'; +import postcss from 'rollup-plugin-postcss'; +import url from '@rollup/plugin-url'; +import postcssUrl from 'postcss-url'; +import copy from 'rollup-plugin-copy'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; + +import minifyHtml from 'rollup-plugin-minify-html-literals'; +import { terser } from 'rollup-plugin-terser'; + +import path from 'path'; + +function createConfig(packageName, tsconfig = './tsconfig.json') { + const output = { + exports: 'named', + name: packageName, + sourcemap: true, + }; + + const production = !process.env.ROLLUP_WATCH; + + const esbuildPlugin = esbuild({ + minify: false, + tsconfig, + platform: 'browser', + treeShaking: true, + loaders: { + '.json': 'json', + }, + }); + + const litCssPlugin = litCss({ + include: ['**/*.css'], + uglify: true, + }); + + const copyPlugin = copy({ + targets: [ + // Need to copy the files over for usage + { src: 'src/assets/fonts', dest: 'dist/assets' }, + // { src: 'src/sandbox', dest: 'dist' }, + ], + }); + + const postcssPlugin = postcss({ + minimize: true, + modules: false, + autoModules: true, + extensions: ['.css', '.less'], + use: { + sass: null, + stylus: null, + }, + extract: path.resolve('dist/index.css'), + plugins: [ + postcssUrl({ + url: 'inline', // enable inline assets using base64 encoding + maxSize: 10, // maximum file size to inline (in kilobytes) + fallback: 'copy', // fallback method to use if max size is exceeded + }), + ], + }); + + const urlPlugin = url(); + + const terserPlugin = + production && + terser({ + compress: { + drop_console: production, + drop_debugger: production, + }, + output: { comments: false }, + }); + + return [ + { + input: './src/index.ts', + plugins: [nodeResolve(), commonjs(), litCssPlugin, minifyHtml, esbuildPlugin, postcssPlugin, urlPlugin, copyPlugin], + output: [{ file: './dist/index.js', format: 'cjs', ...output }], + }, + ]; +}; + +export default createConfig('web'); + diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts new file mode 100644 index 00000000..ddafd118 --- /dev/null +++ b/packages/web/src/index.ts @@ -0,0 +1,17 @@ +import { SDK } from './sdk'; +import setup from './setup'; + +const setupSDK = (() => { + let sdk: SDK | undefined = undefined; + return () => { + if (sdk) return sdk; + const delegate = setup(); + sdk = new SDK(delegate); + return sdk; + }; +})(); + +export default { + SDK, + setupSDK, +}; diff --git a/packages/web/src/sdk.ts b/packages/web/src/sdk.ts new file mode 100644 index 00000000..a64ab213 --- /dev/null +++ b/packages/web/src/sdk.ts @@ -0,0 +1,34 @@ +import { ReactWebLogin, Theme } from '@aelf-web-login/react'; + +export interface SDKDelegate { + webLogin: ReactWebLogin; + setTheme(theme: Theme): void; +} + +export class SDK { + constructor(private delegate: SDKDelegate) {} + + setTheme(theme: Theme) { + this.delegate.setTheme(theme); + } + + canLoginEagerly(): boolean { + return this.delegate.webLogin.canLoginEagerly(); + } + + setLoginEagerly(flag: boolean): void { + return this.delegate.webLogin.setLoginEagerly(flag); + } + + loginEagerly(): Promise { + return this.delegate.webLogin.loginEagerly(); + } + + login(): Promise { + return this.delegate.webLogin.login(); + } + + logout(): Promise { + return this.delegate.webLogin.logout(); + } +} diff --git a/packages/web/src/setup.tsx b/packages/web/src/setup.tsx new file mode 100644 index 00000000..01fc2e74 --- /dev/null +++ b/packages/web/src/setup.tsx @@ -0,0 +1,44 @@ +import React, { useState } from 'react'; +import { createRoot } from 'react-dom/client'; +import { WebLoginProvider, useWebLogin } from '@aelf-web-login/react'; +import { SDKDelegate } from './sdk'; + +const delegate: SDKDelegate = {} as any; + +function SDKContent() { + const webLogin = useWebLogin(); + delegate.webLogin = webLogin; + return <>; +} + +function SDKRoot() { + const [theme, setTheme] = useState<'dark' | 'light'>('light'); + delegate.setTheme = setTheme; + + return ( + + + + ); +} + +export default function setup() { + const container = document.createElement('div'); + container.id = 'aelf-web-login-root'; + const root = createRoot(container); + root.render( + + + , + ); + return delegate; +} diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json new file mode 100644 index 00000000..43528897 --- /dev/null +++ b/packages/web/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "target": "ES2020", + "lib": ["DOM", "DOM.Iterable", "ES2021"], + "module": "ES2020", + "allowJs": false, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "moduleResolution": "Node", + "noImplicitReturns": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "baseUrl": "./", + "rootDir": "./src", + "allowSyntheticDefaultImports": true, + "noFallthroughCasesInSwitch": true, + "isolatedModules": true, + "allowUnreachableCode": false, + "experimentalDecorators": true + }, + "include": ["global.d.ts", "src", "src/index.ts"], + "exclude": ["dist", "node_modules"] +} diff --git a/packages/web/tsconfig.types.json b/packages/web/tsconfig.types.json new file mode 100644 index 00000000..6c40c9d9 --- /dev/null +++ b/packages/web/tsconfig.types.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "declaration": true + } +} diff --git a/packages/web/webpack.config.js b/packages/web/webpack.config.js new file mode 100644 index 00000000..e779a901 --- /dev/null +++ b/packages/web/webpack.config.js @@ -0,0 +1,47 @@ +const path = require('path'); +const merge = require('webpack-merge'); + +module.exports = merge({ + mode: 'production', + entry: './src/index.ts', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'index.js', + library: { + name: 'AElfWebLogin', + type: 'umd', + }, + }, + resolve: { + extensions: ['.ts', '.js', '.tsx', '.jsx', '...'], + alias: { + react: path.resolve('./node_modules/react'), + }, + }, + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + loader: 'babel-loader', + }, + { + test: /\.(ts|tsx)$/, + exclude: /node_modules/, + loader: 'ts-loader', + }, + { + test: /\.(css|less)$/, + use: ['css-loader', 'less-loader'], + }, + { + test: /\.m?js$/, + resolve: { + fullySpecified: false, + }, + } + ], + }, + + plugins: [], +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49d2a005..2be40079 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,9 +32,15 @@ importers: '@next/bundle-analyzer': specifier: ^12.2.4 version: 12.2.4 + '@rollup/plugin-commonjs': + specifier: ^25.0.4 + version: 25.0.4(rollup@3.15.0) '@rollup/plugin-image': specifier: ^3.0.2 version: 3.0.2(rollup@3.15.0) + '@rollup/plugin-node-resolve': + specifier: ^15.1.0 + version: 15.1.0(rollup@3.15.0) '@rollup/plugin-url': specifier: ^8.0.1 version: 8.0.1(rollup@3.15.0) @@ -56,9 +62,18 @@ importers: babel-jest: specifier: ^29.3.1 version: 29.3.1(@babel/core@7.20.12) + babel-loader: + specifier: ^9.1.3 + version: 9.1.3(@babel/core@7.20.12)(webpack@5.88.2) browser-resolve: specifier: ^2.0.0 version: 2.0.0 + concurrently: + specifier: ^8.2.0 + version: 8.2.0 + css-loader: + specifier: ^6.8.1 + version: 6.8.1(webpack@5.88.2) esbuild: specifier: ^0.17.7 version: 0.17.7 @@ -86,8 +101,11 @@ importers: jest-environment-jsdom: specifier: ^29.4.3 version: 29.4.3 + less-loader: + specifier: ^11.1.3 + version: 11.1.3(less@4.1.3)(webpack@5.88.2) lint-staged: - specifier: '>=13' + specifier: ^13.0.0 version: 13.0.0 node-fetch: specifier: ^3.3.0 @@ -131,15 +149,91 @@ importers: ts-jest: specifier: ^29.0.5 version: 29.0.5(@babel/core@7.20.12)(babel-jest@29.3.1)(esbuild@0.17.7)(jest@29.3.1)(typescript@4.9.4) + ts-loader: + specifier: ^9.4.0 + version: 9.4.0(typescript@4.9.4)(webpack@5.88.2) ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@20.3.0)(typescript@4.9.4) typescript: specifier: ^4.9.4 version: 4.9.4 + webpack: + specifier: ^5.88.2 + version: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-cli: + specifier: ^5.1.4 + version: 5.1.4(webpack@5.88.2) + + packages/core: + dependencies: + '@portkey/contracts': + specifier: ^1.2.2 + version: 1.2.2 + '@portkey/detect-provider': + specifier: 1.0.1-alpha.0 + version: 1.0.1-alpha.0 + '@portkey/did': + specifier: ^1.2.2 + version: 1.2.2(react-dom@18.0.0) + '@portkey/did-ui-react': + specifier: ^1.2.2 + version: 1.2.2(i18next@22.5.1)(react-dom@18.0.0)(react@18.2.0) + '@portkey/provider-types': + specifier: 1.0.1-alpha.0 + version: 1.0.1-alpha.0 + '@portkey/services': + specifier: ^1.2.2 + version: 1.2.2(react-dom@18.0.0)(react@18.2.0) + '@portkey/types': + specifier: ^1.2.2 + version: 1.2.2 + '@portkey/utils': + specifier: ^1.2.2 + version: 1.2.2 + aelf-bridge: + specifier: ^0.0.10 + version: 0.0.10 + aelf-sdk: + specifier: ^3.2.40 + version: 3.2.40 + ahooks: + specifier: ^3.7.7 + version: 3.7.7(react@18.2.0) + antd: + specifier: ^4.24.4 + version: 4.24.4(react-dom@18.0.0)(react@18.2.0) + cancelable-promise: + specifier: ^4.3.1 + version: 4.3.1 + ismobilejs: + specifier: ^1.1.1 + version: 1.1.1 + typescript: + specifier: ^4.9.5 + version: 4.9.5 + devDependencies: + '@types/uuid': + specifier: ^8.3.4 + version: 8.3.4 + eslint-plugin-react: + specifier: ^7.32.2 + version: 7.32.2(eslint@7.32.0) + eslint-plugin-react-hooks: + specifier: ^4.6.0 + version: 4.6.0(eslint@7.32.0) + less: + specifier: ^4.1.3 + version: 4.1.3 packages/example: dependencies: + '@aelf-web-login/core': + specifier: workspace:* + version: link:../core + '@aelf-web-login/react': + specifier: workspace:* + version: link:../react '@portkey/did-ui-react': specifier: ^1.2.2 version: 1.2.2(i18next@22.5.1)(react-dom@18.0.0)(react@18.2.0) @@ -149,9 +243,6 @@ importers: '@types/react-dom': specifier: ^18.0.0 version: 18.0.0 - aelf-web-login: - specifier: workspace:* - version: link:../login ahooks: specifier: ^3.7.7 version: 3.7.7(react@18.2.0) @@ -166,7 +257,7 @@ importers: version: 18.0.0(react@18.2.0) react-scripts: specifier: ^5.0.1 - version: 5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(esbuild@0.17.7)(eslint@8.42.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5) + version: 5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(esbuild@0.17.7)(eslint@8.42.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5)(webpack-cli@5.1.4) vconsole: specifier: ^3.15.1 version: 3.15.1 @@ -179,19 +270,22 @@ importers: version: 7.0.3 ts-loader: specifier: ^9.4.0 - version: 9.4.0(typescript@4.9.5)(webpack@5.86.0) + version: 9.4.0(typescript@4.9.5)(webpack@5.88.2) - packages/login: + packages/react: dependencies: - '@aelf-react/core': - specifier: ^0.1.19 - version: 0.1.19(react@18.2.0) + '@aelf-web-login/core': + specifier: workspace:* + version: link:../core '@portkey/contracts': specifier: ^1.2.2 version: 1.2.2 '@portkey/detect-provider': specifier: 1.0.1-alpha.0 version: 1.0.1-alpha.0 + '@portkey/did': + specifier: ^1.2.2 + version: 1.2.2(react-dom@18.0.0) '@portkey/did-ui-react': specifier: ^1.2.2 version: 1.2.2(i18next@22.5.1)(react-dom@18.0.0)(react@18.2.0) @@ -236,6 +330,30 @@ importers: specifier: ^4.1.3 version: 4.1.3 + packages/web: + devDependencies: + '@aelf-web-login/core': + specifier: workspace:* + version: link:../core + '@aelf-web-login/react': + specifier: workspace:* + version: link:../react + '@types/react-dom': + specifier: ^18.0.0 + version: 18.0.0 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.0.0 + version: 18.0.0(react@18.2.0) + vconsole: + specifier: ^3.15.1 + version: 3.15.1 + packages: /@abp/core@7.2.3: @@ -261,24 +379,6 @@ packages: just-compare: 1.5.1 dev: false - /@aelf-react/core@0.1.19(react@18.2.0): - resolution: {integrity: sha512-s329rJOfpNJkw9yRkKA4yqk9iLBn0d2tYZolVt82xwThdslGgvkjf2SUsqkfR4p5cqAMzX94Dm9UdBXVtktNCw==} - peerDependencies: - react: '>=16.8' - dependencies: - '@aelf-react/types': 0.1.10 - aelf-bridge: 0.0.10 - react: 18.2.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: false - - /@aelf-react/types@0.1.10: - resolution: {integrity: sha512-oKEI07EeL8dhUqp8ze50mCXOqAS5psoOpdmCNZaFT2R62/GPoAyvtN8oaZAUb1tycpE+eUdkdv8XDblEsIIiLA==} - dev: false - /@aelfqueen/protobufjs@6.8.9: resolution: {integrity: sha512-xa8i/rsC/Dj6Wh0DWpgr4eODVu8tVktyTENJU0QGjwmu317PCyp/8p7rEcvplljAteoQ31cFxUCrnzFQ0iLG1g==} hasBin: true @@ -1846,7 +1946,7 @@ packages: cosmiconfig: 7.1.0 cross-spawn: 7.0.3 lodash: 4.17.21 - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(esbuild@0.17.7)(eslint@8.42.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(esbuild@0.17.7)(eslint@8.42.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5)(webpack-cli@5.1.4) semver: 7.5.1 webpack-merge: 4.2.2 dev: true @@ -2003,6 +2103,10 @@ packages: engines: {node: '>=10'} dev: false + /@discoveryjs/json-ext@0.5.7: + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + /@esbuild/android-arm64@0.17.7: resolution: {integrity: sha512-fOUBZvcbtbQJIj2K/LMKcjULGfXLV9R4qjXFsi3UuqFhIRJHz0Fp6kFjsMFI6vLuPrfC5G9Dmh+3RZOrSKY2Lg==} engines: {node: '>=12'} @@ -2838,7 +2942,7 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@pmmmwh/react-refresh-webpack-plugin@0.5.10(react-refresh@0.11.0)(webpack-dev-server@4.15.1)(webpack@5.86.0): + /@pmmmwh/react-refresh-webpack-plugin@0.5.10(react-refresh@0.11.0)(webpack-dev-server@4.15.1)(webpack@5.88.2): resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} engines: {node: '>= 10.13'} peerDependencies: @@ -2874,8 +2978,8 @@ packages: react-refresh: 0.11.0 schema-utils: 3.2.0 source-map: 0.7.4 - webpack: 5.86.0(esbuild@0.17.7) - webpack-dev-server: 4.15.1(webpack@5.86.0) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.88.2) /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} @@ -3181,6 +3285,24 @@ packages: '@rollup/pluginutils': 3.1.0(rollup@2.79.1) rollup: 2.79.1 + /@rollup/plugin-commonjs@25.0.4(rollup@3.15.0): + resolution: {integrity: sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.68.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.15.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.27.0 + rollup: 3.15.0 + dev: true + /@rollup/plugin-image@3.0.2(rollup@3.15.0): resolution: {integrity: sha512-eGVrD6lummWH5ENo9LWX3JY62uBb9okUNQ2htXkugrG6WjACrMUVhWvss+0wW3fwJWmFYpoEny3yL4spEdh15g==} engines: {node: '>=14.0.0'} @@ -3209,6 +3331,24 @@ packages: resolve: 1.22.2 rollup: 2.79.1 + /@rollup/plugin-node-resolve@15.1.0(rollup@3.15.0): + resolution: {integrity: sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.15.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.2 + rollup: 3.15.0 + dev: true + /@rollup/plugin-replace@2.4.2(rollup@2.79.1): resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} peerDependencies: @@ -3637,7 +3777,6 @@ packages: resolution: {integrity: sha512-49897Y0UiCGmxZqpC8Blrf6meL8QUla6eb+BBhn69dTXlmuOlzkfr7HHY/O8J25e1lTUMs+YYxSlVDAaGHCOLg==} dependencies: '@types/react': 18.2.11 - dev: false /@types/react@18.2.11: resolution: {integrity: sha512-+hsJr9hmwyDecSMQAmX7drgbDpyE+EgSF6t7+5QEBAn1tQK7kl1vWZ4iRf6SjQ8lk7dyEULxUmZOIpN0W5baZA==} @@ -3662,6 +3801,10 @@ packages: dependencies: '@types/node': 20.3.0 + /@types/resolve@1.20.2: + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + dev: true + /@types/retry@0.12.0: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} @@ -4127,6 +4270,40 @@ packages: '@webassemblyjs/ast': 1.11.6 '@xtuc/long': 4.2.2 + /@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.88.2): + resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} + engines: {node: '>=14.15.0'} + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + dependencies: + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.88.2) + + /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.88.2): + resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} + engines: {node: '>=14.15.0'} + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + dependencies: + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.88.2) + + /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.88.2): + resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} + engines: {node: '>=14.15.0'} + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + webpack-dev-server: '*' + peerDependenciesMeta: + webpack-dev-server: + optional: true + dependencies: + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.88.2) + /@wry/context@0.7.3: resolution: {integrity: sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==} engines: {node: '>=8'} @@ -4754,7 +4931,7 @@ packages: - supports-color dev: true - /babel-loader@8.3.0(@babel/core@7.20.12)(webpack@5.86.0): + /babel-loader@8.3.0(@babel/core@7.20.12)(webpack@5.88.2): resolution: {integrity: sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==} engines: {node: '>= 8.9'} peerDependencies: @@ -4766,7 +4943,20 @@ packages: loader-utils: 2.0.4 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + + /babel-loader@9.1.3(@babel/core@7.20.12)(webpack@5.88.2): + resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + dependencies: + '@babel/core': 7.20.12 + find-cache-dir: 4.0.0 + schema-utils: 4.1.0 + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + dev: true /babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} @@ -5218,6 +5408,10 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + /cancelable-promise@4.3.1: + resolution: {integrity: sha512-A/8PwLk/T7IJDfUdQ68NR24QHa8rIlnN/stiJEBo6dmVUkD4K14LswG0w3VwdeK/o7qOwRUR1k2MhK5Rpy2m7A==} + dev: false + /caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: @@ -5352,6 +5546,14 @@ packages: wrap-ansi: 7.0.0 dev: true + /clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + /clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} @@ -5405,6 +5607,10 @@ packages: dependencies: delayed-stream: 1.0.0 + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + /commander@2.17.1: resolution: {integrity: sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==} dev: true @@ -5500,6 +5706,22 @@ packages: source-map: 0.6.1 dev: true + /concurrently@8.2.0: + resolution: {integrity: sha512-nnLMxO2LU492mTUj9qX/az/lESonSZu81UznYDoXtz1IQf996ixVqPAgHXwvHiHCAef/7S8HIK+fTFK7Ifk8YA==} + engines: {node: ^14.13.0 || >=16.0.0} + hasBin: true + dependencies: + chalk: 4.1.2 + date-fns: 2.30.0 + lodash: 4.17.21 + rxjs: 7.8.1 + shell-quote: 1.8.1 + spawn-command: 0.0.2 + supports-color: 8.1.1 + tree-kill: 1.2.2 + yargs: 17.7.2 + dev: true + /confusing-browser-globals@1.0.11: resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} @@ -5570,7 +5792,6 @@ packages: /copy-text-to-clipboard@3.1.0: resolution: {integrity: sha512-PFM6BnjLnOON/lB3ta/Jg7Ywsv+l9kQGD4TWDCSlRBGmqnnTM5MrDkhAFgw+8HZt0wW6Q2BBE4cmy9sq+s9Qng==} engines: {node: '>=12'} - dev: false /copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} @@ -5721,23 +5942,23 @@ packages: hyphenate-style-name: 1.0.4 dev: false - /css-loader@6.8.1(webpack@5.86.0): + /css-loader@6.8.1(webpack@5.88.2): resolution: {integrity: sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: - icss-utils: 5.1.0(postcss@8.4.21) - postcss: 8.4.21 - postcss-modules-extract-imports: 3.0.0(postcss@8.4.21) - postcss-modules-local-by-default: 4.0.3(postcss@8.4.21) - postcss-modules-scope: 3.0.0(postcss@8.4.21) - postcss-modules-values: 4.0.0(postcss@8.4.21) + icss-utils: 5.1.0(postcss@8.4.24) + postcss: 8.4.24 + postcss-modules-extract-imports: 3.0.0(postcss@8.4.24) + postcss-modules-local-by-default: 4.0.3(postcss@8.4.24) + postcss-modules-scope: 3.0.0(postcss@8.4.24) + postcss-modules-values: 4.0.0(postcss@8.4.24) postcss-value-parser: 4.2.0 semver: 7.5.1 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) - /css-minimizer-webpack-plugin@3.4.1(esbuild@0.17.7)(webpack@5.86.0): + /css-minimizer-webpack-plugin@3.4.1(esbuild@0.17.7)(webpack@5.88.2): resolution: {integrity: sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -5763,7 +5984,7 @@ packages: schema-utils: 4.1.0 serialize-javascript: 6.0.1 source-map: 0.6.1 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /css-prefers-color-scheme@6.0.3(postcss@8.4.21): resolution: {integrity: sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==} @@ -5944,7 +6165,6 @@ packages: engines: {node: '>=0.11'} dependencies: '@babel/runtime': 7.22.5 - dev: false /dayjs@1.11.8: resolution: {integrity: sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ==} @@ -6332,6 +6552,14 @@ packages: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 + dev: true + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} @@ -6348,6 +6576,11 @@ packages: engines: {node: '>=0.12'} dev: true + /envinfo@7.10.0: + resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} + engines: {node: '>=4'} + hasBin: true + /errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} hasBin: true @@ -6822,7 +7055,7 @@ packages: resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /eslint-webpack-plugin@3.2.0(eslint@8.42.0)(webpack@5.86.0): + /eslint-webpack-plugin@3.2.0(eslint@8.42.0)(webpack@5.88.2): resolution: {integrity: sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -6835,7 +7068,7 @@ packages: micromatch: 4.0.5 normalize-path: 3.0.0 schema-utils: 4.1.0 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /eslint@7.32.0: resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} @@ -7148,6 +7381,10 @@ packages: resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} dev: false + /fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + /fastest-stable-stringify@2.0.2: resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} dev: false @@ -7189,7 +7426,7 @@ packages: dependencies: flat-cache: 3.0.4 - /file-loader@6.2.0(webpack@5.86.0): + /file-loader@6.2.0(webpack@5.88.2): resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -7197,7 +7434,7 @@ packages: dependencies: loader-utils: 2.0.4 schema-utils: 3.2.0 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} @@ -7245,6 +7482,14 @@ packages: make-dir: 3.1.0 pkg-dir: 4.2.0 + /find-cache-dir@4.0.0: + resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} + engines: {node: '>=14.16'} + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + dev: true + /find-up@3.0.0: resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} engines: {node: '>=6'} @@ -7265,6 +7510,14 @@ packages: locate-path: 6.0.0 path-exists: 4.0.0 + /find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + dev: true + /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -7289,7 +7542,7 @@ packages: dependencies: is-callable: 1.2.7 - /fork-ts-checker-webpack-plugin@6.5.3(eslint@8.42.0)(typescript@4.9.5)(webpack@5.86.0): + /fork-ts-checker-webpack-plugin@6.5.3(eslint@8.42.0)(typescript@4.9.5)(webpack@5.88.2): resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} engines: {node: '>=10', yarn: '>=1.0.0'} peerDependencies: @@ -7318,7 +7571,7 @@ packages: semver: 7.5.1 tapable: 1.1.3 typescript: 4.9.5 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /form-data@3.0.1: resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} @@ -7395,7 +7648,7 @@ packages: engines: {node: '>=10'} dependencies: at-least-node: 1.0.0 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.0 @@ -7517,6 +7770,17 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + /global-dirs@0.1.1: resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} engines: {node: '>=4'} @@ -7584,9 +7848,6 @@ packages: dependencies: get-intrinsic: 1.2.1 - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -7802,7 +8063,7 @@ packages: void-elements: 3.1.0 dev: false - /html-webpack-plugin@5.5.3(webpack@5.86.0): + /html-webpack-plugin@5.5.3(webpack@5.88.2): resolution: {integrity: sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==} engines: {node: '>=10.13.0'} peerDependencies: @@ -7813,7 +8074,7 @@ packages: lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.2.1 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /htmlparser2@6.1.0: resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} @@ -7954,6 +8215,15 @@ packages: postcss: ^8.1.0 dependencies: postcss: 8.4.21 + dev: true + + /icss-utils@5.1.0(postcss@8.4.24): + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.24 /idb@7.1.1: resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} @@ -8060,6 +8330,10 @@ packages: has: 1.0.3 side-channel: 1.0.4 + /interpret@3.1.1: + resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} + engines: {node: '>=10.13.0'} + /intersection-observer@0.12.2: resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} dev: false @@ -8107,6 +8381,13 @@ packages: call-bind: 1.0.2 has-tostringtag: 1.0.0 + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -8207,6 +8488,12 @@ packages: resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} engines: {node: '>=10'} + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + /is-plain-object@3.0.1: resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} engines: {node: '>=0.10.0'} @@ -8215,6 +8502,12 @@ packages: /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + /is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + dependencies: + '@types/estree': 1.0.1 + dev: true + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -8316,6 +8609,14 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /ismobilejs@1.1.1: + resolution: {integrity: sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==} + dev: false + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + /isomorphic-fetch@3.0.0: resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} dependencies: @@ -9548,6 +9849,17 @@ packages: picocolors: 1.0.0 shell-quote: 1.8.1 + /less-loader@11.1.3(less@4.1.3)(webpack@5.88.2): + resolution: {integrity: sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + less: ^3.5.0 || ^4.0.0 + webpack: ^5.0.0 + dependencies: + less: 4.1.3 + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + dev: true + /less@4.1.3: resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} engines: {node: '>=6'} @@ -9675,6 +9987,13 @@ packages: dependencies: p-locate: 5.0.0 + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + /lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: true @@ -9778,6 +10097,13 @@ packages: dependencies: sourcemap-codec: 1.4.8 + /magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + /make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -9915,14 +10241,14 @@ packages: engines: {node: '>=4'} dev: true - /mini-css-extract-plugin@2.7.6(webpack@5.86.0): + /mini-css-extract-plugin@2.7.6(webpack@5.88.2): resolution: {integrity: sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: schema-utils: 4.1.0 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} @@ -10008,7 +10334,6 @@ packages: /mutation-observer@1.0.3: resolution: {integrity: sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==} - dev: false /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -10337,6 +10662,13 @@ packages: dependencies: yocto-queue: 0.1.0 + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + /p-locate@3.0.0: resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} engines: {node: '>=6'} @@ -10355,6 +10687,13 @@ packages: dependencies: p-limit: 3.1.0 + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + /p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} @@ -10461,6 +10800,11 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -10535,6 +10879,13 @@ packages: dependencies: find-up: 4.1.0 + /pkg-dir@7.0.0: + resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} + engines: {node: '>=14.16'} + dependencies: + find-up: 6.3.0 + dev: true + /pkg-up@3.1.0: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} @@ -10835,7 +11186,7 @@ packages: ts-node: 10.9.1(@types/node@20.3.0)(typescript@4.9.4) yaml: 2.3.1 - /postcss-loader@6.2.1(postcss@8.4.21)(webpack@5.86.0): + /postcss-loader@6.2.1(postcss@8.4.21)(webpack@5.88.2): resolution: {integrity: sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -10846,7 +11197,7 @@ packages: klona: 2.0.6 postcss: 8.4.21 semver: 7.5.1 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /postcss-logical@5.0.4(postcss@8.4.21): resolution: {integrity: sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==} @@ -10933,6 +11284,15 @@ packages: postcss: ^8.1.0 dependencies: postcss: 8.4.21 + dev: true + + /postcss-modules-extract-imports@3.0.0(postcss@8.4.24): + resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.24 /postcss-modules-local-by-default@4.0.3(postcss@8.4.21): resolution: {integrity: sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==} @@ -10944,6 +11304,18 @@ packages: postcss: 8.4.21 postcss-selector-parser: 6.0.13 postcss-value-parser: 4.2.0 + dev: true + + /postcss-modules-local-by-default@4.0.3(postcss@8.4.24): + resolution: {integrity: sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.24) + postcss: 8.4.24 + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 /postcss-modules-scope@3.0.0(postcss@8.4.21): resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} @@ -10953,6 +11325,16 @@ packages: dependencies: postcss: 8.4.21 postcss-selector-parser: 6.0.13 + dev: true + + /postcss-modules-scope@3.0.0(postcss@8.4.24): + resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.24 + postcss-selector-parser: 6.0.13 /postcss-modules-values@4.0.0(postcss@8.4.21): resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} @@ -10962,6 +11344,16 @@ packages: dependencies: icss-utils: 5.1.0(postcss@8.4.21) postcss: 8.4.21 + dev: true + + /postcss-modules-values@4.0.0(postcss@8.4.24): + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.24) + postcss: 8.4.24 /postcss-modules@4.3.1(postcss@8.4.21): resolution: {integrity: sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==} @@ -12024,7 +12416,7 @@ packages: regenerator-runtime: 0.13.11 whatwg-fetch: 3.6.2 - /react-dev-utils@12.0.1(eslint@8.42.0)(typescript@4.9.5)(webpack@5.86.0): + /react-dev-utils@12.0.1(eslint@8.42.0)(typescript@4.9.5)(webpack@5.88.2): resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} engines: {node: '>=14'} peerDependencies: @@ -12043,7 +12435,7 @@ packages: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.42.0)(typescript@4.9.5)(webpack@5.86.0) + fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.42.0)(typescript@4.9.5)(webpack@5.88.2) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -12059,7 +12451,7 @@ packages: strip-ansi: 6.0.1 text-table: 0.2.0 typescript: 4.9.5 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) transitivePeerDependencies: - eslint - supports-color @@ -12073,7 +12465,6 @@ packages: loose-envify: 1.4.0 react: 18.2.0 scheduler: 0.21.0 - dev: false /react-error-overlay@6.0.11: resolution: {integrity: sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==} @@ -12123,7 +12514,7 @@ packages: resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} engines: {node: '>=0.10.0'} - /react-scripts@5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(esbuild@0.17.7)(eslint@8.42.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5): + /react-scripts@5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(esbuild@0.17.7)(eslint@8.42.0)(react@18.2.0)(ts-node@10.9.1)(typescript@4.9.5)(webpack-cli@5.1.4): resolution: {integrity: sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -12136,54 +12527,54 @@ packages: optional: true dependencies: '@babel/core': 7.20.12 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(react-refresh@0.11.0)(webpack-dev-server@4.15.1)(webpack@5.86.0) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(react-refresh@0.11.0)(webpack-dev-server@4.15.1)(webpack@5.88.2) '@svgr/webpack': 5.5.0 babel-jest: 27.5.1(@babel/core@7.20.12) - babel-loader: 8.3.0(@babel/core@7.20.12)(webpack@5.86.0) + babel-loader: 8.3.0(@babel/core@7.20.12)(webpack@5.88.2) babel-plugin-named-asset-import: 0.3.8(@babel/core@7.20.12) babel-preset-react-app: 10.0.1 bfj: 7.0.2 browserslist: 4.21.7 camelcase: 6.3.0 case-sensitive-paths-webpack-plugin: 2.4.0 - css-loader: 6.8.1(webpack@5.86.0) - css-minimizer-webpack-plugin: 3.4.1(esbuild@0.17.7)(webpack@5.86.0) + css-loader: 6.8.1(webpack@5.88.2) + css-minimizer-webpack-plugin: 3.4.1(esbuild@0.17.7)(webpack@5.88.2) dotenv: 10.0.0 dotenv-expand: 5.1.0 eslint: 8.42.0 eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(eslint@8.42.0)(jest@27.5.1)(typescript@4.9.5) - eslint-webpack-plugin: 3.2.0(eslint@8.42.0)(webpack@5.86.0) - file-loader: 6.2.0(webpack@5.86.0) + eslint-webpack-plugin: 3.2.0(eslint@8.42.0)(webpack@5.88.2) + file-loader: 6.2.0(webpack@5.88.2) fs-extra: 10.1.0 - html-webpack-plugin: 5.5.3(webpack@5.86.0) + html-webpack-plugin: 5.5.3(webpack@5.88.2) identity-obj-proxy: 3.0.0 jest: 27.5.1(ts-node@10.9.1) jest-resolve: 27.5.1 jest-watch-typeahead: 1.1.0(jest@27.5.1) - mini-css-extract-plugin: 2.7.6(webpack@5.86.0) + mini-css-extract-plugin: 2.7.6(webpack@5.88.2) postcss: 8.4.21 postcss-flexbugs-fixes: 5.0.2(postcss@8.4.21) - postcss-loader: 6.2.1(postcss@8.4.21)(webpack@5.86.0) + postcss-loader: 6.2.1(postcss@8.4.21)(webpack@5.88.2) postcss-normalize: 10.0.1(browserslist@4.21.7)(postcss@8.4.21) postcss-preset-env: 7.8.3(postcss@8.4.21) prompts: 2.4.2 react: 18.2.0 react-app-polyfill: 3.0.0 - react-dev-utils: 12.0.1(eslint@8.42.0)(typescript@4.9.5)(webpack@5.86.0) + react-dev-utils: 12.0.1(eslint@8.42.0)(typescript@4.9.5)(webpack@5.88.2) react-refresh: 0.11.0 resolve: 1.22.2 resolve-url-loader: 4.0.0 - sass-loader: 12.6.0(webpack@5.86.0) + sass-loader: 12.6.0(webpack@5.88.2) semver: 7.5.1 - source-map-loader: 3.0.2(webpack@5.86.0) - style-loader: 3.3.3(webpack@5.86.0) + source-map-loader: 3.0.2(webpack@5.88.2) + style-loader: 3.3.3(webpack@5.88.2) tailwindcss: 3.3.2(ts-node@10.9.1) - terser-webpack-plugin: 5.3.9(esbuild@0.17.7)(webpack@5.86.0) + terser-webpack-plugin: 5.3.9(esbuild@0.17.7)(webpack@5.88.2) typescript: 4.9.5 - webpack: 5.86.0(esbuild@0.17.7) - webpack-dev-server: 4.15.1(webpack@5.86.0) - webpack-manifest-plugin: 4.1.1(webpack@5.86.0) - workbox-webpack-plugin: 6.6.0(webpack@5.86.0) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.88.2) + webpack-manifest-plugin: 4.1.1(webpack@5.88.2) + workbox-webpack-plugin: 6.6.0(webpack@5.88.2) optionalDependencies: fsevents: 2.3.2 transitivePeerDependencies: @@ -12319,6 +12710,12 @@ packages: dependencies: picomatch: 2.3.1 + /rechoir@0.8.0: + resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} + engines: {node: '>= 10.13.0'} + dependencies: + resolve: 1.22.2 + /recursive-readdir@2.2.3: resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} engines: {node: '>=6.0.0'} @@ -12708,7 +13105,7 @@ packages: /sanitize.css@13.0.0: resolution: {integrity: sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==} - /sass-loader@12.6.0(webpack@5.86.0): + /sass-loader@12.6.0(webpack@5.88.2): resolution: {integrity: sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -12729,7 +13126,7 @@ packages: dependencies: klona: 2.0.6 neo-async: 2.6.2 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -12751,7 +13148,6 @@ packages: resolution: {integrity: sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==} dependencies: loose-envify: 1.4.0 - dev: false /schema-utils@2.7.0: resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} @@ -12923,6 +13319,12 @@ packages: safe-buffer: 5.2.1 dev: false + /shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + dependencies: + kind-of: 6.0.3 + /shallowequal@1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} dev: false @@ -13040,7 +13442,7 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - /source-map-loader@3.0.2(webpack@5.86.0): + /source-map-loader@3.0.2(webpack@5.88.2): resolution: {integrity: sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -13049,7 +13451,7 @@ packages: abab: 2.0.6 iconv-lite: 0.6.3 source-map-js: 1.0.2 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} @@ -13087,6 +13489,10 @@ packages: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead + /spawn-command@0.0.2: + resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} + dev: true + /spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} dependencies: @@ -13365,13 +13771,13 @@ packages: resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} dev: true - /style-loader@3.3.3(webpack@5.86.0): + /style-loader@3.3.3(webpack@5.88.2): resolution: {integrity: sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /stylehacks@5.1.1(postcss@8.4.21): resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} @@ -13565,7 +13971,7 @@ packages: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - /terser-webpack-plugin@5.3.9(esbuild@0.17.7)(webpack@5.86.0): + /terser-webpack-plugin@5.3.9(esbuild@0.17.7)(webpack@5.88.2): resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -13587,7 +13993,7 @@ packages: schema-utils: 3.2.0 serialize-javascript: 6.0.1 terser: 5.17.7 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) /terser@5.17.7: resolution: {integrity: sha512-/bi0Zm2C6VAexlGgLlVxA0P2lru/sdLyfCVaRMfKVo9nWxbmz7f/sD8VPybPeSUJaJcwmCJis9pBIhcVcG1QcQ==} @@ -13707,6 +14113,11 @@ packages: punycode: 2.3.0 dev: true + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} @@ -13765,7 +14176,22 @@ packages: yargs-parser: 21.1.1 dev: true - /ts-loader@9.4.0(typescript@4.9.5)(webpack@5.86.0): + /ts-loader@9.4.0(typescript@4.9.4)(webpack@5.88.2): + resolution: {integrity: sha512-0G3UMhk1bjgsgiwF4rnZRAeTi69j9XMDtmDDMghGSqlWESIAS3LFgJe//GYfE4vcjbyzuURLB9Us2RZIWp2clQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + typescript: '*' + webpack: ^5.0.0 + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.14.1 + micromatch: 4.0.5 + semver: 7.5.1 + typescript: 4.9.4 + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + dev: true + + /ts-loader@9.4.0(typescript@4.9.5)(webpack@5.88.2): resolution: {integrity: sha512-0G3UMhk1bjgsgiwF4rnZRAeTi69j9XMDtmDDMghGSqlWESIAS3LFgJe//GYfE4vcjbyzuURLB9Us2RZIWp2clQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -13777,7 +14203,7 @@ packages: micromatch: 4.0.5 semver: 7.5.1 typescript: 4.9.5 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) dev: true /ts-node@10.9.1(@types/node@20.3.0)(typescript@4.9.4): @@ -14143,7 +14569,6 @@ packages: copy-text-to-clipboard: 3.1.0 core-js: 3.31.0 mutation-observer: 1.0.3 - dev: false /void-elements@3.1.0: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} @@ -14229,7 +14654,39 @@ packages: - utf-8-validate dev: true - /webpack-dev-middleware@5.3.3(webpack@5.86.0): + /webpack-cli@5.1.4(webpack@5.88.2): + resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==} + engines: {node: '>=14.15.0'} + hasBin: true + peerDependencies: + '@webpack-cli/generators': '*' + webpack: 5.x.x + webpack-bundle-analyzer: '*' + webpack-dev-server: '*' + peerDependenciesMeta: + '@webpack-cli/generators': + optional: true + webpack-bundle-analyzer: + optional: true + webpack-dev-server: + optional: true + dependencies: + '@discoveryjs/json-ext': 0.5.7 + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.88.2) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.88.2) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.88.2) + colorette: 2.0.20 + commander: 10.0.1 + cross-spawn: 7.0.3 + envinfo: 7.10.0 + fastest-levenshtein: 1.0.16 + import-local: 3.1.0 + interpret: 3.1.1 + rechoir: 0.8.0 + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-merge: 5.9.0 + + /webpack-dev-middleware@5.3.3(webpack@5.88.2): resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -14240,9 +14697,9 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.1.0 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) - /webpack-dev-server@4.15.1(webpack@5.86.0): + /webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.88.2): resolution: {integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==} engines: {node: '>= 12.13.0'} hasBin: true @@ -14283,8 +14740,9 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.86.0(esbuild@0.17.7) - webpack-dev-middleware: 5.3.3(webpack@5.86.0) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.88.2) + webpack-dev-middleware: 5.3.3(webpack@5.88.2) ws: 8.13.0 transitivePeerDependencies: - bufferutil @@ -14292,14 +14750,14 @@ packages: - supports-color - utf-8-validate - /webpack-manifest-plugin@4.1.1(webpack@5.86.0): + /webpack-manifest-plugin@4.1.1(webpack@5.88.2): resolution: {integrity: sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==} engines: {node: '>=12.22.0'} peerDependencies: webpack: ^4.44.2 || ^5.47.0 dependencies: tapable: 2.2.1 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) webpack-sources: 2.3.1 /webpack-merge@4.2.2: @@ -14308,6 +14766,13 @@ packages: lodash: 4.17.21 dev: true + /webpack-merge@5.9.0: + resolution: {integrity: sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==} + engines: {node: '>=10.0.0'} + dependencies: + clone-deep: 4.0.1 + wildcard: 2.0.1 + /webpack-sources@1.4.3: resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} dependencies: @@ -14325,8 +14790,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - /webpack@5.86.0(esbuild@0.17.7): - resolution: {integrity: sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==} + /webpack@5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4): + resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -14344,7 +14809,7 @@ packages: acorn-import-assertions: 1.9.0(acorn@8.8.2) browserslist: 4.21.7 chrome-trace-event: 1.0.3 - enhanced-resolve: 5.14.1 + enhanced-resolve: 5.15.0 es-module-lexer: 1.3.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -14356,8 +14821,9 @@ packages: neo-async: 2.6.2 schema-utils: 3.2.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9(esbuild@0.17.7)(webpack@5.86.0) + terser-webpack-plugin: 5.3.9(esbuild@0.17.7)(webpack@5.88.2) watchpack: 2.4.0 + webpack-cli: 5.1.4(webpack@5.88.2) webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -14469,6 +14935,9 @@ packages: dependencies: isexe: 2.0.0 + /wildcard@2.0.1: + resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} + /word-wrap@1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} @@ -14598,7 +15067,7 @@ packages: /workbox-sw@6.6.0: resolution: {integrity: sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==} - /workbox-webpack-plugin@6.6.0(webpack@5.86.0): + /workbox-webpack-plugin@6.6.0(webpack@5.88.2): resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==} engines: {node: '>=10.0.0'} peerDependencies: @@ -14607,7 +15076,7 @@ packages: fast-json-stable-stringify: 2.1.0 pretty-bytes: 5.6.0 upath: 1.2.0 - webpack: 5.86.0(esbuild@0.17.7) + webpack: 5.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) webpack-sources: 1.4.3 workbox-build: 6.6.0 transitivePeerDependencies: @@ -14784,6 +15253,11 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + /zen-observable-ts@1.2.5: resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} dependencies: