From 28c89c842534914cc139ed50d39d6004cf17cd8b Mon Sep 17 00:00:00 2001 From: holymingo Date: Fri, 11 Aug 2023 19:30:05 +0800 Subject: [PATCH 01/20] feat: setup 2.0 --- packages/aelf-web-login/.eslintrc.json | 49 ++++ packages/aelf-web-login/.prettierrc | 21 ++ packages/aelf-web-login/global.d.ts | 2 + packages/aelf-web-login/index.less | 234 ++++++++++++++++++ packages/aelf-web-login/package.json | 69 ++++++ packages/aelf-web-login/rollup.config.js | 3 + packages/aelf-web-login/src/index.ts | 1 + packages/aelf-web-login/src/types.ts | 26 ++ .../src/wallets/discover/index.ts | 0 .../src/wallets/nightElf/index.ts | 28 +++ .../src/wallets/portkey/PortkeySDK.ts | 25 ++ .../src/wallets/portkey/index.ts | 3 + .../src/wallets/portkey/processor.ts | 32 +++ .../src/wallets/portkey/react/PortkeyUISDK.ts | 41 +++ .../src/wallets/portkey/react/context.tsx | 77 ++++++ .../react/processors/DefaultLoginProcessor.ts | 10 + .../react/processors/GoogleLoginProcessor.ts | 10 + packages/aelf-web-login/tsconfig.cjs.json | 7 + packages/aelf-web-login/tsconfig.esm.json | 7 + packages/aelf-web-login/tsconfig.json | 27 ++ packages/aelf-web-login/tsconfig.types.json | 7 + packages/example/src/App.tsx | 66 +---- .../example/src/components/CallContract.tsx | 138 ----------- packages/example/src/components/Events.tsx | 27 -- .../example/src/components/MultiWallets.tsx | 25 -- packages/example/src/components/Signature.tsx | 29 --- packages/example/src/index.tsx | 69 +----- packages/login/package.json | 2 +- pnpm-lock.yaml | 59 ++++- 29 files changed, 742 insertions(+), 352 deletions(-) create mode 100644 packages/aelf-web-login/.eslintrc.json create mode 100644 packages/aelf-web-login/.prettierrc create mode 100644 packages/aelf-web-login/global.d.ts create mode 100644 packages/aelf-web-login/index.less create mode 100644 packages/aelf-web-login/package.json create mode 100644 packages/aelf-web-login/rollup.config.js create mode 100644 packages/aelf-web-login/src/index.ts create mode 100644 packages/aelf-web-login/src/types.ts create mode 100644 packages/aelf-web-login/src/wallets/discover/index.ts create mode 100644 packages/aelf-web-login/src/wallets/nightElf/index.ts create mode 100644 packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts create mode 100644 packages/aelf-web-login/src/wallets/portkey/index.ts create mode 100644 packages/aelf-web-login/src/wallets/portkey/processor.ts create mode 100644 packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts create mode 100644 packages/aelf-web-login/src/wallets/portkey/react/context.tsx create mode 100644 packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts create mode 100644 packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts create mode 100644 packages/aelf-web-login/tsconfig.cjs.json create mode 100644 packages/aelf-web-login/tsconfig.esm.json create mode 100644 packages/aelf-web-login/tsconfig.json create mode 100644 packages/aelf-web-login/tsconfig.types.json delete mode 100644 packages/example/src/components/CallContract.tsx delete mode 100644 packages/example/src/components/Events.tsx delete mode 100644 packages/example/src/components/MultiWallets.tsx delete mode 100644 packages/example/src/components/Signature.tsx diff --git a/packages/aelf-web-login/.eslintrc.json b/packages/aelf-web-login/.eslintrc.json new file mode 100644 index 00000000..e6ca75e2 --- /dev/null +++ b/packages/aelf-web-login/.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/aelf-web-login/.prettierrc b/packages/aelf-web-login/.prettierrc new file mode 100644 index 00000000..727dd3f3 --- /dev/null +++ b/packages/aelf-web-login/.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/aelf-web-login/global.d.ts b/packages/aelf-web-login/global.d.ts new file mode 100644 index 00000000..bd1fc2cc --- /dev/null +++ b/packages/aelf-web-login/global.d.ts @@ -0,0 +1,2 @@ +declare module 'aelf-sdk'; +declare module 'aelf-bridge'; diff --git a/packages/aelf-web-login/index.less b/packages/aelf-web-login/index.less new file mode 100644 index 00000000..ca3e3505 --- /dev/null +++ b/packages/aelf-web-login/index.less @@ -0,0 +1,234 @@ +.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/aelf-web-login/package.json b/packages/aelf-web-login/package.json new file mode 100644 index 00000000..a6302b75 --- /dev/null +++ b/packages/aelf-web-login/package.json @@ -0,0 +1,69 @@ +{ + "name": "aelf-web-login", + "version": "2.0.0-alpha.1", + "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", + "lint": "eslint . --ext .tsx,.ts", + "lint:md": "remark . -f -q", + "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 && npm run build:css", + "build:css": "lessc ./index.less dist/assets/index.css", + "release": "yarn version && yarn build", + "pub": "npm publish" + }, + "dependencies": { + "@portkey/contracts": "^1.2.2", + "@portkey/detect-provider": "1.0.1-alpha.0", + "@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", + "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/aelf-web-login/rollup.config.js b/packages/aelf-web-login/rollup.config.js new file mode 100644 index 00000000..e6a4c775 --- /dev/null +++ b/packages/aelf-web-login/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/aelf-web-login/src/index.ts b/packages/aelf-web-login/src/index.ts new file mode 100644 index 00000000..ba337293 --- /dev/null +++ b/packages/aelf-web-login/src/index.ts @@ -0,0 +1 @@ +export * from './wallets/portkey'; diff --git a/packages/aelf-web-login/src/types.ts b/packages/aelf-web-login/src/types.ts new file mode 100644 index 00000000..37dfbcde --- /dev/null +++ b/packages/aelf-web-login/src/types.ts @@ -0,0 +1,26 @@ +export type WalletType = 'Discover' | 'NightElf' | 'PortkeySDK'; + +export type WalletInfo = { + address: string; +}; + +export type PortkeySDKWalletInfo = WalletInfo & {}; + +export interface ILogin { + walletType: WalletType; + walletInfo: T; + login(): Promise; + logout(): Promise; + getWalletName(): Promise; + getSignature(signInfo: string): Promise; +} + +export type PortkeySDKLoginType = + | 'Google' + | 'Apple' + | 'Email' + | 'Phone' + | 'Scan' + | 'PortkeyApp' + | 'Default' + | 'AllInOne'; diff --git a/packages/aelf-web-login/src/wallets/discover/index.ts b/packages/aelf-web-login/src/wallets/discover/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/aelf-web-login/src/wallets/nightElf/index.ts b/packages/aelf-web-login/src/wallets/nightElf/index.ts new file mode 100644 index 00000000..75352877 --- /dev/null +++ b/packages/aelf-web-login/src/wallets/nightElf/index.ts @@ -0,0 +1,28 @@ +import { ILogin, WalletInfo, WalletType } from '../../types'; + +export type NightElfWalletInfo = WalletInfo & {}; + +/** + * implement login feature based on aelf-bridge + */ +export class NightElf implements ILogin { + walletInfo: NightElfWalletInfo; + walletType: WalletType = 'NightElf'; + + constructor() { + this.walletInfo = { address: '' }; + } + + login(): Promise { + 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/aelf-web-login/src/wallets/portkey/PortkeySDK.ts b/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts new file mode 100644 index 00000000..9d804b7f --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts @@ -0,0 +1,25 @@ +import { ILogin, WalletInfo, WalletType } from '../../types'; + +export type PortkeySDKWalletInfo = WalletInfo & {}; + +/** + * implement login feature based on aelf-bridge + */ +export abstract class PortkeySDK implements ILogin { + walletInfo: PortkeySDKWalletInfo; + walletType: WalletType = 'PortkeySDK'; + + constructor() { + this.walletInfo = { address: '' }; + } + + getWalletName(): Promise { + throw new Error('Method not implemented.'); + } + getSignature(signInfo: string): Promise { + throw new Error('Method not implemented.'); + } + + abstract login(): Promise; + abstract logout(): Promise; +} diff --git a/packages/aelf-web-login/src/wallets/portkey/index.ts b/packages/aelf-web-login/src/wallets/portkey/index.ts new file mode 100644 index 00000000..93b7ca7a --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/index.ts @@ -0,0 +1,3 @@ +export * from './react/processors/GoogleLoginProcessor'; +export * from './react/context'; +export * from './PortkeySDK'; diff --git a/packages/aelf-web-login/src/wallets/portkey/processor.ts b/packages/aelf-web-login/src/wallets/portkey/processor.ts new file mode 100644 index 00000000..5d6389e6 --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/processor.ts @@ -0,0 +1,32 @@ +import { DIDWalletInfo } from '@portkey/did-ui-react'; +import { PortkeySDKLoginType } from '../../types'; + +export class PortkeySDKLoginResult { + code: number; + message: string; + walletInfo?: DIDWalletInfo | undefined; + + constructor(code: number, message: string, walletInfo?: DIDWalletInfo | undefined) { + this.code = code; + this.message = message; + this.walletInfo = walletInfo; + } +} + +export abstract class PortkeySDKLoginProcessorBase { + abstract type: PortkeySDKLoginType; + + login(): Promise { + return new Promise((resolve, reject) => { + this._processLogin((result) => { + if (result.code === 0) { + resolve(result.walletInfo!); + } else { + reject(result); + } + }); + }); + } + + protected abstract _processLogin(complete: (result: PortkeySDKLoginResult) => void): void; +} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts b/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts new file mode 100644 index 00000000..3c033e92 --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts @@ -0,0 +1,41 @@ +import { DIDWalletInfo, Theme } from '@portkey/did-ui-react'; +import { ChainType, NetworkType } from '@portkey/provider-types'; +import { PortkeySDKLoginType } from '../../../types'; +import { PortkeySDK } from '../PortkeySDK'; + +export type PortkeyState = { + theme?: Theme; + sandboxId?: string; + networkType: NetworkType; + chainType: ChainType; +}; + +export class PortkeyUISDK extends PortkeySDK { + readonly portkeyState: PortkeyState; + + constructor(portkeyState: PortkeyState) { + super(); + this.portkeyState = portkeyState; + } + + login(): Promise; + login(type: PortkeySDKLoginType): Promise; + login(type: PortkeySDKLoginType = 'Default'): Promise { + throw new Error('Method not implemented.'); + } + logout(): Promise { + throw new Error('Method not implemented.'); + } + + onFinish(didWalletInfo: DIDWalletInfo) { + throw new Error('Method not implemented.'); + } + + onError(error: any) { + throw new Error('Method not implemented.'); + } + + onCancel() { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/context.tsx b/packages/aelf-web-login/src/wallets/portkey/react/context.tsx new file mode 100644 index 00000000..41aec89b --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/react/context.tsx @@ -0,0 +1,77 @@ +import React, { createContext, useContext, useMemo } from 'react'; +import { PortkeyProvider, SignIn } from '@portkey/did-ui-react'; +import { PortkeyState, PortkeyUISDK } from './PortkeyUISDK'; + +export type PortkeySDKProviderProps = PortkeyState & { + customPortkeySDK?: PortkeyUISDK | (() => PortkeyUISDK); + customPortkeyUI?: boolean; + children: React.ReactNode | ((portkeySDK: PortkeyUISDK) => React.ReactNode); +}; + +type PortkeySDKContextType = PortkeyState & { + portkeySDK: PortkeyUISDK; +}; + +const PortkeySDKContext = createContext({} as PortkeySDKContextType); + +export function usePortkeyUISDK() { + return useContext(PortkeySDKContext).portkeySDK; +} + +export function PortkeySDKProvider({ + customPortkeySDK, + customPortkeyUI, + children, + chainType, + networkType, + theme, + sandboxId, +}: PortkeySDKProviderProps) { + const portkeySDK = useMemo( + () => { + if (customPortkeySDK) { + if (typeof customPortkeySDK === 'function') { + return customPortkeySDK(); + } + return customPortkeySDK; + } + const sdk = new PortkeyUISDK({ + chainType, + networkType, + theme, + sandboxId, + }); + return sdk; + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ); + + const value = useMemo( + () => ({ chainType, networkType, theme, sandboxId, portkeySDK }), + [chainType, networkType, portkeySDK, sandboxId, theme], + ); + + const renderChildren = () => { + if (typeof children === 'function') { + return children(portkeySDK); + } + + if (customPortkeyUI) { + return children; + } + + return ( + <> + {children} + + + ); + }; + + return ( + + {renderChildren()}; + + ); +} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts b/packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts new file mode 100644 index 00000000..48c754c1 --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts @@ -0,0 +1,10 @@ +import { PortkeySDKLoginType } from '../../../../types'; +import { PortkeySDKLoginProcessorBase, PortkeySDKLoginResult } from '../../processor'; + +export class DefaultLoginProcessor extends PortkeySDKLoginProcessorBase { + type: PortkeySDKLoginType = 'Default'; + + protected _processLogin(complete: (result: PortkeySDKLoginResult) => void): void { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts b/packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts new file mode 100644 index 00000000..bcec605f --- /dev/null +++ b/packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts @@ -0,0 +1,10 @@ +import { PortkeySDKLoginType } from '../../../../types'; +import { PortkeySDKLoginProcessorBase, PortkeySDKLoginResult } from '../../processor'; + +export class GoogleLoginProcessor extends PortkeySDKLoginProcessorBase { + type: PortkeySDKLoginType = 'Google'; + + protected _processLogin(complete: (result: PortkeySDKLoginResult) => void): void { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/aelf-web-login/tsconfig.cjs.json b/packages/aelf-web-login/tsconfig.cjs.json new file mode 100644 index 00000000..a41760de --- /dev/null +++ b/packages/aelf-web-login/tsconfig.cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/cjs", + "declaration": false + } +} diff --git a/packages/aelf-web-login/tsconfig.esm.json b/packages/aelf-web-login/tsconfig.esm.json new file mode 100644 index 00000000..b75c80a8 --- /dev/null +++ b/packages/aelf-web-login/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/esm", + "declaration": false + } +} diff --git a/packages/aelf-web-login/tsconfig.json b/packages/aelf-web-login/tsconfig.json new file mode 100644 index 00000000..43528897 --- /dev/null +++ b/packages/aelf-web-login/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/aelf-web-login/tsconfig.types.json b/packages/aelf-web-login/tsconfig.types.json new file mode 100644 index 00000000..b1c3478e --- /dev/null +++ b/packages/aelf-web-login/tsconfig.types.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/types", + "declaration": true + } +} diff --git a/packages/example/src/App.tsx b/packages/example/src/App.tsx index d051cbad..7357b3f9 100644 --- a/packages/example/src/App.tsx +++ b/packages/example/src/App.tsx @@ -1,13 +1,7 @@ -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 isMobile from './utils/isMobile'; -import Signature from './components/Signature'; -import Events from './components/Events'; const win = window as any; let showVConsole = () => {}; @@ -19,63 +13,5 @@ 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); - - 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: , - }, - ]} - /> -
- ); + return
; } 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/index.tsx b/packages/example/src/index.tsx index d7572401..91ca58ff 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -1,77 +1,22 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { createRoot } from 'react-dom/client'; import 'antd/dist/antd.css'; import '@portkey/did-ui-react/dist/assets/index.css'; import 'aelf-web-login/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!); -}); +import { Button } from 'antd'; +import { GoogleLoginProcessor, PortkeySDK, PortkeySDKProvider } from 'aelf-web-login'; function Index() { 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(); - }, - }}> - - - + + + ); } + const container = document.getElementById('root'); const root = createRoot(container!); root.render( diff --git a/packages/login/package.json b/packages/login/package.json index e4416257..6616cf42 100644 --- a/packages/login/package.json +++ b/packages/login/package.json @@ -1,5 +1,5 @@ { - "name": "aelf-web-login", + "name": "aelf-web-login-legacy", "version": "1.0.11-alpha", "main": "dist/esm/index.js", "types": "dist/types/index.d.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49d2a005..8028634a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -138,6 +138,58 @@ importers: specifier: ^4.9.4 version: 4.9.4 + packages/aelf-web-login: + 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-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) + 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: '@portkey/did-ui-react': @@ -151,7 +203,7 @@ importers: version: 18.0.0 aelf-web-login: specifier: workspace:* - version: link:../login + version: link:../aelf-web-login ahooks: specifier: ^3.7.7 version: 3.7.7(react@18.2.0) @@ -7395,7 +7447,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 @@ -7584,9 +7636,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==} From cd5db19237e4aa63d37d5c1b1e88796f166888a9 Mon Sep 17 00:00:00 2001 From: holymingo Date: Mon, 14 Aug 2023 17:16:34 +0800 Subject: [PATCH 02/20] feat: portkey wallet --- packages/aelf-web-login/src/types.ts | 9 +- .../src/wallets/discover/index.ts | 29 +++++ .../src/wallets/nightElf/index.ts | 3 +- .../src/wallets/portkey/PortkeySDK.ts | 5 +- .../src/wallets/portkey/react/PortkeyUISDK.ts | 60 +++++++-- .../src/wallets/portkey/react/context.tsx | 28 +++-- packages/example/src/App.tsx | 14 ++- packages/example/src/config.ts | 114 +++++++++--------- packages/example/src/index.tsx | 5 +- 9 files changed, 182 insertions(+), 85 deletions(-) diff --git a/packages/aelf-web-login/src/types.ts b/packages/aelf-web-login/src/types.ts index 37dfbcde..93a955d5 100644 --- a/packages/aelf-web-login/src/types.ts +++ b/packages/aelf-web-login/src/types.ts @@ -1,14 +1,21 @@ +import type { DIDWalletInfo } from '@portkey/did-ui-react'; + +export type LoginState = 'initial' | 'logining' | 'logined' | 'logouting'; + export type WalletType = 'Discover' | 'NightElf' | 'PortkeySDK'; export type WalletInfo = { address: string; }; -export type PortkeySDKWalletInfo = WalletInfo & {}; +export type PortkeySDKWalletInfo = WalletInfo & { + didWalletInfo?: DIDWalletInfo | undefined; +}; export interface ILogin { walletType: WalletType; walletInfo: T; + loginState: LoginState; login(): Promise; logout(): Promise; getWalletName(): Promise; diff --git a/packages/aelf-web-login/src/wallets/discover/index.ts b/packages/aelf-web-login/src/wallets/discover/index.ts index e69de29b..92af365c 100644 --- a/packages/aelf-web-login/src/wallets/discover/index.ts +++ b/packages/aelf-web-login/src/wallets/discover/index.ts @@ -0,0 +1,29 @@ +import { ILogin, LoginState, WalletInfo, WalletType } from '../../types'; + +export type DiscoverWalletInfo = WalletInfo & {}; + +/** + * implement login feature based on aelf-bridge + */ +export class Discover implements ILogin { + walletInfo: DiscoverWalletInfo; + walletType: WalletType = 'Discover'; + loginState: LoginState = 'initial'; + + constructor() { + this.walletInfo = { address: '' }; + } + + login(): Promise { + 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/aelf-web-login/src/wallets/nightElf/index.ts b/packages/aelf-web-login/src/wallets/nightElf/index.ts index 75352877..efd97613 100644 --- a/packages/aelf-web-login/src/wallets/nightElf/index.ts +++ b/packages/aelf-web-login/src/wallets/nightElf/index.ts @@ -1,4 +1,4 @@ -import { ILogin, WalletInfo, WalletType } from '../../types'; +import { ILogin, LoginState, WalletInfo, WalletType } from '../../types'; export type NightElfWalletInfo = WalletInfo & {}; @@ -8,6 +8,7 @@ export type NightElfWalletInfo = WalletInfo & {}; export class NightElf implements ILogin { walletInfo: NightElfWalletInfo; walletType: WalletType = 'NightElf'; + loginState: LoginState = 'initial'; constructor() { this.walletInfo = { address: '' }; diff --git a/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts b/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts index 9d804b7f..a3db8802 100644 --- a/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts +++ b/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts @@ -1,6 +1,4 @@ -import { ILogin, WalletInfo, WalletType } from '../../types'; - -export type PortkeySDKWalletInfo = WalletInfo & {}; +import { ILogin, LoginState, PortkeySDKWalletInfo, WalletType } from '../../types'; /** * implement login feature based on aelf-bridge @@ -8,6 +6,7 @@ export type PortkeySDKWalletInfo = WalletInfo & {}; export abstract class PortkeySDK implements ILogin { walletInfo: PortkeySDKWalletInfo; walletType: WalletType = 'PortkeySDK'; + loginState: LoginState = 'initial'; constructor() { this.walletInfo = { address: '' }; diff --git a/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts b/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts index 3c033e92..1b8a415a 100644 --- a/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts +++ b/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts @@ -1,7 +1,8 @@ -import { DIDWalletInfo, Theme } from '@portkey/did-ui-react'; +import { DIDWalletInfo, Theme, SignInInterface } from '@portkey/did-ui-react'; import { ChainType, NetworkType } from '@portkey/provider-types'; import { PortkeySDKLoginType } from '../../../types'; import { PortkeySDK } from '../PortkeySDK'; +import { RefObject } from 'react'; export type PortkeyState = { theme?: Theme; @@ -10,32 +11,73 @@ export type PortkeyState = { chainType: ChainType; }; +export type PromiseHolder = + | { + resolve: () => void; + reject: (error: any) => void; + } + | undefined; + export class PortkeyUISDK extends PortkeySDK { readonly portkeyState: PortkeyState; + readonly signInfRef: RefObject; + + private _promiseHolder: PromiseHolder; - constructor(portkeyState: PortkeyState) { + constructor(portkeyState: PortkeyState, signInfRef: RefObject) { super(); this.portkeyState = portkeyState; + this.signInfRef = signInfRef; } - login(): Promise; - login(type: PortkeySDKLoginType): Promise; - login(type: PortkeySDKLoginType = 'Default'): Promise { - throw new Error('Method not implemented.'); + login(): Promise { + 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 new Promise((resolve, reject) => { + this._promiseHolder = { + resolve, + reject, + }; + }); } + logout(): Promise { throw new Error('Method not implemented.'); } onFinish(didWalletInfo: DIDWalletInfo) { - throw new Error('Method not implemented.'); + 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 || '', + didWalletInfo, + }; + this._promiseHolder?.resolve(); } onError(error: any) { - throw new Error('Method not implemented.'); + if (this.loginState !== 'logining') { + console.warn('onError called when loginState is not logining', this.loginState); + return; + } + this.loginState = 'initial'; + this._promiseHolder?.reject(error); } onCancel() { - throw new Error('Method not implemented.'); + if (this.loginState !== 'logining') { + console.warn('onCancel called when loginState is not logining', this.loginState); + return; + } + this.loginState = 'initial'; + this._promiseHolder?.reject('cancel'); } } diff --git a/packages/aelf-web-login/src/wallets/portkey/react/context.tsx b/packages/aelf-web-login/src/wallets/portkey/react/context.tsx index 41aec89b..417f260a 100644 --- a/packages/aelf-web-login/src/wallets/portkey/react/context.tsx +++ b/packages/aelf-web-login/src/wallets/portkey/react/context.tsx @@ -1,5 +1,5 @@ -import React, { createContext, useContext, useMemo } from 'react'; -import { PortkeyProvider, SignIn } from '@portkey/did-ui-react'; +import React, { createContext, useContext, useMemo, useRef } from 'react'; +import { PortkeyProvider, SignIn, SignInInterface } from '@portkey/did-ui-react'; import { PortkeyState, PortkeyUISDK } from './PortkeyUISDK'; export type PortkeySDKProviderProps = PortkeyState & { @@ -27,6 +27,7 @@ export function PortkeySDKProvider({ theme, sandboxId, }: PortkeySDKProviderProps) { + const signInRef = useRef(null); const portkeySDK = useMemo( () => { if (customPortkeySDK) { @@ -35,12 +36,15 @@ export function PortkeySDKProvider({ } return customPortkeySDK; } - const sdk = new PortkeyUISDK({ - chainType, - networkType, - theme, - sandboxId, - }); + const sdk = new PortkeyUISDK( + { + chainType, + networkType, + theme, + sandboxId, + }, + signInRef, + ); return sdk; }, // eslint-disable-next-line react-hooks/exhaustive-deps @@ -64,7 +68,13 @@ export function PortkeySDKProvider({ return ( <> {children} - + portkeySDK.onCancel()} + onError={(error) => portkeySDK.onError(error)} + onFinish={(didWalletInfo) => portkeySDK.onFinish(didWalletInfo)} + /> ); }; diff --git a/packages/example/src/App.tsx b/packages/example/src/App.tsx index 7357b3f9..ccce7b1e 100644 --- a/packages/example/src/App.tsx +++ b/packages/example/src/App.tsx @@ -1,7 +1,8 @@ import VConsole from 'vconsole'; import { useState } from 'react'; -import { Tabs } from 'antd'; +import { Button, Tabs } from 'antd'; import isMobile from './utils/isMobile'; +import { usePortkeyUISDK } from 'aelf-web-login'; const win = window as any; let showVConsole = () => {}; @@ -13,5 +14,14 @@ if (isMobile() || win.ReactNativeWebView) { } export default function App() { - return
; + const portkeySDK = usePortkeyUISDK(); + + return ( +
+
+ + +
+
+ ); } 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.tsx b/packages/example/src/index.tsx index 91ca58ff..0ca67af4 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -2,12 +2,11 @@ import React, { useEffect, useMemo } from 'react'; import { createRoot } from 'react-dom/client'; 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/dist/assets/index.css'; import './index.css'; import './config'; import App from './App'; -import { Button } from 'antd'; -import { GoogleLoginProcessor, PortkeySDK, PortkeySDKProvider } from 'aelf-web-login'; +import { PortkeySDKProvider } from 'aelf-web-login'; function Index() { return ( From c5199e3d2b456d454a950a6ce81543cd5d4274bc Mon Sep 17 00:00:00 2001 From: holymingo Date: Mon, 14 Aug 2023 18:30:55 +0800 Subject: [PATCH 03/20] feat: web module --- package.json | 8 ++- packages/web/package.json | 39 +++++++++++ packages/web/rollup.config.js | 88 +++++++++++++++++++++++ packages/web/src/index.ts | 10 +++ packages/web/src/setup.tsx | 24 +++++++ packages/web/tsconfig.json | 27 ++++++++ packages/web/tsconfig.types.json | 7 ++ packages/web/webpack.prod.config.js | 0 pnpm-lock.yaml | 104 ++++++++++++++++++++++++++-- 9 files changed, 298 insertions(+), 9 deletions(-) create mode 100644 packages/web/package.json create mode 100644 packages/web/rollup.config.js create mode 100644 packages/web/src/index.ts create mode 100644 packages/web/src/setup.tsx create mode 100644 packages/web/tsconfig.json create mode 100644 packages/web/tsconfig.types.json create mode 100644 packages/web/webpack.prod.config.js diff --git a/package.json b/package.json index 7c5580a0..423167d8 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "login:dev": "pnpm --filter aelf-web-login dev", "login:build": "pnpm --filter aelf-web-login build", "login:pub": "pnpm --filter aelf-web-login pub", + "web:dev": "pnpm --filter @aelf-web-login/web dev", + "web:build": "pnpm --filter @aelf-web-login/web build", "example": "pnpm --filter @aelf-web-login/example start", "test": "jest", "test:browser": "jest --config=jest.browser.config.ts", @@ -30,7 +32,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", @@ -69,7 +73,5 @@ "lint-staged": { "*.{js,jsx,ts,tsx}": "eslint --cache --fix" }, - "version": "0.0.0", - "dependencies": { - } + "version": "0.0.0" } diff --git a/packages/web/package.json b/packages/web/package.json new file mode 100644 index 00000000..1014b8be --- /dev/null +++ b/packages/web/package.json @@ -0,0 +1,39 @@ +{ + "private": true, + "name": "@aelf-web-login/web", + "version": "0.0.1-alpha.1.4", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": "./dist/index.js", + "./dist/index.css": "./dist/index.css" + }, + "type": "module", + "module": "./dist/index.js", + "scripts": { + "dev": "rollup --watch --config rollup.config.js", + "build": "rollup --silent --config rollup.config.js" + }, + "dependencies": { + }, + "devDependencies": { + "@types/react-dom": "^18.0.0", + "react": "^18.2.0", + "react-dom": "^18.0.0", + "aelf-web-login": "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..e84fc340 --- /dev/null +++ b/packages/web/src/index.ts @@ -0,0 +1,10 @@ +import setup from './setup'; + +export class SDK { + setup = setup; + login() { + console.log('login'); + } +} + +export default new SDK(); diff --git a/packages/web/src/setup.tsx b/packages/web/src/setup.tsx new file mode 100644 index 00000000..6ece5bc5 --- /dev/null +++ b/packages/web/src/setup.tsx @@ -0,0 +1,24 @@ +import React, { useEffect, useMemo } from 'react'; +import { createRoot } from 'react-dom/client'; +import 'antd/dist/antd.css'; +import '@portkey/did-ui-react/dist/assets/index.css'; +import { PortkeySDKProvider } from 'aelf-web-login'; + +function SDKRoot() { + return ( + + <> + + ); +} + +export default function setup() { + const container = document.createElement('div'); + container.id = 'aelf-web-login-root'; + const root = createRoot(container); + root.render( + + + , + ); +} 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.prod.config.js b/packages/web/webpack.prod.config.js new file mode 100644 index 00000000..e69de29b diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8028634a..d4d2a824 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) @@ -288,6 +294,27 @@ importers: specifier: ^4.1.3 version: 4.1.3 + packages/web: + devDependencies: + '@types/react-dom': + specifier: ^18.0.0 + version: 18.0.0 + aelf-web-login: + specifier: workspace:* + version: link:../aelf-web-login + 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: @@ -3233,6 +3260,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'} @@ -3261,6 +3306,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: @@ -3689,7 +3752,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==} @@ -3714,6 +3776,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==} @@ -5622,7 +5688,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==} @@ -7569,6 +7634,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'} @@ -8156,6 +8232,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'} @@ -8264,6 +8347,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'} @@ -9827,6 +9916,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'} @@ -10057,7 +10153,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==} @@ -12122,7 +12217,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==} @@ -12800,7 +12894,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==} @@ -14192,7 +14285,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==} From 451986b18cecdd077a4696e44bb7881f25f10f1f Mon Sep 17 00:00:00 2001 From: holymingo Date: Mon, 14 Aug 2023 18:55:44 +0800 Subject: [PATCH 04/20] feat: webpack config --- package.json | 5 +- packages/web/package.json | 6 +- packages/web/webpack.config.js | 38 ++++ packages/web/webpack.prod.config.js | 0 pnpm-lock.yaml | 299 +++++++++++++++++++++------- 5 files changed, 274 insertions(+), 74 deletions(-) create mode 100644 packages/web/webpack.config.js delete mode 100644 packages/web/webpack.prod.config.js diff --git a/package.json b/package.json index 423167d8..b8449b3a 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,11 @@ "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" diff --git a/packages/web/package.json b/packages/web/package.json index 1014b8be..831bd315 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -8,11 +8,9 @@ ".": "./dist/index.js", "./dist/index.css": "./dist/index.css" }, - "type": "module", - "module": "./dist/index.js", "scripts": { - "dev": "rollup --watch --config rollup.config.js", - "build": "rollup --silent --config rollup.config.js" + "dev": "webpack --watch --config webpack.config.js", + "build": "webpack --config webpack.config.js" }, "dependencies": { }, diff --git a/packages/web/webpack.config.js b/packages/web/webpack.config.js new file mode 100644 index 00000000..1b0aa8ff --- /dev/null +++ b/packages/web/webpack.config.js @@ -0,0 +1,38 @@ +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'], + }, + 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'], + }, + ], + }, + + plugins: [], +}); diff --git a/packages/web/webpack.prod.config.js b/packages/web/webpack.prod.config.js deleted file mode 100644 index e69de29b..00000000 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4d2a824..2e034c8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -137,12 +137,21 @@ 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/aelf-web-login: dependencies: @@ -224,7 +233,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 @@ -237,7 +246,7 @@ 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: dependencies: @@ -1925,7 +1934,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 @@ -2082,6 +2091,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'} @@ -2917,7 +2930,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: @@ -2953,8 +2966,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==} @@ -4245,6 +4258,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'} @@ -4872,7 +4919,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: @@ -4884,7 +4931,7 @@ 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-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} @@ -5470,6 +5517,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'} @@ -5523,6 +5578,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 @@ -5838,7 +5897,7 @@ 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: @@ -5852,9 +5911,9 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.21) 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: @@ -5880,7 +5939,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==} @@ -6449,6 +6508,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==} @@ -6465,6 +6532,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 @@ -6939,7 +7011,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: @@ -6952,7 +7024,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==} @@ -7265,6 +7337,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 @@ -7306,7 +7382,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: @@ -7314,7 +7390,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==} @@ -7406,7 +7482,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: @@ -7435,7 +7511,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==} @@ -7927,7 +8003,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: @@ -7938,7 +8014,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==} @@ -8185,6 +8261,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 @@ -8339,6 +8419,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'} @@ -8454,6 +8540,10 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /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: @@ -10060,14 +10150,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==} @@ -10979,7 +11069,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: @@ -10990,7 +11080,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==} @@ -12168,7 +12258,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: @@ -12187,7 +12277,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 @@ -12203,7 +12293,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 @@ -12266,7 +12356,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 @@ -12279,54 +12369,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: @@ -12462,6 +12552,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'} @@ -12851,7 +12947,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: @@ -12872,7 +12968,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==} @@ -13065,6 +13161,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 @@ -13182,7 +13284,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: @@ -13191,7 +13293,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==} @@ -13507,13 +13609,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==} @@ -13707,7 +13809,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: @@ -13729,7 +13831,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==} @@ -13907,7 +14009,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: @@ -13919,7 +14036,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): @@ -14370,7 +14487,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: @@ -14381,9 +14530,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 @@ -14424,8 +14573,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 @@ -14433,14 +14583,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: @@ -14449,6 +14599,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: @@ -14466,8 +14623,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: @@ -14485,7 +14642,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 @@ -14497,8 +14654,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' @@ -14610,6 +14768,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'} @@ -14739,7 +14900,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: @@ -14748,7 +14909,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: From 9e3c0841c6de63b6e85ddf60d698042359a46742 Mon Sep 17 00:00:00 2001 From: holymingo Date: Mon, 14 Aug 2023 19:46:26 +0800 Subject: [PATCH 05/20] feat: webpack pack library --- package.json | 3 + packages/web/src/setup.tsx | 2 - packages/web/webpack.config.js | 11 ++- pnpm-lock.yaml | 149 +++++++++++++++++++++++++++++++-- 4 files changed, 156 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index b8449b3a..4f8dc3e1 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,9 @@ "@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", + "css-loader": "^6.8.1", "esbuild": "^0.17.7", "eslint": "^7.32.0", "eslint-config-prettier": "^8.5.0", @@ -52,6 +54,7 @@ "istanbul-badges-readme": "^1.8.5", "jest": "^29.3.1", "jest-environment-jsdom": "^29.4.3", + "less-loader": "^11.1.3", "lint-staged": ">=13", "node-fetch": "^3.3.0", "postcss": "^8.4.21", diff --git a/packages/web/src/setup.tsx b/packages/web/src/setup.tsx index 6ece5bc5..51a9e7d3 100644 --- a/packages/web/src/setup.tsx +++ b/packages/web/src/setup.tsx @@ -1,7 +1,5 @@ import React, { useEffect, useMemo } from 'react'; import { createRoot } from 'react-dom/client'; -import 'antd/dist/antd.css'; -import '@portkey/did-ui-react/dist/assets/index.css'; import { PortkeySDKProvider } from 'aelf-web-login'; function SDKRoot() { diff --git a/packages/web/webpack.config.js b/packages/web/webpack.config.js index 1b0aa8ff..e779a901 100644 --- a/packages/web/webpack.config.js +++ b/packages/web/webpack.config.js @@ -13,7 +13,10 @@ module.exports = merge({ }, }, resolve: { - extensions: ['.ts', '.js'], + extensions: ['.ts', '.js', '.tsx', '.jsx', '...'], + alias: { + react: path.resolve('./node_modules/react'), + }, }, module: { rules: [ @@ -31,6 +34,12 @@ module.exports = merge({ test: /\.(css|less)$/, use: ['css-loader', 'less-loader'], }, + { + test: /\.m?js$/, + resolve: { + fullySpecified: false, + }, + } ], }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e034c8a..18588be8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,9 +62,15 @@ 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 + css-loader: + specifier: ^6.8.1 + version: 6.8.1(webpack@5.88.2) esbuild: specifier: ^0.17.7 version: 0.17.7 @@ -92,6 +98,9 @@ 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' version: 13.0.0 @@ -4933,6 +4942,19 @@ packages: schema-utils: 2.7.1 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==} engines: {node: '>=8'} @@ -5903,12 +5925,12 @@ packages: 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.88.2(esbuild@0.17.7)(webpack-cli@5.1.4) @@ -7438,6 +7460,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'} @@ -7458,6 +7488,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} @@ -8155,6 +8193,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==} @@ -9776,6 +9823,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'} @@ -9903,6 +9961,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 @@ -10571,6 +10636,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'} @@ -10589,6 +10661,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'} @@ -10695,6 +10774,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'} @@ -10769,6 +10853,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'} @@ -11167,6 +11258,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==} @@ -11178,6 +11278,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==} @@ -11187,6 +11299,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==} @@ -11196,6 +11318,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==} @@ -15086,6 +15218,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: From 730c035d515c99fb8abe38f9fc8dd30ac6928d60 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 15 Aug 2023 13:49:58 +0800 Subject: [PATCH 06/20] feat: refactor modules --- package.json | 7 +- packages/aelf-web-login/index.less | 234 ---------- packages/aelf-web-login/src/index.ts | 1 - .../src/wallets/portkey/index.ts | 3 - .../src/wallets/portkey/processor.ts | 32 -- .../react/processors/DefaultLoginProcessor.ts | 10 - .../react/processors/GoogleLoginProcessor.ts | 10 - .../{aelf-web-login => core}/.eslintrc.json | 0 packages/{aelf-web-login => core}/.prettierrc | 0 packages/{aelf-web-login => core}/global.d.ts | 0 packages/{login => core}/package.json | 8 +- .../{aelf-web-login => core}/rollup.config.js | 0 packages/{login => core}/src/errors.ts | 0 packages/core/src/index.ts | 5 + .../{aelf-web-login => core}/src/types.ts | 0 .../src/wallets/discover/index.ts | 0 .../src/wallets/nightElf/index.ts | 0 .../src/wallets/portkey/PortkeySDK.ts | 0 packages/core/src/wallets/portkey/index.ts | 1 + .../tsconfig.cjs.json | 0 .../tsconfig.esm.json | 0 .../{aelf-web-login => core}/tsconfig.json | 0 .../tsconfig.types.json | 0 packages/example/package.json | 3 +- packages/example/src/App.tsx | 2 +- packages/example/src/index.tsx | 11 +- packages/login/global.d.ts | 4 - packages/login/index.less | 234 ---------- .../ConfirmLogoutDialog.tsx | 85 ---- .../components/CofirmLogoutDialog/index.ts | 1 - packages/login/src/components/PluginEntry.tsx | 10 - packages/login/src/config.ts | 54 --- packages/login/src/constants.ts | 33 -- packages/login/src/context.tsx | 407 ------------------ .../login/src/hooks/internal/useEnvChecks.ts | 42 -- packages/login/src/hooks/useCallContract.ts | 179 -------- packages/login/src/hooks/useContract.ts | 5 - packages/login/src/hooks/useGetAccount.ts | 62 --- packages/login/src/hooks/useLoginState.ts | 15 - packages/login/src/hooks/useMultiWallets.ts | 121 ------ packages/login/src/hooks/usePortkeyLock.ts | 11 - .../login/src/hooks/usePortkeyPreparing.ts | 10 - packages/login/src/hooks/useWebLoginEvent.ts | 33 -- packages/login/src/index.ts | 39 -- packages/login/src/types.ts | 161 ------- .../login/src/utils/getContractBasicAsync.ts | 49 --- packages/login/src/utils/isMobile.ts | 24 -- packages/login/src/utils/isPortkeyApp.ts | 4 - packages/login/src/utils/pluginPages.ts | 11 - packages/login/src/utils/signatureParams.ts | 9 - packages/login/src/utils/waitForSeconds.ts | 5 - .../src/wallets/discover/DiscoverPlugin.tsx | 54 --- .../src/wallets/discover/detectProvider.ts | 10 - .../src/wallets/discover/openDiscoverPage.ts | 16 - .../src/wallets/discover/useChainIdsSync.ts | 47 -- .../login/src/wallets/discover/useDiscover.ts | 397 ----------------- .../login/src/wallets/elf/AelfBridgeCheck.ts | 40 -- .../login/src/wallets/elf/NightElfCheck.ts | 35 -- .../login/src/wallets/elf/NightElfPlugin.tsx | 46 -- .../login/src/wallets/elf/detectNightElf.ts | 5 - packages/login/src/wallets/elf/useElf.ts | 326 -------------- packages/login/src/wallets/elf/utils.ts | 50 --- .../login/src/wallets/portkey/Portkey.tsx | 90 ---- .../src/wallets/portkey/useAccountInfoSync.ts | 62 --- .../login/src/wallets/portkey/usePortkey.ts | 392 ----------------- packages/login/src/wallets/types.ts | 21 - packages/{login => react}/.eslintrc.json | 0 packages/{login => react}/.prettierrc | 0 packages/react/global.d.ts | 2 + packages/react/index.less | 11 + .../{aelf-web-login => react}/package.json | 5 +- packages/{login => react}/rollup.config.js | 0 packages/react/src/index.ts | 3 + packages/react/src/nightElf/context.tsx | 21 + packages/react/src/nightElf/withNightElf.tsx | 12 + packages/react/src/portkey/ExtraElement.tsx | 11 + .../src/portkey}/PortkeyUISDK.ts | 23 +- .../react => react/src/portkey}/context.tsx | 27 +- packages/react/src/types.ts | 18 + packages/{login => react}/tsconfig.cjs.json | 0 packages/{login => react}/tsconfig.esm.json | 0 packages/{login => react}/tsconfig.json | 0 packages/{login => react}/tsconfig.types.json | 0 packages/web/package.json | 5 +- pnpm-lock.yaml | 46 +- 85 files changed, 149 insertions(+), 3561 deletions(-) delete mode 100644 packages/aelf-web-login/index.less delete mode 100644 packages/aelf-web-login/src/index.ts delete mode 100644 packages/aelf-web-login/src/wallets/portkey/index.ts delete mode 100644 packages/aelf-web-login/src/wallets/portkey/processor.ts delete mode 100644 packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts delete mode 100644 packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts rename packages/{aelf-web-login => core}/.eslintrc.json (100%) rename packages/{aelf-web-login => core}/.prettierrc (100%) rename packages/{aelf-web-login => core}/global.d.ts (100%) rename packages/{login => core}/package.json (89%) rename packages/{aelf-web-login => core}/rollup.config.js (100%) rename packages/{login => core}/src/errors.ts (100%) create mode 100644 packages/core/src/index.ts rename packages/{aelf-web-login => core}/src/types.ts (100%) rename packages/{aelf-web-login => core}/src/wallets/discover/index.ts (100%) rename packages/{aelf-web-login => core}/src/wallets/nightElf/index.ts (100%) rename packages/{aelf-web-login => core}/src/wallets/portkey/PortkeySDK.ts (100%) create mode 100644 packages/core/src/wallets/portkey/index.ts rename packages/{aelf-web-login => core}/tsconfig.cjs.json (100%) rename packages/{aelf-web-login => core}/tsconfig.esm.json (100%) rename packages/{aelf-web-login => core}/tsconfig.json (100%) rename packages/{aelf-web-login => core}/tsconfig.types.json (100%) delete mode 100644 packages/login/global.d.ts delete mode 100644 packages/login/index.less delete mode 100644 packages/login/src/components/CofirmLogoutDialog/ConfirmLogoutDialog.tsx delete mode 100644 packages/login/src/components/CofirmLogoutDialog/index.ts delete mode 100644 packages/login/src/components/PluginEntry.tsx delete mode 100644 packages/login/src/config.ts delete mode 100644 packages/login/src/constants.ts delete mode 100644 packages/login/src/context.tsx delete mode 100644 packages/login/src/hooks/internal/useEnvChecks.ts delete mode 100644 packages/login/src/hooks/useCallContract.ts delete mode 100644 packages/login/src/hooks/useContract.ts delete mode 100644 packages/login/src/hooks/useGetAccount.ts delete mode 100644 packages/login/src/hooks/useLoginState.ts delete mode 100644 packages/login/src/hooks/useMultiWallets.ts delete mode 100644 packages/login/src/hooks/usePortkeyLock.ts delete mode 100644 packages/login/src/hooks/usePortkeyPreparing.ts delete mode 100644 packages/login/src/hooks/useWebLoginEvent.ts delete mode 100644 packages/login/src/index.ts delete mode 100644 packages/login/src/types.ts delete mode 100644 packages/login/src/utils/getContractBasicAsync.ts delete mode 100644 packages/login/src/utils/isMobile.ts delete mode 100644 packages/login/src/utils/isPortkeyApp.ts delete mode 100644 packages/login/src/utils/pluginPages.ts delete mode 100644 packages/login/src/utils/signatureParams.ts delete mode 100644 packages/login/src/utils/waitForSeconds.ts delete mode 100644 packages/login/src/wallets/discover/DiscoverPlugin.tsx delete mode 100644 packages/login/src/wallets/discover/detectProvider.ts delete mode 100644 packages/login/src/wallets/discover/openDiscoverPage.ts delete mode 100644 packages/login/src/wallets/discover/useChainIdsSync.ts delete mode 100644 packages/login/src/wallets/discover/useDiscover.ts delete mode 100644 packages/login/src/wallets/elf/AelfBridgeCheck.ts delete mode 100644 packages/login/src/wallets/elf/NightElfCheck.ts delete mode 100644 packages/login/src/wallets/elf/NightElfPlugin.tsx delete mode 100644 packages/login/src/wallets/elf/detectNightElf.ts delete mode 100644 packages/login/src/wallets/elf/useElf.ts delete mode 100644 packages/login/src/wallets/elf/utils.ts delete mode 100644 packages/login/src/wallets/portkey/Portkey.tsx delete mode 100644 packages/login/src/wallets/portkey/useAccountInfoSync.ts delete mode 100644 packages/login/src/wallets/portkey/usePortkey.ts delete mode 100644 packages/login/src/wallets/types.ts rename packages/{login => react}/.eslintrc.json (100%) rename packages/{login => react}/.prettierrc (100%) create mode 100644 packages/react/global.d.ts create mode 100644 packages/react/index.less rename packages/{aelf-web-login => react}/package.json (95%) rename packages/{login => react}/rollup.config.js (100%) create mode 100644 packages/react/src/index.ts create mode 100644 packages/react/src/nightElf/context.tsx create mode 100644 packages/react/src/nightElf/withNightElf.tsx create mode 100644 packages/react/src/portkey/ExtraElement.tsx rename packages/{aelf-web-login/src/wallets/portkey/react => react/src/portkey}/PortkeyUISDK.ts (76%) rename packages/{aelf-web-login/src/wallets/portkey/react => react/src/portkey}/context.tsx (75%) create mode 100644 packages/react/src/types.ts rename packages/{login => react}/tsconfig.cjs.json (100%) rename packages/{login => react}/tsconfig.esm.json (100%) rename packages/{login => react}/tsconfig.json (100%) rename packages/{login => react}/tsconfig.types.json (100%) diff --git a/package.json b/package.json index 4f8dc3e1..2011fd6c 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,10 @@ "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", + "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", "example": "pnpm --filter @aelf-web-login/example start", diff --git a/packages/aelf-web-login/index.less b/packages/aelf-web-login/index.less deleted file mode 100644 index ca3e3505..00000000 --- a/packages/aelf-web-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/aelf-web-login/src/index.ts b/packages/aelf-web-login/src/index.ts deleted file mode 100644 index ba337293..00000000 --- a/packages/aelf-web-login/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './wallets/portkey'; diff --git a/packages/aelf-web-login/src/wallets/portkey/index.ts b/packages/aelf-web-login/src/wallets/portkey/index.ts deleted file mode 100644 index 93b7ca7a..00000000 --- a/packages/aelf-web-login/src/wallets/portkey/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './react/processors/GoogleLoginProcessor'; -export * from './react/context'; -export * from './PortkeySDK'; diff --git a/packages/aelf-web-login/src/wallets/portkey/processor.ts b/packages/aelf-web-login/src/wallets/portkey/processor.ts deleted file mode 100644 index 5d6389e6..00000000 --- a/packages/aelf-web-login/src/wallets/portkey/processor.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { DIDWalletInfo } from '@portkey/did-ui-react'; -import { PortkeySDKLoginType } from '../../types'; - -export class PortkeySDKLoginResult { - code: number; - message: string; - walletInfo?: DIDWalletInfo | undefined; - - constructor(code: number, message: string, walletInfo?: DIDWalletInfo | undefined) { - this.code = code; - this.message = message; - this.walletInfo = walletInfo; - } -} - -export abstract class PortkeySDKLoginProcessorBase { - abstract type: PortkeySDKLoginType; - - login(): Promise { - return new Promise((resolve, reject) => { - this._processLogin((result) => { - if (result.code === 0) { - resolve(result.walletInfo!); - } else { - reject(result); - } - }); - }); - } - - protected abstract _processLogin(complete: (result: PortkeySDKLoginResult) => void): void; -} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts b/packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts deleted file mode 100644 index 48c754c1..00000000 --- a/packages/aelf-web-login/src/wallets/portkey/react/processors/DefaultLoginProcessor.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { PortkeySDKLoginType } from '../../../../types'; -import { PortkeySDKLoginProcessorBase, PortkeySDKLoginResult } from '../../processor'; - -export class DefaultLoginProcessor extends PortkeySDKLoginProcessorBase { - type: PortkeySDKLoginType = 'Default'; - - protected _processLogin(complete: (result: PortkeySDKLoginResult) => void): void { - throw new Error('Method not implemented.'); - } -} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts b/packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts deleted file mode 100644 index bcec605f..00000000 --- a/packages/aelf-web-login/src/wallets/portkey/react/processors/GoogleLoginProcessor.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { PortkeySDKLoginType } from '../../../../types'; -import { PortkeySDKLoginProcessorBase, PortkeySDKLoginResult } from '../../processor'; - -export class GoogleLoginProcessor extends PortkeySDKLoginProcessorBase { - type: PortkeySDKLoginType = 'Google'; - - protected _processLogin(complete: (result: PortkeySDKLoginResult) => void): void { - throw new Error('Method not implemented.'); - } -} diff --git a/packages/aelf-web-login/.eslintrc.json b/packages/core/.eslintrc.json similarity index 100% rename from packages/aelf-web-login/.eslintrc.json rename to packages/core/.eslintrc.json diff --git a/packages/aelf-web-login/.prettierrc b/packages/core/.prettierrc similarity index 100% rename from packages/aelf-web-login/.prettierrc rename to packages/core/.prettierrc diff --git a/packages/aelf-web-login/global.d.ts b/packages/core/global.d.ts similarity index 100% rename from packages/aelf-web-login/global.d.ts rename to packages/core/global.d.ts diff --git a/packages/login/package.json b/packages/core/package.json similarity index 89% rename from packages/login/package.json rename to packages/core/package.json index 6616cf42..528508a6 100644 --- a/packages/login/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { - "name": "aelf-web-login-legacy", - "version": "1.0.11-alpha", + "name": "@aelf-web-login/core", + "version": "0.1.0", "main": "dist/esm/index.js", "types": "dist/types/index.d.ts", "exports": { @@ -41,13 +41,11 @@ "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 && npm run build:css", - "build:css": "lessc ./index.less dist/assets/index.css", + "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": { - "@aelf-react/core": "^0.1.19", "@portkey/contracts": "^1.2.2", "@portkey/detect-provider": "1.0.1-alpha.0", "@portkey/did-ui-react": "^1.2.2", diff --git a/packages/aelf-web-login/rollup.config.js b/packages/core/rollup.config.js similarity index 100% rename from packages/aelf-web-login/rollup.config.js rename to packages/core/rollup.config.js diff --git a/packages/login/src/errors.ts b/packages/core/src/errors.ts similarity index 100% rename from packages/login/src/errors.ts rename to packages/core/src/errors.ts diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 00000000..721a0ede --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,5 @@ +export * from './wallets/portkey'; +export * from './wallets/nightElf'; +export * from './wallets/discover'; +export * from './types'; +export * from './errors'; diff --git a/packages/aelf-web-login/src/types.ts b/packages/core/src/types.ts similarity index 100% rename from packages/aelf-web-login/src/types.ts rename to packages/core/src/types.ts diff --git a/packages/aelf-web-login/src/wallets/discover/index.ts b/packages/core/src/wallets/discover/index.ts similarity index 100% rename from packages/aelf-web-login/src/wallets/discover/index.ts rename to packages/core/src/wallets/discover/index.ts diff --git a/packages/aelf-web-login/src/wallets/nightElf/index.ts b/packages/core/src/wallets/nightElf/index.ts similarity index 100% rename from packages/aelf-web-login/src/wallets/nightElf/index.ts rename to packages/core/src/wallets/nightElf/index.ts diff --git a/packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts b/packages/core/src/wallets/portkey/PortkeySDK.ts similarity index 100% rename from packages/aelf-web-login/src/wallets/portkey/PortkeySDK.ts rename to packages/core/src/wallets/portkey/PortkeySDK.ts 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/aelf-web-login/tsconfig.cjs.json b/packages/core/tsconfig.cjs.json similarity index 100% rename from packages/aelf-web-login/tsconfig.cjs.json rename to packages/core/tsconfig.cjs.json diff --git a/packages/aelf-web-login/tsconfig.esm.json b/packages/core/tsconfig.esm.json similarity index 100% rename from packages/aelf-web-login/tsconfig.esm.json rename to packages/core/tsconfig.esm.json diff --git a/packages/aelf-web-login/tsconfig.json b/packages/core/tsconfig.json similarity index 100% rename from packages/aelf-web-login/tsconfig.json rename to packages/core/tsconfig.json diff --git a/packages/aelf-web-login/tsconfig.types.json b/packages/core/tsconfig.types.json similarity index 100% rename from packages/aelf-web-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 ccce7b1e..0b6004b3 100644 --- a/packages/example/src/App.tsx +++ b/packages/example/src/App.tsx @@ -2,7 +2,7 @@ import VConsole from 'vconsole'; import { useState } from 'react'; import { Button, Tabs } from 'antd'; import isMobile from './utils/isMobile'; -import { usePortkeyUISDK } from 'aelf-web-login'; +import { usePortkeyUISDK } from '@aelf-web-login/react'; const win = window as any; let showVConsole = () => {}; diff --git a/packages/example/src/index.tsx b/packages/example/src/index.tsx index 0ca67af4..fff51256 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -2,15 +2,20 @@ import React, { useEffect, useMemo } from 'react'; import { createRoot } from 'react-dom/client'; 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 App from './App'; -import { PortkeySDKProvider } from 'aelf-web-login'; +import { PortkeySDKProvider } from '@aelf-web-login/react'; function Index() { return ( - + ); 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/isPortkeyApp.ts b/packages/login/src/utils/isPortkeyApp.ts deleted file mode 100644 index 6df6f797..00000000 --- a/packages/login/src/utils/isPortkeyApp.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default function isPortkeyApp() { - const ua = navigator.userAgent; - return ua.indexOf('Portkey did Mobile') !== -1; -} 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/login/.eslintrc.json b/packages/react/.eslintrc.json similarity index 100% rename from packages/login/.eslintrc.json rename to packages/react/.eslintrc.json diff --git a/packages/login/.prettierrc b/packages/react/.prettierrc similarity index 100% rename from packages/login/.prettierrc rename to packages/react/.prettierrc 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..f884a799 --- /dev/null +++ b/packages/react/index.less @@ -0,0 +1,11 @@ +.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); + margin-bottom: 12px; +} diff --git a/packages/aelf-web-login/package.json b/packages/react/package.json similarity index 95% rename from packages/aelf-web-login/package.json rename to packages/react/package.json index a6302b75..0f93cd13 100644 --- a/packages/aelf-web-login/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { - "name": "aelf-web-login", - "version": "2.0.0-alpha.1", + "name": "@aelf-web-login/react", + "version": "0.1.0", "main": "dist/esm/index.js", "types": "dist/types/index.d.ts", "exports": { @@ -54,6 +54,7 @@ "@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/login/rollup.config.js b/packages/react/rollup.config.js similarity index 100% rename from packages/login/rollup.config.js rename to packages/react/rollup.config.js diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts new file mode 100644 index 00000000..8f31e15d --- /dev/null +++ b/packages/react/src/index.ts @@ -0,0 +1,3 @@ +export * from './portkey/context'; +export * from './portkey/PortkeyUISDK'; +export * from './portkey/ExtraElement'; 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/nightElf/withNightElf.tsx b/packages/react/src/nightElf/withNightElf.tsx new file mode 100644 index 00000000..6ceb397c --- /dev/null +++ b/packages/react/src/nightElf/withNightElf.tsx @@ -0,0 +1,12 @@ +import { useNightElf } from './context'; + +export function withNightElf

void }>(Component: React.ComponentType

) { + return function NightElfButtonWrapper(props: P) { + const nightElf = useNightElf(); + return ( + <> + nightElf.login()} /> + + ); + }; +} diff --git a/packages/react/src/portkey/ExtraElement.tsx b/packages/react/src/portkey/ExtraElement.tsx new file mode 100644 index 00000000..add0e326 --- /dev/null +++ b/packages/react/src/portkey/ExtraElement.tsx @@ -0,0 +1,11 @@ +import { Button } from 'antd'; +import { PortkeyStyleProvider } from '@portkey/did-ui-react'; +import { useNightElf } from 'src/nightElf/context'; + +export default function ExtraElement() { + return ( + + + + ); +} diff --git a/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts b/packages/react/src/portkey/PortkeyUISDK.ts similarity index 76% rename from packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts rename to packages/react/src/portkey/PortkeyUISDK.ts index 1b8a415a..ebaaf706 100644 --- a/packages/aelf-web-login/src/wallets/portkey/react/PortkeyUISDK.ts +++ b/packages/react/src/portkey/PortkeyUISDK.ts @@ -1,22 +1,7 @@ -import { DIDWalletInfo, Theme, SignInInterface } from '@portkey/did-ui-react'; -import { ChainType, NetworkType } from '@portkey/provider-types'; -import { PortkeySDKLoginType } from '../../../types'; -import { PortkeySDK } from '../PortkeySDK'; +import { DIDWalletInfo, SignInInterface } from '@portkey/did-ui-react'; +import { PortkeySDK, makeError, ERR_CODE } from '@aelf-web-login/core'; import { RefObject } from 'react'; - -export type PortkeyState = { - theme?: Theme; - sandboxId?: string; - networkType: NetworkType; - chainType: ChainType; -}; - -export type PromiseHolder = - | { - resolve: () => void; - reject: (error: any) => void; - } - | undefined; +import { PortkeyState, PromiseHolder } from '../types'; export class PortkeyUISDK extends PortkeySDK { readonly portkeyState: PortkeyState; @@ -78,6 +63,6 @@ export class PortkeyUISDK extends PortkeySDK { return; } this.loginState = 'initial'; - this._promiseHolder?.reject('cancel'); + this._promiseHolder?.reject(makeError(ERR_CODE.USER_CANCEL)); } } diff --git a/packages/aelf-web-login/src/wallets/portkey/react/context.tsx b/packages/react/src/portkey/context.tsx similarity index 75% rename from packages/aelf-web-login/src/wallets/portkey/react/context.tsx rename to packages/react/src/portkey/context.tsx index 417f260a..0628617b 100644 --- a/packages/aelf-web-login/src/wallets/portkey/react/context.tsx +++ b/packages/react/src/portkey/context.tsx @@ -1,6 +1,8 @@ import React, { createContext, useContext, useMemo, useRef } from 'react'; import { PortkeyProvider, SignIn, SignInInterface } from '@portkey/did-ui-react'; -import { PortkeyState, PortkeyUISDK } from './PortkeyUISDK'; +import { PortkeyUISDK } from './PortkeyUISDK'; +import ExtraElement from './ExtraElement'; +import { PortkeyState } from '../types'; export type PortkeySDKProviderProps = PortkeyState & { customPortkeySDK?: PortkeyUISDK | (() => PortkeyUISDK); @@ -18,6 +20,10 @@ export function usePortkeyUISDK() { return useContext(PortkeySDKContext).portkeySDK; } +export function usePortkeyState(): PortkeyState { + return useContext(PortkeySDKContext); +} + export function PortkeySDKProvider({ customPortkeySDK, customPortkeyUI, @@ -25,7 +31,9 @@ export function PortkeySDKProvider({ chainType, networkType, theme, - sandboxId, + uiType, + design, + defaultChainId, }: PortkeySDKProviderProps) { const signInRef = useRef(null); const portkeySDK = useMemo( @@ -41,7 +49,9 @@ export function PortkeySDKProvider({ chainType, networkType, theme, - sandboxId, + uiType, + defaultChainId, + design, }, signInRef, ); @@ -52,8 +62,8 @@ export function PortkeySDKProvider({ ); const value = useMemo( - () => ({ chainType, networkType, theme, sandboxId, portkeySDK }), - [chainType, networkType, portkeySDK, sandboxId, theme], + () => ({ defaultChainId, chainType, networkType, theme, uiType, design, portkeySDK }), + [chainType, defaultChainId, design, networkType, portkeySDK, theme, uiType], ); const renderChildren = () => { @@ -70,7 +80,10 @@ export function PortkeySDKProvider({ {children} } onCancel={() => portkeySDK.onCancel()} onError={(error) => portkeySDK.onError(error)} onFinish={(didWalletInfo) => portkeySDK.onFinish(didWalletInfo)} @@ -80,7 +93,7 @@ export function PortkeySDKProvider({ }; return ( - + {renderChildren()}; ); diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts new file mode 100644 index 00000000..d6b2bdcf --- /dev/null +++ b/packages/react/src/types.ts @@ -0,0 +1,18 @@ +import type { TDesign, Theme, UI_TYPE } from '@portkey/did-ui-react'; +import type { ChainId, ChainType, NetworkType } from '@portkey/provider-types'; + +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/login/tsconfig.cjs.json b/packages/react/tsconfig.cjs.json similarity index 100% rename from packages/login/tsconfig.cjs.json rename to packages/react/tsconfig.cjs.json diff --git a/packages/login/tsconfig.esm.json b/packages/react/tsconfig.esm.json similarity index 100% rename from packages/login/tsconfig.esm.json rename to packages/react/tsconfig.esm.json diff --git a/packages/login/tsconfig.json b/packages/react/tsconfig.json similarity index 100% rename from packages/login/tsconfig.json rename to packages/react/tsconfig.json diff --git a/packages/login/tsconfig.types.json b/packages/react/tsconfig.types.json similarity index 100% rename from packages/login/tsconfig.types.json rename to packages/react/tsconfig.types.json diff --git a/packages/web/package.json b/packages/web/package.json index 831bd315..bffd7c58 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@aelf-web-login/web", - "version": "0.0.1-alpha.1.4", + "version": "0.0.1-alpha.1", "main": "dist/index.js", "types": "dist/index.d.ts", "exports": { @@ -18,7 +18,8 @@ "@types/react-dom": "^18.0.0", "react": "^18.2.0", "react-dom": "^18.0.0", - "aelf-web-login": "workspace:*", + "@aelf-web-login/core": "workspace:*", + "@aelf-web-login/react": "workspace:*", "cross-env": "^7.0.3", "vconsole": "^3.15.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 18588be8..fdc325f0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -162,7 +162,7 @@ importers: specifier: ^5.1.4 version: 5.1.4(webpack@5.88.2) - packages/aelf-web-login: + packages/core: dependencies: '@portkey/contracts': specifier: ^1.2.2 @@ -216,6 +216,12 @@ importers: 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) @@ -225,9 +231,6 @@ importers: '@types/react-dom': specifier: ^18.0.0 version: 18.0.0 - aelf-web-login: - specifier: workspace:* - version: link:../aelf-web-login ahooks: specifier: ^3.7.7 version: 3.7.7(react@18.2.0) @@ -257,11 +260,11 @@ importers: specifier: ^9.4.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 @@ -314,12 +317,15 @@ importers: 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 - aelf-web-login: - specifier: workspace:* - version: link:../aelf-web-login cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -358,24 +364,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 From 77260c8b0c3fb2256b23b32bd8757c17e7a16007 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 15 Aug 2023 18:04:21 +0800 Subject: [PATCH 07/20] feat: extra element --- packages/example/src/App.tsx | 2 +- packages/example/src/index.css | 36 +----- packages/example/src/index.tsx | 29 +++-- packages/react/index.less | 125 ++++++++++++++++++-- packages/react/src/icons/IconNightElf.tsx | 32 +++++ packages/react/src/icons/IconPortkey.tsx | 49 ++++++++ packages/react/src/index.ts | 1 + packages/react/src/portkey/ExtraElement.tsx | 60 +++++++++- packages/react/src/portkey/context.tsx | 28 ++--- packages/react/src/webLogin.tsx | 15 +++ 10 files changed, 307 insertions(+), 70 deletions(-) create mode 100644 packages/react/src/icons/IconNightElf.tsx create mode 100644 packages/react/src/icons/IconPortkey.tsx create mode 100644 packages/react/src/webLogin.tsx diff --git a/packages/example/src/App.tsx b/packages/example/src/App.tsx index 0b6004b3..ffe13e5f 100644 --- a/packages/example/src/App.tsx +++ b/packages/example/src/App.tsx @@ -17,7 +17,7 @@ export default function App() { const portkeySDK = usePortkeyUISDK(); return ( -

+
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 fff51256..9728ec62 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -1,23 +1,34 @@ -import React, { useEffect, useMemo } 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/react/dist/assets/index.css'; import './index.css'; import './config'; import App from './App'; -import { PortkeySDKProvider } from '@aelf-web-login/react'; function Index() { + const [theme, setTheme] = useState<'dark' | 'light'>('light'); return ( - + - + setTheme(checked ? 'dark' : 'light')} + /> + ); } diff --git a/packages/react/index.less b/packages/react/index.less index f884a799..f7f9c346 100644 --- a/packages/react/index.less +++ b/packages/react/index.less @@ -1,11 +1,116 @@ -.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); - margin-bottom: 12px; +.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; + + > 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/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 index 8f31e15d..9bc70851 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,3 +1,4 @@ export * from './portkey/context'; export * from './portkey/PortkeyUISDK'; export * from './portkey/ExtraElement'; +export * from './webLogin'; diff --git a/packages/react/src/portkey/ExtraElement.tsx b/packages/react/src/portkey/ExtraElement.tsx index add0e326..f9fbd557 100644 --- a/packages/react/src/portkey/ExtraElement.tsx +++ b/packages/react/src/portkey/ExtraElement.tsx @@ -1,11 +1,65 @@ import { Button } from 'antd'; import { PortkeyStyleProvider } from '@portkey/did-ui-react'; -import { useNightElf } from 'src/nightElf/context'; +import { PortkeySDKProviderProps, usePortkeyState } from './context'; +import IconPortkey from '../icons/IconPortkey'; +import IconNightElf from '../icons/IconNightElf'; + +export default function ExtraElement(props: PortkeySDKProviderProps) { + const portkeyState = usePortkeyState(); + const design = portkeyState.design; + + const renderButtons = ({ iconType }: { iconType: 'circle' | 'plain' }) => { + return ( + <> + + + + ); + }; + + 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' })}
+
+
+ ); + } -export default function ExtraElement() { return ( - +
+
Crypto wallet
+
+
+ + Portkey +
+
+ + Night Elf +
+
+
); } diff --git a/packages/react/src/portkey/context.tsx b/packages/react/src/portkey/context.tsx index 0628617b..862fe83c 100644 --- a/packages/react/src/portkey/context.tsx +++ b/packages/react/src/portkey/context.tsx @@ -7,7 +7,13 @@ import { PortkeyState } from '../types'; export type PortkeySDKProviderProps = PortkeyState & { customPortkeySDK?: PortkeyUISDK | (() => PortkeyUISDK); customPortkeyUI?: boolean; - children: React.ReactNode | ((portkeySDK: PortkeyUISDK) => React.ReactNode); + socialDesign?: + | { + logo?: string | undefined; + title?: string | undefined; + } + | undefined; + children: React.ReactNode; }; type PortkeySDKContextType = PortkeyState & { @@ -24,17 +30,9 @@ export function usePortkeyState(): PortkeyState { return useContext(PortkeySDKContext); } -export function PortkeySDKProvider({ - customPortkeySDK, - customPortkeyUI, - children, - chainType, - networkType, - theme, - uiType, - design, - defaultChainId, -}: PortkeySDKProviderProps) { +export function PortkeySDKProvider(props: PortkeySDKProviderProps) { + const { customPortkeySDK, customPortkeyUI, children, chainType, networkType, theme, uiType, design, defaultChainId } = + props; const signInRef = useRef(null); const portkeySDK = useMemo( () => { @@ -67,10 +65,6 @@ export function PortkeySDKProvider({ ); const renderChildren = () => { - if (typeof children === 'function') { - return children(portkeySDK); - } - if (customPortkeyUI) { return children; } @@ -83,7 +77,7 @@ export function PortkeySDKProvider({ design={design} uiType={uiType} defaultChainId={defaultChainId} - extraElement={} + extraElement={} onCancel={() => portkeySDK.onCancel()} onError={(error) => portkeySDK.onError(error)} onFinish={(didWalletInfo) => portkeySDK.onFinish(didWalletInfo)} diff --git a/packages/react/src/webLogin.tsx b/packages/react/src/webLogin.tsx new file mode 100644 index 00000000..8a4dc875 --- /dev/null +++ b/packages/react/src/webLogin.tsx @@ -0,0 +1,15 @@ +import { NightElfProvider } from './nightElf/context'; +import { PortkeySDKProvider, PortkeySDKProviderProps } from './portkey/context'; + +export type WebLoginProps = { + portkey: Omit; + children: React.ReactNode; +}; + +export function WebLoginProvider(props: WebLoginProps) { + return ( + + {props.children} + + ); +} From 929363c0963bc1e88d2cfb2d883bf3a13983a053 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 15 Aug 2023 18:55:15 +0800 Subject: [PATCH 08/20] feat: add login base --- packages/core/src/LoginBase.ts | 26 ++++++++++++++ packages/core/src/types.ts | 6 +++- packages/core/src/wallets/discover/index.ts | 8 +++-- packages/core/src/wallets/nightElf/index.ts | 6 ++-- .../core/src/wallets/portkey/PortkeySDK.ts | 8 +++-- packages/core/src/webLogin.ts | 34 +++++++++++++++++++ packages/react/index.less | 1 + packages/react/src/discover/context.tsx | 21 ++++++++++++ packages/react/src/hooks/useCyptoLogin.tsx | 8 +++++ packages/react/src/nightElf/withNightElf.tsx | 12 ------- packages/react/src/portkey/ExtraElement.tsx | 14 +++++--- packages/react/src/webLogin.tsx | 5 ++- 12 files changed, 123 insertions(+), 26 deletions(-) create mode 100644 packages/core/src/LoginBase.ts create mode 100644 packages/core/src/webLogin.ts create mode 100644 packages/react/src/discover/context.tsx create mode 100644 packages/react/src/hooks/useCyptoLogin.tsx delete mode 100644 packages/react/src/nightElf/withNightElf.tsx diff --git a/packages/core/src/LoginBase.ts b/packages/core/src/LoginBase.ts new file mode 100644 index 00000000..a8b99016 --- /dev/null +++ b/packages/core/src/LoginBase.ts @@ -0,0 +1,26 @@ +import { EventType, ILogin, LoginState, WalletInfo, WalletType } from './types'; +import { EventEmitter } from 'events'; + +export abstract class LoginBase implements ILogin { + abstract walletInfo: T; + abstract walletType: WalletType; + abstract loginState: LoginState; + + protected _events: EventEmitter; + + constructor() { + this._events = new EventEmitter(); + } + + on(event: EventType, listener: () => void): void { + this._events.on(event, listener); + } + off(event: EventType, listener: () => void): void { + this._events.off(event, listener); + } + + abstract login(): Promise; + abstract logout(): Promise; + abstract getWalletName(): Promise; + abstract getSignature(signInfo: string): Promise; +} diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 93a955d5..bd332e69 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -2,12 +2,14 @@ import type { DIDWalletInfo } from '@portkey/did-ui-react'; export type LoginState = 'initial' | 'logining' | 'logined' | 'logouting'; -export type WalletType = 'Discover' | 'NightElf' | 'PortkeySDK'; +export type WalletType = 'Unknown' | 'Discover' | 'NightElf' | 'PortkeySDK'; export type WalletInfo = { address: string; }; +export type EventType = 'logined'; + export type PortkeySDKWalletInfo = WalletInfo & { didWalletInfo?: DIDWalletInfo | undefined; }; @@ -16,6 +18,8 @@ export interface ILogin { walletType: WalletType; walletInfo: T; loginState: LoginState; + on(event: EventType, listener: () => void): void; + off(event: EventType, listener: () => void): void; login(): Promise; logout(): Promise; getWalletName(): Promise; diff --git a/packages/core/src/wallets/discover/index.ts b/packages/core/src/wallets/discover/index.ts index 92af365c..f5c9be16 100644 --- a/packages/core/src/wallets/discover/index.ts +++ b/packages/core/src/wallets/discover/index.ts @@ -1,16 +1,18 @@ -import { ILogin, LoginState, WalletInfo, WalletType } from '../../types'; +import { LoginBase } from '../../LoginBase'; +import { LoginState, WalletInfo, WalletType } from '../../types'; export type DiscoverWalletInfo = WalletInfo & {}; /** - * implement login feature based on aelf-bridge + * implement login feature based on detect provider */ -export class Discover implements ILogin { +export class Discover extends LoginBase { walletInfo: DiscoverWalletInfo; walletType: WalletType = 'Discover'; loginState: LoginState = 'initial'; constructor() { + super(); this.walletInfo = { address: '' }; } diff --git a/packages/core/src/wallets/nightElf/index.ts b/packages/core/src/wallets/nightElf/index.ts index efd97613..32a70ce1 100644 --- a/packages/core/src/wallets/nightElf/index.ts +++ b/packages/core/src/wallets/nightElf/index.ts @@ -1,16 +1,18 @@ -import { ILogin, LoginState, WalletInfo, WalletType } from '../../types'; +import { LoginBase } from '../../LoginBase'; +import { LoginState, WalletInfo, WalletType } from '../../types'; export type NightElfWalletInfo = WalletInfo & {}; /** * implement login feature based on aelf-bridge */ -export class NightElf implements ILogin { +export class NightElf extends LoginBase { walletInfo: NightElfWalletInfo; walletType: WalletType = 'NightElf'; loginState: LoginState = 'initial'; constructor() { + super(); this.walletInfo = { address: '' }; } diff --git a/packages/core/src/wallets/portkey/PortkeySDK.ts b/packages/core/src/wallets/portkey/PortkeySDK.ts index a3db8802..4fe853ca 100644 --- a/packages/core/src/wallets/portkey/PortkeySDK.ts +++ b/packages/core/src/wallets/portkey/PortkeySDK.ts @@ -1,14 +1,16 @@ -import { ILogin, LoginState, PortkeySDKWalletInfo, WalletType } from '../../types'; +import { LoginBase } from '../../LoginBase'; +import { LoginState, PortkeySDKWalletInfo, WalletType } from '../../types'; /** - * implement login feature based on aelf-bridge + * implement login feature based on portkey sdk */ -export abstract class PortkeySDK implements ILogin { +export abstract class PortkeySDK extends LoginBase { walletInfo: PortkeySDKWalletInfo; walletType: WalletType = 'PortkeySDK'; loginState: LoginState = 'initial'; constructor() { + super(); this.walletInfo = { address: '' }; } diff --git a/packages/core/src/webLogin.ts b/packages/core/src/webLogin.ts new file mode 100644 index 00000000..2253e7a8 --- /dev/null +++ b/packages/core/src/webLogin.ts @@ -0,0 +1,34 @@ +import { LoginBase } from './LoginBase'; +import { LoginState, PortkeySDKWalletInfo, WalletInfo, WalletType } from './types'; +import { DiscoverWalletInfo } from './wallets/discover'; +import { NightElfWalletInfo } from './wallets/nightElf'; + +export type WebLoginWalletInfo = WalletInfo & { + nightElf?: NightElfWalletInfo | undefined; + portkey?: PortkeySDKWalletInfo | undefined; + discover?: DiscoverWalletInfo | undefined; +}; + +export class WebLogin extends LoginBase { + walletInfo: WebLoginWalletInfo; + walletType: WalletType = 'Unknown'; + loginState: LoginState = 'initial'; + + constructor() { + super(); + this.walletInfo = { address: '' }; + } + + login(): Promise { + 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/react/index.less b/packages/react/index.less index f7f9c346..26defaac 100644 --- a/packages/react/index.less +++ b/packages/react/index.less @@ -96,6 +96,7 @@ justify-content: center; padding: 0; margin: 0; + cursor: pointer; > svg { width: 40px; 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/useCyptoLogin.tsx b/packages/react/src/hooks/useCyptoLogin.tsx new file mode 100644 index 00000000..83b99f9e --- /dev/null +++ b/packages/react/src/hooks/useCyptoLogin.tsx @@ -0,0 +1,8 @@ +import { ILogin, WalletInfo } from '@aelf-web-login/core'; + +export type CryptoWalletType = 'discover' | 'nightElf'; + +export function useCryptoLogin(login: ILogin) { + const handleLogin = () => login.login(); + return handleLogin; +} diff --git a/packages/react/src/nightElf/withNightElf.tsx b/packages/react/src/nightElf/withNightElf.tsx deleted file mode 100644 index 6ceb397c..00000000 --- a/packages/react/src/nightElf/withNightElf.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { useNightElf } from './context'; - -export function withNightElf

void }>(Component: React.ComponentType

) { - return function NightElfButtonWrapper(props: P) { - const nightElf = useNightElf(); - return ( - <> - nightElf.login()} /> - - ); - }; -} diff --git a/packages/react/src/portkey/ExtraElement.tsx b/packages/react/src/portkey/ExtraElement.tsx index f9fbd557..db8a2c98 100644 --- a/packages/react/src/portkey/ExtraElement.tsx +++ b/packages/react/src/portkey/ExtraElement.tsx @@ -3,18 +3,24 @@ import { PortkeyStyleProvider } from '@portkey/did-ui-react'; import { PortkeySDKProviderProps, usePortkeyState } from './context'; import IconPortkey from '../icons/IconPortkey'; import IconNightElf from '../icons/IconNightElf'; +import { useCryptoLogin } from '../hooks/useCyptoLogin'; +import { useDiscover } from '../discover/context'; +import { useNightElf } from '../nightElf/context'; export default function ExtraElement(props: PortkeySDKProviderProps) { const portkeyState = usePortkeyState(); const design = portkeyState.design; + const discoverLogin = useCryptoLogin(useDiscover()); + const nightElfLogin = useCryptoLogin(useNightElf()); + const renderButtons = ({ iconType }: { iconType: 'circle' | 'plain' }) => { return ( <> - - @@ -50,11 +56,11 @@ export default function ExtraElement(props: PortkeySDKProviderProps) {

Crypto wallet
-
+
Portkey
-
+
Night Elf
diff --git a/packages/react/src/webLogin.tsx b/packages/react/src/webLogin.tsx index 8a4dc875..e160ba9f 100644 --- a/packages/react/src/webLogin.tsx +++ b/packages/react/src/webLogin.tsx @@ -1,5 +1,6 @@ import { NightElfProvider } from './nightElf/context'; import { PortkeySDKProvider, PortkeySDKProviderProps } from './portkey/context'; +import { DiscoverProvider } from './discover/context'; export type WebLoginProps = { portkey: Omit; @@ -9,7 +10,9 @@ export type WebLoginProps = { export function WebLoginProvider(props: WebLoginProps) { return ( - {props.children} + + {props.children} + ); } From dde9e1763f786fad01c527a836e768a9d77fbbb7 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 15 Aug 2023 20:10:07 +0800 Subject: [PATCH 09/20] feat: updated --- packages/core/src/index.ts | 1 + packages/core/src/types.ts | 10 ---------- packages/core/src/webLogin.ts | 26 ++++++++++++++++---------- packages/react/src/webLogin.tsx | 10 ++++++++++ 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 721a0ede..ce929872 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -3,3 +3,4 @@ export * from './wallets/nightElf'; export * from './wallets/discover'; export * from './types'; export * from './errors'; +export * from './webLogin'; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index bd332e69..91a9c297 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -25,13 +25,3 @@ export interface ILogin { getWalletName(): Promise; getSignature(signInfo: string): Promise; } - -export type PortkeySDKLoginType = - | 'Google' - | 'Apple' - | 'Email' - | 'Phone' - | 'Scan' - | 'PortkeyApp' - | 'Default' - | 'AllInOne'; diff --git a/packages/core/src/webLogin.ts b/packages/core/src/webLogin.ts index 2253e7a8..b78032ea 100644 --- a/packages/core/src/webLogin.ts +++ b/packages/core/src/webLogin.ts @@ -1,5 +1,5 @@ import { LoginBase } from './LoginBase'; -import { LoginState, PortkeySDKWalletInfo, WalletInfo, WalletType } from './types'; +import { ILogin, LoginState, PortkeySDKWalletInfo, WalletInfo, WalletType } from './types'; import { DiscoverWalletInfo } from './wallets/discover'; import { NightElfWalletInfo } from './wallets/nightElf'; @@ -9,26 +9,32 @@ export type WebLoginWalletInfo = WalletInfo & { discover?: DiscoverWalletInfo | undefined; }; -export class WebLogin extends LoginBase { +export abstract class WebLogin extends LoginBase { walletInfo: WebLoginWalletInfo; walletType: WalletType = 'Unknown'; loginState: LoginState = 'initial'; + private _current: ILogin | undefined; + constructor() { super(); this.walletInfo = { address: '' }; } - login(): Promise { - throw new Error('Method not implemented.'); - } - logout(): Promise { - throw new Error('Method not implemented.'); - } + abstract login(): Promise; + abstract logout(): Promise; + getWalletName(): Promise { - throw new Error('Method not implemented.'); + if (!this._current) { + throw new Error('No wallet logined'); + } + return this._current.getWalletName(); } + getSignature(signInfo: string): Promise { - throw new Error('Method not implemented.'); + if (!this._current) { + throw new Error('No wallet logined'); + } + return this._current.getSignature(signInfo); } } diff --git a/packages/react/src/webLogin.tsx b/packages/react/src/webLogin.tsx index e160ba9f..24fbbadf 100644 --- a/packages/react/src/webLogin.tsx +++ b/packages/react/src/webLogin.tsx @@ -1,6 +1,16 @@ import { NightElfProvider } from './nightElf/context'; import { PortkeySDKProvider, PortkeySDKProviderProps } from './portkey/context'; import { DiscoverProvider } from './discover/context'; +import { WebLogin } from '@aelf-web-login/core'; + +export class ReactWebLogin extends WebLogin { + login(): Promise { + throw new Error('Method not implemented.'); + } + logout(): Promise { + throw new Error('Method not implemented.'); + } +} export type WebLoginProps = { portkey: Omit; From 6aaf6f56fd40dacc50559cf45709cf234d6fe61d Mon Sep 17 00:00:00 2001 From: holymingo Date: Wed, 16 Aug 2023 12:00:26 +0800 Subject: [PATCH 10/20] feat: login eagerly --- packages/core/src/LoginBase.ts | 18 +++++++ packages/core/src/types.ts | 2 + packages/core/src/wallets/discover/index.ts | 4 ++ packages/core/src/wallets/nightElf/index.ts | 4 ++ packages/core/src/webLogin.ts | 3 ++ packages/react/src/context.tsx | 42 +++++++++++++++ ...CyptoLogin.tsx => useExtraWalletLogin.tsx} | 4 +- packages/react/src/index.ts | 1 + packages/react/src/portkey/ExtraElement.tsx | 6 +-- packages/react/src/portkey/PortkeyUISDK.ts | 19 ++++++- packages/react/src/portkey/context.tsx | 50 ++++++++++++++++- packages/react/src/webLogin.ts | 53 +++++++++++++++++++ packages/react/src/webLogin.tsx | 28 ---------- 13 files changed, 199 insertions(+), 35 deletions(-) create mode 100644 packages/react/src/context.tsx rename packages/react/src/hooks/{useCyptoLogin.tsx => useExtraWalletLogin.tsx} (60%) create mode 100644 packages/react/src/webLogin.ts delete mode 100644 packages/react/src/webLogin.tsx diff --git a/packages/core/src/LoginBase.ts b/packages/core/src/LoginBase.ts index a8b99016..82a5c77c 100644 --- a/packages/core/src/LoginBase.ts +++ b/packages/core/src/LoginBase.ts @@ -12,6 +12,10 @@ export abstract class LoginBase implements ILogin { this._events = new EventEmitter(); } + getLoginEagerlyKey(): string { + return `AElf.WebLogin.${this.walletType}.loginEagerly`; + } + on(event: EventType, listener: () => void): void { this._events.on(event, listener); } @@ -19,6 +23,20 @@ export abstract class LoginBase implements ILogin { this._events.off(event, listener); } + 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(): Promise; abstract logout(): Promise; abstract getWalletName(): Promise; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 91a9c297..d4c40372 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -21,6 +21,8 @@ export interface ILogin { on(event: EventType, listener: () => void): void; off(event: EventType, listener: () => void): void; login(): Promise; + canLoginEagerly(): boolean; + loginEagerly(): Promise; logout(): Promise; getWalletName(): Promise; getSignature(signInfo: string): Promise; diff --git a/packages/core/src/wallets/discover/index.ts b/packages/core/src/wallets/discover/index.ts index f5c9be16..9cdc8d80 100644 --- a/packages/core/src/wallets/discover/index.ts +++ b/packages/core/src/wallets/discover/index.ts @@ -16,6 +16,10 @@ export class Discover extends LoginBase { this.walletInfo = { address: '' }; } + loginEagerly(): Promise { + throw new Error('Method not implemented.'); + } + login(): 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 index 32a70ce1..dfa09d4a 100644 --- a/packages/core/src/wallets/nightElf/index.ts +++ b/packages/core/src/wallets/nightElf/index.ts @@ -16,6 +16,10 @@ export class NightElf extends LoginBase { this.walletInfo = { address: '' }; } + loginEagerly(): Promise { + throw new Error('Method not implemented.'); + } + login(): Promise { throw new Error('Method not implemented.'); } diff --git a/packages/core/src/webLogin.ts b/packages/core/src/webLogin.ts index b78032ea..045b1f5a 100644 --- a/packages/core/src/webLogin.ts +++ b/packages/core/src/webLogin.ts @@ -21,6 +21,9 @@ export abstract class WebLogin extends LoginBase { this.walletInfo = { address: '' }; } + abstract setLoginEagerly(flag: boolean): void; + abstract canLoginEagerly(): boolean; + abstract loginEagerly(): Promise; abstract login(): Promise; abstract logout(): Promise; 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/hooks/useCyptoLogin.tsx b/packages/react/src/hooks/useExtraWalletLogin.tsx similarity index 60% rename from packages/react/src/hooks/useCyptoLogin.tsx rename to packages/react/src/hooks/useExtraWalletLogin.tsx index 83b99f9e..32da26b6 100644 --- a/packages/react/src/hooks/useCyptoLogin.tsx +++ b/packages/react/src/hooks/useExtraWalletLogin.tsx @@ -2,7 +2,9 @@ import { ILogin, WalletInfo } from '@aelf-web-login/core'; export type CryptoWalletType = 'discover' | 'nightElf'; -export function useCryptoLogin(login: ILogin) { +export function useExtraWalletLogin(login: ILogin) { const handleLogin = () => login.login(); + // TODO: debounce + // TODO: click logic return handleLogin; } diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 9bc70851..09d132af 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,4 +1,5 @@ export * from './portkey/context'; export * from './portkey/PortkeyUISDK'; export * from './portkey/ExtraElement'; +export * from './context'; export * from './webLogin'; diff --git a/packages/react/src/portkey/ExtraElement.tsx b/packages/react/src/portkey/ExtraElement.tsx index db8a2c98..3f95497c 100644 --- a/packages/react/src/portkey/ExtraElement.tsx +++ b/packages/react/src/portkey/ExtraElement.tsx @@ -3,7 +3,7 @@ import { PortkeyStyleProvider } from '@portkey/did-ui-react'; import { PortkeySDKProviderProps, usePortkeyState } from './context'; import IconPortkey from '../icons/IconPortkey'; import IconNightElf from '../icons/IconNightElf'; -import { useCryptoLogin } from '../hooks/useCyptoLogin'; +import { useExtraWalletLogin } from '../hooks/useExtraWalletLogin'; import { useDiscover } from '../discover/context'; import { useNightElf } from '../nightElf/context'; @@ -11,8 +11,8 @@ export default function ExtraElement(props: PortkeySDKProviderProps) { const portkeyState = usePortkeyState(); const design = portkeyState.design; - const discoverLogin = useCryptoLogin(useDiscover()); - const nightElfLogin = useCryptoLogin(useNightElf()); + const discoverLogin = useExtraWalletLogin(useDiscover()); + const nightElfLogin = useExtraWalletLogin(useNightElf()); const renderButtons = ({ iconType }: { iconType: 'circle' | 'plain' }) => { return ( diff --git a/packages/react/src/portkey/PortkeyUISDK.ts b/packages/react/src/portkey/PortkeyUISDK.ts index ebaaf706..c5a16b3a 100644 --- a/packages/react/src/portkey/PortkeyUISDK.ts +++ b/packages/react/src/portkey/PortkeyUISDK.ts @@ -6,16 +6,29 @@ import { PortkeyState, PromiseHolder } from '../types'; export class PortkeyUISDK extends PortkeySDK { readonly portkeyState: PortkeyState; readonly signInfRef: RefObject; + setUnlockOpen: (open: boolean) => void; private _promiseHolder: PromiseHolder; - constructor(portkeyState: PortkeyState, signInfRef: RefObject) { + constructor( + portkeyState: PortkeyState, + signInfRef: RefObject, + setUnlockOpen: (open: boolean) => void, + ) { super(); this.portkeyState = portkeyState; this.signInfRef = signInfRef; + this.setUnlockOpen = setUnlockOpen; + } + + loginEagerly(): Promise { + throw new Error('Method not implemented.'); } login(): Promise { + 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}`); } @@ -57,6 +70,10 @@ export class PortkeyUISDK extends PortkeySDK { this._promiseHolder?.reject(error); } + onUnlock(didWalletInfo: DIDWalletInfo) { + throw new Error('Method not implemented.'); + } + onCancel() { if (this.loginState !== 'logining') { console.warn('onCancel called when loginState is not logining', this.loginState); diff --git a/packages/react/src/portkey/context.tsx b/packages/react/src/portkey/context.tsx index 862fe83c..8e0905e6 100644 --- a/packages/react/src/portkey/context.tsx +++ b/packages/react/src/portkey/context.tsx @@ -1,10 +1,12 @@ -import React, { createContext, useContext, useMemo, useRef } from 'react'; -import { PortkeyProvider, SignIn, SignInInterface } from '@portkey/did-ui-react'; +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'; +import { ChainId } from '@portkey/types'; export type PortkeySDKProviderProps = PortkeyState & { + appName: string; customPortkeySDK?: PortkeyUISDK | (() => PortkeyUISDK); customPortkeyUI?: boolean; socialDesign?: @@ -34,6 +36,10 @@ 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) { @@ -52,6 +58,7 @@ export function PortkeySDKProvider(props: PortkeySDKProviderProps) { design, }, signInRef, + setUnlockOpen, ); return sdk; }, @@ -64,6 +71,37 @@ export function PortkeySDKProvider(props: PortkeySDKProviderProps) { [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(''); + + // const didWalletInfo: DIDWalletInfo = { + // pin: password, + // chainId: originChainId as ChainId, + // walletInfo: localWallet.didWallet.managementAccount!.wallet as any, + // accountInfo: localWallet.didWallet.accountInfo as any, + // }; + } catch (error) { + setIsWrongPassword(true); + return; + } + }; + + useEffect(() => { + portkeySDK.setUnlockOpen = setUnlockOpen; + }, [portkeySDK, setUnlockOpen]); + const renderChildren = () => { if (customPortkeyUI) { return children; @@ -82,6 +120,14 @@ export function PortkeySDKProvider(props: PortkeySDKProviderProps) { onError={(error) => portkeySDK.onError(error)} onFinish={(didWalletInfo) => portkeySDK.onFinish(didWalletInfo)} /> + portkeySDK.onCancel()} + onUnlock={onUnlockInternal} + /> ); }; diff --git a/packages/react/src/webLogin.ts b/packages/react/src/webLogin.ts new file mode 100644 index 00000000..3f0777dc --- /dev/null +++ b/packages/react/src/webLogin.ts @@ -0,0 +1,53 @@ +import { NightElf, Discover, WebLogin } 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(): Promise { + throw new Error('Method not implemented.'); + } + logout(): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/react/src/webLogin.tsx b/packages/react/src/webLogin.tsx deleted file mode 100644 index 24fbbadf..00000000 --- a/packages/react/src/webLogin.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { NightElfProvider } from './nightElf/context'; -import { PortkeySDKProvider, PortkeySDKProviderProps } from './portkey/context'; -import { DiscoverProvider } from './discover/context'; -import { WebLogin } from '@aelf-web-login/core'; - -export class ReactWebLogin extends WebLogin { - login(): Promise { - throw new Error('Method not implemented.'); - } - logout(): Promise { - throw new Error('Method not implemented.'); - } -} - -export type WebLoginProps = { - portkey: Omit; - children: React.ReactNode; -}; - -export function WebLoginProvider(props: WebLoginProps) { - return ( - - - {props.children} - - - ); -} From e8a1449359601a5f88e876b1dd1a1511b6f94881 Mon Sep 17 00:00:00 2001 From: holymingo Date: Thu, 17 Aug 2023 19:51:23 +0800 Subject: [PATCH 11/20] feat: login logic --- package.json | 2 + packages/core/package.json | 2 + packages/core/src/LoginBase.ts | 16 ++-- packages/core/src/errors.ts | 5 +- packages/core/src/index.ts | 1 + packages/core/src/types.ts | 27 ++++--- .../core/src/utils/newCancalablePromise.ts | 6 ++ packages/core/src/wallets/discover/index.ts | 4 +- packages/core/src/wallets/nightElf/index.ts | 4 +- .../core/src/wallets/portkey/PortkeySDK.ts | 10 ++- packages/core/src/webLogin.ts | 7 +- packages/example/src/index.tsx | 1 + packages/react/package.json | 1 + packages/react/src/portkey/PortkeyUISDK.ts | 61 ++++++++++++--- packages/react/src/webLogin.ts | 77 ++++++++++++++++++- pnpm-lock.yaml | 42 +++++++++- 16 files changed, 223 insertions(+), 43 deletions(-) create mode 100644 packages/core/src/utils/newCancalablePromise.ts diff --git a/package.json b/package.json index 2011fd6c..fa21bc60 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "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", "test": "jest", "test:browser": "jest --config=jest.browser.config.ts", @@ -45,6 +46,7 @@ "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", diff --git a/packages/core/package.json b/packages/core/package.json index 528508a6..3900d7d8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -48,6 +48,7 @@ "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", @@ -57,6 +58,7 @@ "aelf-sdk": "^3.2.40", "ahooks": "^3.7.7", "antd": "^4.24.4", + "cancelable-promise": "^4.3.1", "typescript": "^4.9.5" }, "devDependencies": { diff --git a/packages/core/src/LoginBase.ts b/packages/core/src/LoginBase.ts index 82a5c77c..79649825 100644 --- a/packages/core/src/LoginBase.ts +++ b/packages/core/src/LoginBase.ts @@ -1,8 +1,8 @@ -import { EventType, ILogin, LoginState, WalletInfo, WalletType } from './types'; +import { CancelablePromise, EventType, ILogin, LoginState, WalletInfo, WalletType } from './types'; import { EventEmitter } from 'events'; -export abstract class LoginBase implements ILogin { - abstract walletInfo: T; +export abstract class LoginBase implements ILogin { + abstract walletInfo: W; abstract walletType: WalletType; abstract loginState: LoginState; @@ -16,13 +16,17 @@ export abstract class LoginBase implements ILogin { return `AElf.WebLogin.${this.walletType}.loginEagerly`; } - on(event: EventType, listener: () => void): void { + on(event: EventType, listener: (data: T) => void): void { this._events.on(event, listener); } - off(event: EventType, listener: () => void): void { + 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()); } @@ -37,7 +41,7 @@ export abstract class LoginBase implements ILogin { } abstract loginEagerly(): Promise; - abstract login(): Promise; + abstract login(): CancelablePromise; abstract logout(): Promise; abstract getWalletName(): Promise; abstract getSignature(signInfo: string): Promise; diff --git a/packages/core/src/errors.ts b/packages/core/src/errors.ts index 2f1a1cdd..50afa67b 100644 --- a/packages/core/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 index ce929872..2ddfd0f9 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -4,3 +4,4 @@ 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 index d4c40372..15ca2a1d 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -1,4 +1,4 @@ -import type { DIDWalletInfo } from '@portkey/did-ui-react'; +import CancelablePromiseImpl from 'cancelable-promise'; export type LoginState = 'initial' | 'logining' | 'logined' | 'logouting'; @@ -8,22 +8,27 @@ export type WalletInfo = { address: string; }; -export type EventType = 'logined'; +export type EventType = 'logined' | 'cancelLogin' | 'commonError'; -export type PortkeySDKWalletInfo = WalletInfo & { - didWalletInfo?: DIDWalletInfo | undefined; -}; - -export interface ILogin { +export interface ILogin { walletType: WalletType; - walletInfo: T; + walletInfo: W; loginState: LoginState; - on(event: EventType, listener: () => void): void; - off(event: EventType, listener: () => void): void; - login(): Promise; + 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/newCancalablePromise.ts b/packages/core/src/utils/newCancalablePromise.ts new file mode 100644 index 00000000..9278fb5c --- /dev/null +++ b/packages/core/src/utils/newCancalablePromise.ts @@ -0,0 +1,6 @@ +import 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 index 9cdc8d80..60dbaf6f 100644 --- a/packages/core/src/wallets/discover/index.ts +++ b/packages/core/src/wallets/discover/index.ts @@ -1,5 +1,5 @@ import { LoginBase } from '../../LoginBase'; -import { LoginState, WalletInfo, WalletType } from '../../types'; +import { CancelablePromise, LoginState, WalletInfo, WalletType } from '../../types'; export type DiscoverWalletInfo = WalletInfo & {}; @@ -20,7 +20,7 @@ export class Discover extends LoginBase { throw new Error('Method not implemented.'); } - login(): Promise { + login(): CancelablePromise { throw new Error('Method not implemented.'); } logout(): Promise { diff --git a/packages/core/src/wallets/nightElf/index.ts b/packages/core/src/wallets/nightElf/index.ts index dfa09d4a..46e37af1 100644 --- a/packages/core/src/wallets/nightElf/index.ts +++ b/packages/core/src/wallets/nightElf/index.ts @@ -1,5 +1,5 @@ import { LoginBase } from '../../LoginBase'; -import { LoginState, WalletInfo, WalletType } from '../../types'; +import { CancelablePromise, LoginState, WalletInfo, WalletType } from '../../types'; export type NightElfWalletInfo = WalletInfo & {}; @@ -20,7 +20,7 @@ export class NightElf extends LoginBase { throw new Error('Method not implemented.'); } - login(): Promise { + login(): CancelablePromise { throw new Error('Method not implemented.'); } logout(): Promise { diff --git a/packages/core/src/wallets/portkey/PortkeySDK.ts b/packages/core/src/wallets/portkey/PortkeySDK.ts index 4fe853ca..9c84210c 100644 --- a/packages/core/src/wallets/portkey/PortkeySDK.ts +++ b/packages/core/src/wallets/portkey/PortkeySDK.ts @@ -1,5 +1,11 @@ +import { DID } from '@portkey/did'; import { LoginBase } from '../../LoginBase'; -import { LoginState, PortkeySDKWalletInfo, WalletType } from '../../types'; +import { CancelablePromise, LoginState, WalletInfo, WalletType } from '../../types'; + +export type PortkeySDKWalletInfo = WalletInfo & { + originChainId?: string; + did?: DID; +}; /** * implement login feature based on portkey sdk @@ -21,6 +27,6 @@ export abstract class PortkeySDK extends LoginBase { throw new Error('Method not implemented.'); } - abstract login(): Promise; + abstract login(): CancelablePromise; abstract logout(): Promise; } diff --git a/packages/core/src/webLogin.ts b/packages/core/src/webLogin.ts index 045b1f5a..3184eae8 100644 --- a/packages/core/src/webLogin.ts +++ b/packages/core/src/webLogin.ts @@ -1,7 +1,8 @@ import { LoginBase } from './LoginBase'; -import { ILogin, LoginState, PortkeySDKWalletInfo, WalletInfo, WalletType } from './types'; +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; @@ -14,7 +15,7 @@ export abstract class WebLogin extends LoginBase { walletType: WalletType = 'Unknown'; loginState: LoginState = 'initial'; - private _current: ILogin | undefined; + protected _current: ILogin | undefined; constructor() { super(); @@ -24,7 +25,7 @@ export abstract class WebLogin extends LoginBase { abstract setLoginEagerly(flag: boolean): void; abstract canLoginEagerly(): boolean; abstract loginEagerly(): Promise; - abstract login(): Promise; + abstract login(): CancelablePromise; abstract logout(): Promise; getWalletName(): Promise { diff --git a/packages/example/src/index.tsx b/packages/example/src/index.tsx index 9728ec62..98a3ab3a 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -14,6 +14,7 @@ function Index() { return ( ; @@ -22,10 +24,23 @@ export class PortkeyUISDK extends PortkeySDK { } loginEagerly(): Promise { - throw new Error('Method not implemented.'); + 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(): Promise { + login(): CancelablePromise { if (this.portkeyState.uiType !== 'Modal') { throw new Error('login only support Modal uiType'); } @@ -36,15 +51,27 @@ export class PortkeyUISDK extends PortkeySDK { const signIn = this.signInfRef.current!; signIn.setOpen(true); - return new Promise((resolve, reject) => { + return newCancelablePromise((resolve, reject, onCancel) => { + onCancel(() => { + this.loginState = 'initial'; + this._promiseHolder = undefined; + signIn.setOpen(false); + }); this._promiseHolder = { - resolve, - reject, + resolve: () => { + signIn.setOpen(false); + resolve(); + }, + reject: (error: any) => { + reject(error); + }, }; }); } logout(): Promise { + localStorage.removeItem(ORIGIN_CHAIN_ID_KEY); + this.setLoginEagerly(false); throw new Error('Method not implemented.'); } @@ -56,22 +83,36 @@ export class PortkeyUISDK extends PortkeySDK { this.loginState = 'logined'; this.walletInfo = { address: didWalletInfo?.caInfo.caAddress || '', - didWalletInfo, + originChainId: didWalletInfo.chainId, + did: did, }; + localStorage.setItem(ORIGIN_CHAIN_ID_KEY, didWalletInfo.chainId); + this.setLoginEagerly(true); this._promiseHolder?.resolve(); } onError(error: any) { if (this.loginState !== 'logining') { + 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, + }); return; } this.loginState = 'initial'; this._promiseHolder?.reject(error); } - onUnlock(didWalletInfo: DIDWalletInfo) { - throw new Error('Method not implemented.'); + 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() { diff --git a/packages/react/src/webLogin.ts b/packages/react/src/webLogin.ts index 3f0777dc..0faeb770 100644 --- a/packages/react/src/webLogin.ts +++ b/packages/react/src/webLogin.ts @@ -1,4 +1,12 @@ -import { NightElf, Discover, WebLogin } from '@aelf-web-login/core'; +import { + NightElf, + Discover, + WebLogin, + CancelablePromise, + newCancelablePromise, + makeError, + ERR_CODE, +} from '@aelf-web-login/core'; import { PortkeyUISDK } from './portkey/PortkeyUISDK'; export class ReactWebLogin extends WebLogin { @@ -44,10 +52,71 @@ export class ReactWebLogin extends WebLogin { return Promise.resolve(); } - login(): Promise { - throw new Error('Method not implemented.'); + 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 { - throw new Error('Method not implemented.'); + 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/pnpm-lock.yaml b/pnpm-lock.yaml index fdc325f0..2bd1e046 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,6 +68,9 @@ importers: 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) @@ -170,6 +173,9 @@ importers: '@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) @@ -197,6 +203,9 @@ importers: 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 typescript: specifier: ^4.9.5 version: 4.9.5 @@ -271,6 +280,9 @@ importers: '@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) @@ -5393,6 +5405,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: @@ -5687,6 +5703,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==} @@ -6130,7 +6162,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==} @@ -13451,6 +13482,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: @@ -14071,6 +14106,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'} From 42aac143cb03301c890142db81cad39623c566d2 Mon Sep 17 00:00:00 2001 From: holymingo Date: Fri, 18 Aug 2023 18:42:18 +0800 Subject: [PATCH 12/20] feat: detect web env --- packages/core/package.json | 1 + packages/core/src/utils/detectWebEnv.ts | 28 +++++++++++++++++++++++++ packages/core/src/utils/isAElfWallet.ts | 12 +++++++++++ packages/core/src/utils/isPortkeyApp.ts | 4 ++++ pnpm-lock.yaml | 7 +++++++ 5 files changed, 52 insertions(+) create mode 100644 packages/core/src/utils/detectWebEnv.ts create mode 100644 packages/core/src/utils/isAElfWallet.ts create mode 100644 packages/core/src/utils/isPortkeyApp.ts diff --git a/packages/core/package.json b/packages/core/package.json index 3900d7d8..2119616c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -59,6 +59,7 @@ "ahooks": "^3.7.7", "antd": "^4.24.4", "cancelable-promise": "^4.3.1", + "ismobilejs": "^1.1.1", "typescript": "^4.9.5" }, "devDependencies": { 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..a2a70082 --- /dev/null +++ b/packages/core/src/utils/isAElfWallet.ts @@ -0,0 +1,12 @@ +import isMobile from 'ismobilejs'; + +const mobile = isMobile(window.navigator); + +export default function isAElfWallet() { + if (!mobile.any) return false; + const win = window as any; + return ( + ('android' in window && mobile.android) || + (mobile.apple && win.webkit && win.webkit.messageHandlers && win.webkit.messageHandlers.JSCallback) + ); +} diff --git a/packages/core/src/utils/isPortkeyApp.ts b/packages/core/src/utils/isPortkeyApp.ts new file mode 100644 index 00000000..6df6f797 --- /dev/null +++ b/packages/core/src/utils/isPortkeyApp.ts @@ -0,0 +1,4 @@ +export default function isPortkeyApp() { + const ua = navigator.userAgent; + return ua.indexOf('Portkey did Mobile') !== -1; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2bd1e046..ea107d24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -206,6 +206,9 @@ importers: 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 @@ -8606,6 +8609,10 @@ 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'} From 3de5b85a861a5bcc34b094663d5c2de269d58a00 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 18:21:32 +0800 Subject: [PATCH 13/20] feat: add unit test --- .github/workflows/CI.yml | 7 +- jest.config.ts | 206 ++++++++++++++++++ package.json | 7 +- packages/core/jest.config.ts | 5 + packages/core/package.json | 2 +- packages/core/src/utils/isAElfWallet.ts | 5 +- .../core/src/utils/newCancalablePromise.ts | 2 +- packages/core/test/utils.test.ts | 8 + packages/example/src/index.tsx | 2 +- .../react/src/hooks/useExtraWalletLogin.tsx | 4 +- packages/react/src/portkey/ExtraElement.tsx | 40 ++-- packages/react/src/portkey/context.tsx | 3 +- packages/web/src/setup.tsx | 19 +- pnpm-lock.yaml | 2 +- 14 files changed, 275 insertions(+), 37 deletions(-) create mode 100644 jest.config.ts create mode 100644 packages/core/jest.config.ts create mode 100644 packages/core/test/utils.test.ts 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/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 fa21bc60..5154d8e4 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,7 @@ "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", - "test": "jest", - "test:browser": "jest --config=jest.browser.config.ts", - "make-badges": "istanbul-badges-readme" + "example": "pnpm --filter @aelf-web-login/example start" }, "devDependencies": { "@babel/core": "^7.20.12", @@ -58,7 +55,7 @@ "jest": "^29.3.1", "jest-environment-jsdom": "^29.4.3", "less-loader": "^11.1.3", - "lint-staged": ">=13", + "lint-staged": "^13.0.0", "node-fetch": "^3.3.0", "postcss": "^8.4.21", "postcss-url": "^10.1.3", 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 index 2119616c..970690d7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -31,8 +31,8 @@ "scripts": { "prebuild": "rm -rf dist", "start": "tsc --watch", + "test": "jest", "lint": "eslint . --ext .tsx,.ts", - "lint:md": "remark . -f -q", "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", diff --git a/packages/core/src/utils/isAElfWallet.ts b/packages/core/src/utils/isAElfWallet.ts index a2a70082..a5ddbb38 100644 --- a/packages/core/src/utils/isAElfWallet.ts +++ b/packages/core/src/utils/isAElfWallet.ts @@ -1,12 +1,11 @@ import isMobile from 'ismobilejs'; -const mobile = isMobile(window.navigator); - export default function isAElfWallet() { + const mobile = isMobile(navigator); if (!mobile.any) return false; const win = window as any; return ( - ('android' in window && mobile.android) || + (win.android && mobile.android) || (mobile.apple && win.webkit && win.webkit.messageHandlers && win.webkit.messageHandlers.JSCallback) ); } diff --git a/packages/core/src/utils/newCancalablePromise.ts b/packages/core/src/utils/newCancalablePromise.ts index 9278fb5c..a1c76190 100644 --- a/packages/core/src/utils/newCancalablePromise.ts +++ b/packages/core/src/utils/newCancalablePromise.ts @@ -1,4 +1,4 @@ -import CancelablePromiseImpl from 'cancelable-promise'; +import { CancelablePromise as CancelablePromiseImpl } from 'cancelable-promise'; import { CancelablePromise, CancelablePromiseExecutor } from '../types'; export function newCancelablePromise(executor: CancelablePromiseExecutor): CancelablePromise { diff --git a/packages/core/test/utils.test.ts b/packages/core/test/utils.test.ts new file mode 100644 index 00000000..940f25f5 --- /dev/null +++ b/packages/core/test/utils.test.ts @@ -0,0 +1,8 @@ +import { describe, expect, test } from '@jest/globals'; +import isAElfWallet from '../src/utils/isAElfWallet'; + +describe('utils', () => { + test('isAElfWallet', async () => { + expect(isAElfWallet()).toEqual(false); + }); +}); diff --git a/packages/example/src/index.tsx b/packages/example/src/index.tsx index 98a3ab3a..861173e7 100644 --- a/packages/example/src/index.tsx +++ b/packages/example/src/index.tsx @@ -19,7 +19,7 @@ function Index() { chainType: 'aelf', defaultChainId: 'AELF', uiType: 'Modal', - design: 'Web2Design', + design: 'SocialDesign', theme, }}> diff --git a/packages/react/src/hooks/useExtraWalletLogin.tsx b/packages/react/src/hooks/useExtraWalletLogin.tsx index 32da26b6..aa2f3daf 100644 --- a/packages/react/src/hooks/useExtraWalletLogin.tsx +++ b/packages/react/src/hooks/useExtraWalletLogin.tsx @@ -4,7 +4,7 @@ export type CryptoWalletType = 'discover' | 'nightElf'; export function useExtraWalletLogin(login: ILogin) { const handleLogin = () => login.login(); - // TODO: debounce - // TODO: click logic + // TODO debounce + // TODO check env return handleLogin; } diff --git a/packages/react/src/portkey/ExtraElement.tsx b/packages/react/src/portkey/ExtraElement.tsx index 3f95497c..f854ed51 100644 --- a/packages/react/src/portkey/ExtraElement.tsx +++ b/packages/react/src/portkey/ExtraElement.tsx @@ -10,19 +10,27 @@ 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 && ( + + )} ); }; @@ -56,14 +64,18 @@ export default function ExtraElement(props: PortkeySDKProviderProps) {
Crypto wallet
-
- - Portkey -
-
- - Night Elf -
+ {showDiscover && ( +
+ + Portkey +
+ )} + {showNightElf && ( +
+ + Night Elf +
+ )}
diff --git a/packages/react/src/portkey/context.tsx b/packages/react/src/portkey/context.tsx index 8e0905e6..9e9b0d51 100644 --- a/packages/react/src/portkey/context.tsx +++ b/packages/react/src/portkey/context.tsx @@ -3,12 +3,13 @@ import { PortkeyProvider, SignIn, SignInInterface, Unlock, did } from '@portkey/ import { PortkeyUISDK } from './PortkeyUISDK'; import ExtraElement from './ExtraElement'; import { PortkeyState } from '../types'; -import { ChainId } from '@portkey/types'; export type PortkeySDKProviderProps = PortkeyState & { appName: string; customPortkeySDK?: PortkeyUISDK | (() => PortkeyUISDK); customPortkeyUI?: boolean; + showNightElf?: boolean; + showDiscover?: boolean; socialDesign?: | { logo?: string | undefined; diff --git a/packages/web/src/setup.tsx b/packages/web/src/setup.tsx index 51a9e7d3..610f6ae3 100644 --- a/packages/web/src/setup.tsx +++ b/packages/web/src/setup.tsx @@ -1,12 +1,23 @@ -import React, { useEffect, useMemo } from 'react'; +import React, { useState } from 'react'; import { createRoot } from 'react-dom/client'; -import { PortkeySDKProvider } from 'aelf-web-login'; +import { WebLoginProvider } from '@aelf-web-login/react'; function SDKRoot() { + const [theme, setTheme] = useState<'dark' | 'light'>('light'); + return ( - + <> - +
); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea107d24..2be40079 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,7 +105,7 @@ importers: 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 From 53ec9767afa5d88d968a82db76149ee73d841730 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 18:23:16 +0800 Subject: [PATCH 14/20] feat: lint & test before commit --- .husky/pre-commit | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From ee86ae734a4ccf19e1a21a01f3d2234f1c05eb7d Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 18:27:44 +0800 Subject: [PATCH 15/20] feat: ci yarn => pnpm --- .github/actions/setup/action.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 034ec5dc..29aec353 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -8,14 +8,14 @@ runs: with: node-version: 16 registry-url: https://registry.npmjs.org - cache: yarn + cache: pnpm - uses: actions/cache@v3 id: install-cache with: path: node_modules/ - key: ${{ runner.os }}-install-${{ hashFiles('**/yarn.lock') }} + key: ${{ runner.os }}-install-${{ hashFiles('**/pnpm-lock.yaml') }} - if: steps.install-cache.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile --ignore-scripts - shell: bash \ No newline at end of file + run: pnpm i + shell: bash From af3e3ab0a27c44d3c068a536d36d62320084c3f6 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 18:31:31 +0800 Subject: [PATCH 16/20] feat: ci pnpm steps --- .github/actions/setup/action.yml | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 29aec353..6a300956 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -4,18 +4,29 @@ runs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + + - uses: pnpm/action-setup@v2 + name: Install pnpm with: - node-version: 16 - registry-url: https://registry.npmjs.org - cache: pnpm + 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('**/pnpm-lock.yaml') }} + 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: pnpm i - shell: bash + - name: Install dependencies + run: pnpm install From 7d242aebb5edefe206203f6793b6fa0d0ff73c72 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 18:34:59 +0800 Subject: [PATCH 17/20] feat: ci --- .github/actions/setup/action.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 6a300956..3d016442 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -3,11 +3,12 @@ runs: using: composite steps: - uses: actions/checkout@v3 + name: Checkout - - name: Install Node.js - uses: actions/setup-node@v3 - with: - node-version: 16 + - uses: actions/setup-node@v3 + name: Install Node.js + with: + node-version: 16 - uses: pnpm/action-setup@v2 name: Install pnpm From 49f91ecea5faf315d84f2db042781a7d4cfccc0f Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 18:37:07 +0800 Subject: [PATCH 18/20] feat: ci --- .github/actions/setup/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 3d016442..f439ee0e 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -30,4 +30,5 @@ runs: ${{ runner.os }}-pnpm-store- - name: Install dependencies + shell: bash run: pnpm install From 5bd5356b696d7425b9c747869c298050039a6d93 Mon Sep 17 00:00:00 2001 From: holymingo Date: Tue, 22 Aug 2023 19:06:51 +0800 Subject: [PATCH 19/20] feat: web sdk api --- packages/react/src/index.ts | 1 + packages/react/src/types.ts | 2 ++ packages/web/src/index.ts | 21 ++++++++++++++------- packages/web/src/sdk.ts | 34 ++++++++++++++++++++++++++++++++++ packages/web/src/setup.tsx | 15 +++++++++++++-- 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 packages/web/src/sdk.ts diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 09d132af..1424ca9c 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -3,3 +3,4 @@ export * from './portkey/PortkeyUISDK'; export * from './portkey/ExtraElement'; export * from './context'; export * from './webLogin'; +export * from './types'; diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index d6b2bdcf..eed49a3b 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -1,6 +1,8 @@ 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; diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts index e84fc340..ddafd118 100644 --- a/packages/web/src/index.ts +++ b/packages/web/src/index.ts @@ -1,10 +1,17 @@ +import { SDK } from './sdk'; import setup from './setup'; -export class SDK { - setup = setup; - login() { - console.log('login'); - } -} +const setupSDK = (() => { + let sdk: SDK | undefined = undefined; + return () => { + if (sdk) return sdk; + const delegate = setup(); + sdk = new SDK(delegate); + return sdk; + }; +})(); -export default new 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 index 610f6ae3..01fc2e74 100644 --- a/packages/web/src/setup.tsx +++ b/packages/web/src/setup.tsx @@ -1,9 +1,19 @@ import React, { useState } from 'react'; import { createRoot } from 'react-dom/client'; -import { WebLoginProvider } from '@aelf-web-login/react'; +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 ( - <> + ); } @@ -30,4 +40,5 @@ export default function setup() { , ); + return delegate; } From f8fd454bd037b84ccad8f1674ffc81716e98a487 Mon Sep 17 00:00:00 2001 From: holymingo Date: Mon, 28 Aug 2023 18:57:35 +0800 Subject: [PATCH 20/20] feat: test --- .../core/src/wallets/portkey/PortkeySDK.ts | 3 -- packages/core/test/utils.test.ts | 9 +++-- packages/react/jest.config.ts | 5 +++ packages/react/package.json | 1 + packages/react/src/portkey/PortkeyUISDK.ts | 33 +++++++++++-------- packages/react/src/portkey/context.tsx | 7 +--- packages/react/test/index.test.ts | 7 ++++ 7 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 packages/react/jest.config.ts create mode 100644 packages/react/test/index.test.ts diff --git a/packages/core/src/wallets/portkey/PortkeySDK.ts b/packages/core/src/wallets/portkey/PortkeySDK.ts index 9c84210c..cec3051b 100644 --- a/packages/core/src/wallets/portkey/PortkeySDK.ts +++ b/packages/core/src/wallets/portkey/PortkeySDK.ts @@ -26,7 +26,4 @@ export abstract class PortkeySDK extends LoginBase { getSignature(signInfo: string): Promise { throw new Error('Method not implemented.'); } - - abstract login(): CancelablePromise; - abstract logout(): Promise; } diff --git a/packages/core/test/utils.test.ts b/packages/core/test/utils.test.ts index 940f25f5..ef5f13a1 100644 --- a/packages/core/test/utils.test.ts +++ b/packages/core/test/utils.test.ts @@ -1,8 +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', async () => { - expect(isAElfWallet()).toEqual(false); + test('isAElfWallet', () => { + expect(isAElfWallet()).toBe(false); + }); + + test('isPortkeyApp', () => { + expect(isPortkeyApp()).toBe(false); }); }); 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/react/package.json b/packages/react/package.json index 7fbe494d..1b14bfec 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -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", diff --git a/packages/react/src/portkey/PortkeyUISDK.ts b/packages/react/src/portkey/PortkeyUISDK.ts index f97128e0..aa457ca0 100644 --- a/packages/react/src/portkey/PortkeyUISDK.ts +++ b/packages/react/src/portkey/PortkeyUISDK.ts @@ -2,6 +2,7 @@ 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`; @@ -69,10 +70,19 @@ export class PortkeyUISDK extends PortkeySDK { }); } - logout(): Promise { - localStorage.removeItem(ORIGIN_CHAIN_ID_KEY); + 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); - throw new Error('Method not implemented.'); + localStorage.removeItem(ORIGIN_CHAIN_ID_KEY); + this.loginState = 'initial'; } onFinish(didWalletInfo: DIDWalletInfo) { @@ -92,17 +102,12 @@ export class PortkeyUISDK extends PortkeySDK { } onError(error: any) { - if (this.loginState !== 'logining') { - 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, - }); - return; - } - this.loginState = 'initial'; - this._promiseHolder?.reject(error); + 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() { diff --git a/packages/react/src/portkey/context.tsx b/packages/react/src/portkey/context.tsx index 9e9b0d51..42dca821 100644 --- a/packages/react/src/portkey/context.tsx +++ b/packages/react/src/portkey/context.tsx @@ -87,12 +87,7 @@ export function PortkeySDKProvider(props: PortkeySDKProviderProps) { setIsWrongPassword(false); setPassword(''); - // const didWalletInfo: DIDWalletInfo = { - // pin: password, - // chainId: originChainId as ChainId, - // walletInfo: localWallet.didWallet.managementAccount!.wallet as any, - // accountInfo: localWallet.didWallet.accountInfo as any, - // }; + portkeySDK.onUnlock(); } catch (error) { setIsWrongPassword(true); return; 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); + }); +});