diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 00000000000..35962618ff2 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,17 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) + +## Released packages + +Currently, we release the following packages in this monorepo to npm. + +- [@masknet/base](../packages/base) +- [@masknet/typed-message](../packages/typed-message/base) +- [@masknet/typed-message-react](../packages/typed-message/react) +- [@masknet/encryption](../packages/encryption) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000000..a0f5e30d11a --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "develop", + "updateInternalDependencies": "patch", + "ignore": [ + "!(@masknet/base|@masknet/typed-message|@masknet/typed-message-react|@masknet/encryption|@masknet/config)" + ] +} diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 61463ef6980..00000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,117 +0,0 @@ -# Javascript Node CircleCI 2.0 configuration file -# -# Check https://circleci.com/docs/2.0/language-javascript/ for more details -# -version: 2.1 -executors: - mask_node: - docker: - - image: cimg/node:17.5 - working_directory: ~/repo -commands: - restore_workspace: - description: 'Restore the workspace' - steps: - - attach_workspace: - at: ~/ -jobs: - install_dependencies: - executor: mask_node - steps: - - checkout - - restore_cache: - name: Restore PNPM Package Cache - keys: - - v4-mask-cache-pnpm - - run: - name: Enable corepack - command: sudo corepack enable - - run: - name: Install Dependencies - command: pnpm install --frozen-lockfile --store-dir ~/.pnpm/ - - save_cache: - name: Save NPM Package Cache - key: v4-mask-cache-pnpm - paths: - - ~/.pnpm/ - - persist_to_workspace: - root: ~/ - paths: - - repo - build: - executor: mask_node - steps: - - restore_workspace - - run: - name: Enable corepack - command: sudo corepack enable - - run: - name: Build Mask Network - command: npx gulp build-ci - - store_artifacts: - path: MaskNetwork.base.zip - destination: /MaskNetwork.base.zip - - store_artifacts: - path: MaskNetwork.iOS.zip - destination: /MaskNetwork.iOS.zip - - store_artifacts: - path: MaskNetwork.chromium.zip - destination: /MaskNetwork.chromium.zip - - store_artifacts: - path: MaskNetwork.firefox.zip - destination: /MaskNetwork.firefox.zip - - store_artifacts: - path: MaskNetwork.gecko.zip - destination: /MaskNetwork.gecko.zip - - store_artifacts: - path: MaskNetwork.chromium-beta.zip - destination: /MaskNetwork.chromium-beta.zip - - persist_to_workspace: - root: ~/repo/ - paths: - - MaskNetwork.base.zip - - MaskNetwork.iOS.zip - - MaskNetwork.chromium.zip - - MaskNetwork.chromium-beta.zip - - MaskNetwork.firefox.zip - - MaskNetwork.gecko.zip - publish-github-release: - docker: - - image: cibuilds/github:0.10 - steps: - - restore_workspace - - run: - name: 'Publish Release on GitHub' - command: | - set -o nounset - mkdir ~/repo/release - mv ~/*.zip ~/repo/release/ - cd ~/repo/release - ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -b "✔ No breaking changes. / ⚠ Has breaking changes! - - 🆕 New Feature - - 🔐 Security - - 🎨 UI Improvements - - 🐛 Bug Fixes - - 👩‍💻 Miscellaneous" -replace -draft $(git describe HEAD) ~/repo/release - # -b BODY \ # Set text describing the contents of the release - # -delete \ # Delete release and its git tag in advance if it exists (same as -recreate) - # -n TITLE \ # Set release title -workflows: - version: 2 - main: - jobs: - - install_dependencies - - build: - requires: - - install_dependencies - - publish-github-release: - requires: - - build - filters: - branches: - only: released diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 40bdbc3261e..00000000000 --- a/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -root = true - -[*] -indent_size = 4 -charset = utf-8 -end_of_line = lf -trim_trailing_whitespace = true -insert_final_newline = true -indent_style = space - -[{.*rc,ts*.json,package.json}] -indent_size = 2 - -[*.{yaml,yml,md}] -indent_size = 2 diff --git a/.env/dev-preference.example b/.env/dev-preference.example new file mode 100644 index 00000000000..46cc0346fef --- /dev/null +++ b/.env/dev-preference.example @@ -0,0 +1,107 @@ +# Copy and rename this file to dev-preference +# This dot file will NOT be used in CI or production build. + +### Experimental CSP + +; csp=false +# (default) Not enabling strict CSP. + +; csp=true +# Enable strict CSP. + +### SourceMap + +; sourceMap=true +# (default) Uses suggested sourceMap in the current build set. + +; sourceMap=false +# Disables the sourceMap. + +; sourceMap=eval +; sourceMap=eval-cheap-source-map +; sourceMap=eval-cheap-module-source-map +; sourceMap=eval-source-map +; sourceMap=cheap-source-map +; sourceMap=cheap-module-source-map +; sourceMap=source-map +; sourceMap=inline-cheap-source-map +; sourceMap=inline-cheap-module-source-map +; sourceMap=inline-source-map +# sourceMap=... +# Any valid value listed in https://webpack.js.org/configuration/devtool/, but it might not work in our environment. + +### SourceMap hide frameworks + +; sourceMapHideFrameworks=true +# (default) Hide frameworks in sourceMap. + +; sourceMapHideFrameworks=false +# Show frameworks in sourceMap. + +### Preferred Manifest Version + +; manifest=3 +# (default) Use Chromium Manifest V3 as default development target. + +; manifest=2 +# Use Chromium Manifest V2 as default development target. + +; manifest=chromium-mv2 +; manifest=chromium-beta-mv3 +; manifest=chromium-mv3 +; manifest=firefox-mv2 +; manifest=firefox-mv3 +; manifest=safari-mv3 + +### Hot Module Reload + +; hmr=true +# (default) Enable Hot Module Reload in development mode. + +; hmr=false +# Disable Hot Module Reload in development mode. + +### Devtools integration + +; devtools=true +# (default) Enable Devtools integration in development mode. + +; devtools=false +# Disable Devtools integration in development mode. + +### React devtools default editor + +; devtoolsEditorURI=vscode://file/{path}:{line} +; devtoolsEditorURI=mvim://open?url=file://{path}&line={line} +; devtoolsEditorURI=raycast://script-commands/your-custom-script?arguments={path}&arguments={line} +# (default) VSCode + +# devtoolsEditorURI=... +# Any URI that can open the editor you used. + +### Experimental React compiler + +; reactCompiler=false +# (default) Not enabling react compiler. + +; reactCompiler=true +# Enable react compiler. + +; reactCompiler=infer +; reactCompiler=annotation +; reactCompiler=all +# Enable react compiler with specific mode. + +### Experimental LavaMoat + +; lavamoat=false +# (default) Not enabling LavaMoat. + +; lavamoat=true +# Enable LavaMoat. + +### Build Environment Variables + +; FIREFLY_X_CLIENT_ID= +; FIREFLY_X_CLIENT_SECRET= +; PRIVY_APP_ID= diff --git a/.env/e2e-template b/.env/e2e-template deleted file mode 100644 index 94356e0475d..00000000000 --- a/.env/e2e-template +++ /dev/null @@ -1,58 +0,0 @@ -# THIS FILE ONLY FOR LISTING ALL AVAILABLE E2E CONFIGURATIONS -# PLEASE CREATE CORRESPONDING e2e-[ENV] -# UNDER THE CURRENT DIR TO CUSTOMIZE E2E BEHAVIOR FOR DIFFERENT ENV -# DO NOT RUN ANY E2E TEST WITHOUT THESE VARIABLES SET PROPERLY - -# Specify network (twitter.com or facebook.com) -E2E_NETWORK_ID= - -# Specify the user agent of the puppteer browser -E2E_USER_AGENT= - -# Specify the extension id -E2E_EXT_ID=jkoeaghipilijlahjplgbfiocjhldnap - -# Specify the extension dir which will be tested -# dist/ if test against development build -# build/ if test against production build -E2E_EXT_DIR= - -# Specify the user data dir which helps to prevent frequently -# login thus ban by SNS provider -# -# more about --user-data-dir: -# - https://peter.sh/experiments/chromium-command-line-switches/#user-data-dir -E2E_ALICE_USER_DATA_DIR=./pptr-alice -E2E_BOB_USER_DATA_DIR=./pptr-bob - -# Specify alice's twitter account -E2E_ALICE_TWITTER_ID= -E2E_ALICE_TWITTER_USERNAME= -E2E_ALICE_TWITTER_PASSWORD= -E2E_ALICE_TWITTER_EMAIL= -E2E_ALICE_TWITTER_EMAIL_PASSWORD= -E2E_ALICE_TWITTER_PHONE= - -# Specify bob's twitter account (optional) -E2E_BOB_TWITTER_ID= -E2E_BOB_TWITTER_USERNAME= -E2E_BOB_TWITTER_PASSWORD= -E2E_BOB_TWITTER_EMAIL= -E2E_BOB_TWITTER_EMAIL_PASSWORD= -E2E_BOB_TWITTER_PHONE= - -# Specify primary facebook account -E2E_ALICE_FACEBOOK_ID= -E2E_ALICE_FACEBOOK_USERNAME= -E2E_ALICE_FACEBOOK_PASSWORD= -E2E_ALICE_FACEBOOK_EMAIL= -E2E_ALICE_FACEBOOK_EMAIL_PASSWORD= -E2E_ALICE_FACEBOOK_PHONE= - -# Specify vice facebook account (optional) -E2E_BOB_FACEBOOK_ID= -E2E_BOB_FACEBOOK_USERNAME= -E2E_BOB_FACEBOOK_PASSWORD= -E2E_BOB_FACEBOOK_EMAIL= -E2E_BOB_FACEBOOK_EMAIL_PASSWORD= -E2E_BOB_FACEBOOK_PHONE= diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index dcb2b1518d0..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,15 +0,0 @@ -*.d.ts -*.test.tsx -build/ -dist -gun.js -e2e -package.json -packages/contracts -packages/storybook-shared -packages/netlify/storybook-static -packages/netlify/sites -public/ -scripts/ -packages/dashboard/storybook-static/ -packages/theme/storybook-static/ diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 38b157bf9e1..00000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "module" - }, - "env": { - "node": true - }, - "plugins": ["unused-imports"], - "rules": { - "constructor-super": "error", - "dot-notation": "error", - "eqeqeq": "error", - "object-shorthand": "warn", - "no-var": "error", - "no-bitwise": "error", - "no-debugger": "error", - "no-eval": "error", - "no-extra-bind": "error", - "no-fallthrough": "error", - "no-new-wrappers": "error", - "no-plusplus": "error", - "valid-typeof": "error", - "no-loss-of-precision": "error", - "no-unsafe-optional-chaining": "error", - "no-unsafe-negation": "error", - "no-unsafe-finally": "error", - "no-irregular-whitespace": "error", - "no-restricted-globals": ["error", "event", "name", "length", "closed"], - "no-restricted-imports": [ - "error", - { - "paths": [ - { "name": "lodash", "message": "Please use lodash-unified instead." }, - { "name": "lodash-es", "message": "Please use lodash-unified instead." }, - { "name": "date-fns", "message": "Please use date-fns/{submodule} instead." }, - { "name": "date-fns/esm", "message": "Please use date-fns/{submodule} instead." }, - { "name": "@masknet/typed-message/base", "message": "Please use @masknet/typed-message instead." }, - { - "name": "@dimensiondev/holoflows-kit/es", - "message": "Please use @dimensiondev/holoflows-kit instead." - } - ] - } - ], - "no-return-await": "error", - "no-sparse-arrays": "error", - "no-template-curly-in-string": "error", - "prefer-const": "warn", - "use-isnan": "error", - "unused-imports/no-unused-imports-ts": "error" - } -} diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..11a74a748b1 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# Prettier +17a48c22dace1efc4bb21189f3eeda8363314b31 +b515a343aa66943b4736ea197f8cb7152a0cc126 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..ed3eb4dd930 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +packages/icons/icon-generated-as-jsx.js linguist-generated=true +packages/icons/icon-generated-as-url.js linguist-generated=true +*.po linguist-generated=true +en-US.json linguist-generated=true +ja-JP.json linguist-generated=true +zh-CN.json linguist-generated=true +zh-TW.json linguist-generated=true +ko-KR.json linguist-generated=true diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 81e4acd26aa..d7882a058d6 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -41,5 +41,3 @@ assignees: Jack-Works, jk234ert - [ ] Latest Chrome (stable channel) - [ ] Latest Firefox (stable channel) -- [ ] Android 11 -- [ ] iOS 14 diff --git a/.github/ISSUE_TEMPLATE/evm.md b/.github/ISSUE_TEMPLATE/evm.md index e7298aaae56..22abde3efdf 100644 --- a/.github/ISSUE_TEMPLATE/evm.md +++ b/.github/ISSUE_TEMPLATE/evm.md @@ -6,7 +6,7 @@ labels: '' assignees: DimensionDev/dev-smartcontract --- -Request to depoly contracts on . +Request to deploy contracts on . @@ -17,8 +17,7 @@ Request to depoly contracts on . | Name | \- | | ChainId | \- | | Website | \- | -| RPC Endponit | \- | - +| RPC Endpoint | \- | ## Checklist diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 9190ab74395..98a719a3aed 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -11,7 +11,7 @@ When reporting an issue, where possible, please provide at least: - The project and commit version the issue was identified at - A proof of concept (plain-text; no binaries) - Steps to reproduce -- Your recommended remediation(s), if any. +- Your recommended remediations, if any. ## `security.txt` diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml new file mode 100644 index 00000000000..f291e7c0c08 --- /dev/null +++ b/.github/workflows/changeset.yml @@ -0,0 +1,37 @@ +name: Changeset + +on: + push: + branches: + - develop + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: Changeset + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + filter: blob:none + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: ".node-version" + cache: "pnpm" + - name: Authenticate NPM + uses: DimensionDev/github-token-action@latest + with: + registry: true + - run: git config --global url."https://github.com/".insteadOf git@github.com + - run: pnpm install + - uses: changesets/action@v1 + with: + publish: pnpm exec gulp changeset-release + commit: "chore: changeset release" + title: "chore: changeset release" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index b1ab3043611..c447e884cb5 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -2,74 +2,108 @@ name: Compile on: push: - branches: [master, develop*, released] + tags: ["v*"] + branches: [master, develop, released, hotfix/*, release/*] pull_request: - branches: [master, develop*, released] + branches: [master, develop, released, hotfix/*, release/*] + merge_group: + types: [checks_requested] + +permissions: + contents: write + pull-requests: read + packages: read -# Cancels all previous workflow runs for pull requests that have not completed. concurrency: - # The concurrency group contains the workflow name and the branch name for - # pull requests or the commit hash for any other events. group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} cancel-in-progress: true jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest env: WEB3_CONSTANTS_RPC: ${{ secrets.WEB3_CONSTANTS_RPC }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + MASK_SENTRY_DSN: ${{ secrets.MASK_SENTRY_DSN }} + MASK_SENTRY: ${{ secrets.MASK_SENTRY }} + MASK_MIXPANEL: ${{ secrets.MASK_MIXPANEL }} + PRIVY_APP_ID: ${{ secrets.PRIVY_APP_ID }} + FIREFLY_X_CLIENT_ID: ${{ secrets.FIREFLY_X_CLIENT_ID }} + FIREFLY_X_CLIENT_SECRET: ${{ secrets.FIREFLY_X_CLIENT_SECRET }} steps: - name: Get cache date id: get-date - run: echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" + run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_STATE shell: bash - - uses: actions/checkout@v2 + # note: required by sentry + - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - - uses: pnpm/action-setup@v2.2.1 - - uses: actions/setup-node@v2 + filter: blob:none + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 with: - node-version: '17' + node-version-file: ".node-version" cache: 'pnpm' - - name: Restore Webpack cache - uses: actions/cache@v2 + - name: Authenticate NPM + uses: DimensionDev/github-token-action@latest with: - path: packages/mask/node_modules/.cache/ - key: ${{ runner.os }}-extension-${{ hashFiles('pnpm-lock.yaml') }}-${{ steps.get-date.outputs.date }} - # Not fallback to different dependencies. Webpack seems like have bug. - # An example caused by the webpack cache bug: https://github.com/facebook/react/issues/21587 - restore-keys: ${{ runner.os }}-extension-${{ hashFiles('pnpm-lock.yaml') }} + registry: true + - run: git config --global url."https://github.com/".insteadOf git@github.com - run: pnpm install - - run: npx gulp build-ci - - name: Upload `MaskNetwork.base.zip` - uses: actions/upload-artifact@v2 - with: - name: MaskNetwork.base.zip - path: MaskNetwork.base.zip - - name: Upload `MaskNetwork.iOS.zip` - uses: actions/upload-artifact@v2 + - run: pnpm exec gulp build-ci + # See https://github.com/getsentry/action-release/issues/187 + - name: Change git configuration + shell: bash + run: | + if [ -n "$(git config --get extensions.worktreeconfig)" ]; then + git config --unset-all extensions.worktreeconfig + fi + - name: Create Sentry release + uses: getsentry/action-release@v1 + if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/released' + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: mask-network + SENTRY_PROJECT: mask-network with: - name: MaskNetwork.iOS.zip - path: MaskNetwork.iOS.zip - - name: Upload `MaskNetwork.chromium.zip` - uses: actions/upload-artifact@v2 + environment: production + sourcemaps: ./build + version_prefix: mask- + ignore_missing: true + - name: Upload `MaskNetwork.chromium-mv2.zip` + uses: actions/upload-artifact@v4 with: - name: MaskNetwork.chromium.zip - path: MaskNetwork.chromium.zip + name: MaskNetwork.chromium-mv2.zip + path: masknetwork.chromium-mv2.zip + if-no-files-found: error - name: Upload `MaskNetwork.chromium-beta.zip` - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: MaskNetwork.chromium-beta.zip - path: MaskNetwork.chromium-beta.zip - - name: Upload `MaskNetwork.firefox.zip` - uses: actions/upload-artifact@v2 + path: masknetwork.chromium-beta.zip + if-no-files-found: error + - name: Upload `MaskNetwork.chromium-mv3.zip` + uses: actions/upload-artifact@v4 + with: + name: MaskNetwork.chromium-mv3.zip + path: masknetwork.chromium-mv3.zip + if-no-files-found: error + - name: Upload `MaskNetwork.firefox-mv2.zip` + uses: actions/upload-artifact@v4 + with: + name: MaskNetwork.firefox-mv2.zip + path: masknetwork.firefox-mv2.zip + if-no-files-found: error + - name: Upload `MaskNetwork.firefox-mv3.zip` + uses: actions/upload-artifact@v4 with: - name: MaskNetwork.firefox.zip - path: MaskNetwork.firefox.zip - - name: Upload `MaskNetwork.gecko.zip` - uses: actions/upload-artifact@v2 + name: MaskNetwork.firefox-mv3.zip + path: masknetwork.firefox-mv3.zip + if-no-files-found: error + - uses: "marvinpinto/action-automatic-releases@latest" + if: startsWith(github.ref, 'refs/tags/v') with: - name: MaskNetwork.gecko.zip - path: MaskNetwork.gecko.zip + repo_token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: false + files: | + *.zip diff --git a/.github/workflows/jira-issue-key-checking.yml b/.github/workflows/jira-issue-key-checking.yml new file mode 100644 index 00000000000..ad21db8f943 --- /dev/null +++ b/.github/workflows/jira-issue-key-checking.yml @@ -0,0 +1,23 @@ +name: "Check Jira Issue Key" + +on: + pull_request: + types: + - opened + - edited + - synchronize + merge_group: + types: [checks_requested] + +permissions: + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: DimensionDev/jira-issue-key-checker@master + if: ${{ github.event.pull_request }} + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + jira-prefix: 'MF|FW' diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index f8c9a708783..92b7913cc64 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -2,88 +2,129 @@ name: Linters and tests on: push: - branches: [master, develop*, released] + branches: [master, develop, released, hotfix/*, release/*] pull_request: - branches: [master, develop*, released] + branches: [master, develop, released, hotfix/*, release/*] + merge_group: + types: [checks_requested] + +permissions: + contents: read + packages: read -# Cancels all previous workflow runs for pull requests that have not completed. concurrency: - # The concurrency group contains the workflow name and the branch name for - # pull requests or the commit hash for any other events. group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} cancel-in-progress: true jobs: - prettier: - runs-on: ubuntu-20.04 + linter: + runs-on: ubuntu-latest + permissions: + packages: read + contents: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} - - uses: actions/setup-node@v2 - - run: npx prettier@2.7.1 --check . - markdownlint: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 + ref: ${{ github.event.pull_request.head.ref }} + token: ${{ secrets.GGITHUB_TOKEN }} + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 with: - ref: ${{ github.event.pull_request.head.sha }} - - uses: actions/setup-node@v2 - - run: npx markdownlint-cli . - editorconfig: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 + node-version-file: ".node-version" + cache: "pnpm" + - name: Authenticate NPM + uses: DimensionDev/github-token-action@latest with: - ref: ${{ github.event.pull_request.head.sha }} - - uses: DimensionDev/setup-editorconfig-action@latest - - run: editorconfig-checker - anti-trojan-source: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 + registry: true + - run: pnpm install + - run: pnpx markdownlint-cli --fix . + - run: pnpm exec gulp codegen + - run: pnpm run lingui:extract + - run: pnpm run lingui:compile + - run: pnpm exec gulp lint-package-json + - run: pnpm exec gulp fix-plugins-tsconfig + - run: pnpx prettier@3.6.2 --write . + - uses: EndBug/add-and-commit@v9 with: - ref: ${{ github.event.pull_request.head.sha }} - - uses: actions/setup-node@v2 - - run: npx anti-trojan-source --files='packages/**/src/**/*.{ts,tsx,js}' - type-check-and-jest: - runs-on: ubuntu-20.04 + message: 'fix: linter' + type-check: + runs-on: ubuntu-latest steps: - - name: Get cache date - id: get-date - run: echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" - shell: bash - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: ".node-version" + cache: "pnpm" + - name: Authenticate NPM + uses: DimensionDev/github-token-action@latest with: - ref: ${{ github.event.pull_request.head.sha }} - - uses: pnpm/action-setup@v2.2.1 - - uses: actions/setup-node@v2 + registry: true + - run: git config --global url."https://github.com/".insteadOf git@github.com + - run: pnpm install + - run: pnpm exec gulp codegen + - run: pnpm exec gulp typescript + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 with: - node-version: "17" + node-version-file: ".node-version" cache: "pnpm" + - name: Authenticate NPM + uses: DimensionDev/github-token-action@latest + with: + registry: true + - run: git config --global url."https://github.com/".insteadOf git@github.com - run: pnpm install - - run: npx gulp codegen - - run: npx gulp polyfill - - run: node --experimental-vm-modules ./node_modules/jest/bin/jest.js + - run: pnpm exec gulp codegen + - run: pnpm exec gulp polyfill + - run: pnpm run test eslint: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest + permissions: + packages: read + contents: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha }} - - uses: pnpm/action-setup@v2.2.1 - - uses: actions/setup-node@v2 + ref: ${{ github.event.pull_request.head.ref }} + token: ${{ secrets.GGITHUB_TOKEN }} + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 with: - node-version: "17" + node-version-file: ".node-version" cache: "pnpm" + - name: Authenticate NPM + uses: DimensionDev/github-token-action@latest + with: + registry: true + - name: Get cache date + id: get-date + run: echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_STATE + shell: bash + - name: Restore ESLint cache + uses: actions/cache@v4 + with: + path: .eslintcache + key: linter-v2-${{ steps.get-date.outputs.date }} + restore-keys: linter-v2- + - run: git config --global url."https://github.com/".insteadOf git@github.com - run: pnpm install + - run: pnpm exec gulp codegen - name: Run Eslint run: | - # report to stdio and to file, it's cached, the second run should be fast + export NODE_OPTIONS="--max-old-space-size=8192" + # report to stdio and to a file, it's cached so the second run should be fast pnpm run lint:ci pnpm run lint:ci-report + - uses: EndBug/add-and-commit@v9 + with: + message: 'fix: eslint' - name: Upload eslint report - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: eslint path: reports/junit diff --git a/.github/workflows/milestone.yml b/.github/workflows/milestone.yml new file mode 100644 index 00000000000..1451c4ae797 --- /dev/null +++ b/.github/workflows/milestone.yml @@ -0,0 +1,62 @@ +name: "Check Milestone" + +on: + pull_request: + types: + - opened + - edited + - synchronize + - milestoned + - demilestoned + branches: + - 'develop' + - 'release/*' + - 'hotfix/*' + merge_group: + types: [checks_requested] + +permissions: + contents: read + +jobs: + check: + # disable + if: ${{ false }} + runs-on: ubuntu-latest + steps: + - name: Check Milestone + if: "(github.event.pull_request && github.event.pull_request.milestone == null) && github.event.pull_request.title != 'docs(i18n): sync i18n files from Crowdin'" + run: | + echo "Please set a milestone." + exit 1 + + - name: Check target branch of develop + if: ${{ github.event.pull_request && github.base_ref == 'develop' && github.event.pull_request.milestone != null }} # merge to develop + run: | + if [[ ${{ github.event.pull_request.milestone.title }} =~ ^[0-9]+.[0-9]+.0$ ]] + then + echo "Well Done" + else + echo "Don't patch on the develop branch." + exit 1 + fi + + - name: Check target branch of release/* + if: ${{ github.event.pull_request && startsWith(github.base_ref, 'release/') }} # merge to release/* + run: | + if [[ ${{ github.event.pull_request.milestone.title }} =~ ^[0-9]+.[0-9]+.0$ ]] + then + echo "Well Done" + else + echo "Don't patch on a pre-release branch." + fi + + - name: Check target branch of hotfix/* + if: ${{ github.event.pull_request && startsWith(github.base_ref, 'hotfix/') }} # merge to hotfix/* + run: | + if [[ ${{ github.event.pull_request.milestone.title }} =~ ^[0-9]+.[0-9]+.0$ ]] + then + echo "A hotfix branch only allows patch requests." + else + echo "Well Done" + fi diff --git a/.github/workflows/netlify.yml b/.github/workflows/netlify.yml deleted file mode 100644 index f044a9dbd17..00000000000 --- a/.github/workflows/netlify.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Build - -on: - push: - branches: [master, develop*, released] - pull_request: - branches: [master, develop*, released] - -# Cancels all previous workflow runs for pull requests that have not completed. -concurrency: - # The concurrency group contains the workflow name and the branch name for - # pull requests or the commit hash for any other events. - group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} - cancel-in-progress: true - -jobs: - netlify: - runs-on: ubuntu-20.04 - env: - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - steps: - - name: Get cache date - id: get-date - run: echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" - shell: bash - - uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - uses: pnpm/action-setup@v2.2.1 - - uses: actions/setup-node@v2 - with: - node-version: '16' - cache: 'pnpm' - - name: Restore Webpack cache - uses: actions/cache@v2 - with: - path: | - packages/dashboard/node_modules/.cache/ - packages/theme/node_modules/.cache/ - key: ${{ runner.os }}-netlify-${{ hashFiles('pnpm-lock.yaml') }}-${{ steps.get-date.outputs.date }} - # Not fallback to different dependencies. Webpack seems like have bug. - # An example caused by the webpack cache bug: https://github.com/facebook/react/issues/21587 - restore-keys: ${{ runner.os }}-netlify-${{ hashFiles('pnpm-lock.yaml') }} - - run: pnpm install - - run: npx gulp build-ci-netlify - - name: Deploy to Netlify - uses: nwtgck/actions-netlify@v1.2 - with: - publish-dir: './packages/netlify/' - production-branch: develop - github-token: ${{ secrets.GITHUB_TOKEN }} - deploy-message: "Deploy from GitHub Actions" - enable-commit-comment: false - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 1 diff --git a/.github/workflows/spell-checking.yml b/.github/workflows/spell-checking.yml index de83baf8ff9..6b587f12dc3 100644 --- a/.github/workflows/spell-checking.yml +++ b/.github/workflows/spell-checking.yml @@ -2,22 +2,27 @@ name: Check Spell on: pull_request: - branches: [develop*] + branches: [master, develop, released, hotfix/*, release/*] + merge_group: + types: [checks_requested] + +permissions: + contents: read -# Cancels all previous workflow runs for pull requests that have not completed. concurrency: - # The concurrency group contains the workflow name and the branch name for - # pull requests or the commit hash for any other events. group: ${{ github.workflow }}-${{ github.head_ref }} cancel-in-progress: true jobs: check-spell: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: ".node-version" - name: Check Spell + if: ${{ github.event.pull_request }} run: | git fetch origin ${{ github.event.pull_request.base.ref }} --depth=1 - git diff --name-only origin/${{ github.event.pull_request.base.ref }} | xargs npx cspell lint --no-must-find-files + git diff --name-only origin/${{ github.event.pull_request.base.ref }} | xargs npx cspell lint --no-must-find-files --no-progress diff --git a/.gitignore b/.gitignore index ec3f16f1daf..1429728761c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # generated files -i18n_generated.js -i18n_generated.d.ts -i18n_generated.d.ts.map +i18n_generated* +.swc +.env/dev-preference # VSCode personal settings .vscode/launch.json @@ -10,6 +10,8 @@ i18n_generated.d.ts.map # JetBrain personal settings .idea +.vim + # testing /reports /junit.xml @@ -23,36 +25,13 @@ i18n_generated.d.ts.map dist build /build-* -storybook-static -packages/netlify/sites/ /MaskNetwork.*.zip compilation-stats.json -# Environment files -.env.local -.env.development.local -.env.test.local -.env.production.local - # Block-chain contract files /contracts -# E2E tests -/.env/e2e-test -/.env/e2e-development -/.env/e2e-production -/.pptr-alice -/.pptr-bob -/screenshots -/.env -/.pptr-* - -# Temp profiles -.firefox -.chrome - # Following content is copied from https://github.com/github/gitignore/blob/master/Node.gitignore -# Logs logs *.log npm-debug.log* @@ -95,9 +74,6 @@ build/Release node_modules/ jspm_packages/ -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - # TypeScript cache *.tsbuildinfo @@ -119,17 +95,6 @@ web_modules/ # Output of 'npm pack' *.tgz -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - # Next.js build output .next out @@ -144,31 +109,6 @@ dist # https://nextjs.org/blog/next-9-1#public-directory-support # public -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* - # Rush temporary files common/deploy/ common/temp/ @@ -181,3 +121,5 @@ common/autoinstallers/*/.npmrc # Disallow other package manager lock-file /package-lock.json /yarn.lock +quick-lint-js.config +.aider* diff --git a/.husky/commit-msg b/.husky/commit-msg index 4f15872e334..ef9f0fa958b 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname $0)/_/husky.sh" -npx --no-install commitlint --edit $1 +pnpm exec --no-install commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit index 8c404449e3a..5ee7abd87c6 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname $0)/_/husky.sh" - -npx lint-staged +pnpm exec lint-staged diff --git a/.i18n-codegen.json b/.i18n-codegen.json deleted file mode 100644 index f51efba6f57..00000000000 --- a/.i18n-codegen.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "$schema": "./node_modules/@magic-works/i18n-codegen/schema.json", - "version": 1, - "list": [ - { - "input": "./packages/mask/shared-ui/locales/en-US.json", - "output": "./packages/mask/shared-ui/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useMaskI18N", - "namespace": "mask", - "trans": "MaskTrans" - } - }, - { - "input": "./packages/mask/src/social-network-adaptor/twitter.com/locales/en-US.json", - "output": "./packages/mask/src/social-network-adaptor/twitter.com/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useDO_NOT_USE", - "namespace": "DO_NOT_USE", - "trans": "DO_NOT_USE_TRANSLATOR" - } - }, - { - "input": "./packages/shared/src/locales/en-US.json", - "output": "./packages/shared/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useSharedI18N", - "namespace": "shared", - "trans": "SharedTrans" - } - }, - { - "input": "./packages/shared-base-ui/src/locales/en-US.json", - "output": "./packages/shared-base-ui/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useSharedBaseI18N", - "namespace": "shareBase", - "trans": "SharedBaseTrans" - } - }, - { - "input": "./packages/dashboard/src/locales/en-US.json", - "output": "./packages/dashboard/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useDashboardI18N", - "namespace": "dashboard", - "trans": "DashboardTrans" - } - }, - { - "input": "./packages/plugins/example/src/locales/en-US.json", - "output": "./packages/plugins/example/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "io.mask.example", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/Debugger/src/locales/en-US.json", - "output": "./packages/plugins/Debugger/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "io.mask.debugger", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/Wallet/src/locales/en-US.json", - "output": "./packages/plugins/Wallet/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.wallet", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/Flow/src/locales/en-US.json", - "output": "./packages/plugins/Flow/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.mask.flow", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/FileService/src/locales/en-US.json", - "output": "./packages/plugins/FileService/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.fileservice", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/ScamSniffer/src/locales/en-US.json", - "output": "./packages/plugins/ScamSniffer/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "io.scamsniffer.mask-plugin", - "trans": "Translate", - "sourceMap": "inline" - } - }, - { - "input": "./packages/plugins/CyberConnect/src/locales/en-US.json", - "output": "./packages/plugins/CyberConnect/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.cyberconnect", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/RSS3/src/locales/en-US.json", - "output": "./packages/plugins/RSS3/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "bio.rss3", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/DAO/src/locales/en-US.json", - "output": "./packages/plugins/DAO/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "money.juicebox", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/EVM/src/locales/en-US.json", - "output": "./packages/plugins/EVM/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.mask.evm", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/Solana/src/locales/en-US.json", - "output": "./packages/plugins/Solana/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.solana", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/NextID/locales/en-US.json", - "output": "./packages/mask/src/plugins/NextID/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.mask.next_id", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/template/src/locales/en-US.json", - "output": "./packages/plugins/template/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "__template__", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/GoPlusSecurity/src/locales/en-US.json", - "output": "./packages/plugins/GoPlusSecurity/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "io.gopluslabs.security", - "trans": "Translate" - } - }, - { - "input": "./packages/plugins/CrossChainBridge/src/locales/en-US.json", - "output": "./packages/plugins/CrossChainBridge/src/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "io.mask.cross-chain-bridge", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/RedPacket/locales/en-US.json", - "output": "./packages/mask/src/plugins/RedPacket/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.red_packet", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/Tips/locales/en-US.json", - "output": "./packages/mask/src/plugins/Tips/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.tip", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/Avatar/locales/en-US.json", - "output": "./packages/mask/src/plugins/Avatar/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.avatar", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/Trader/locales/en-US.json", - "output": "./packages/mask/src/plugins/Trader/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.trader", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/Gitcoin/locales/en-US.json", - "output": "./packages/mask/src/plugins/Gitcoin/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "co.gitcoin", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/Referral/locales/en-US.json", - "output": "./packages/mask/src/plugins/Referral/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.referral", - "trans": "Translate", - "sourceMap": "inline" - } - }, - { - "input": "./packages/mask/src/plugins/FindTruman/locales/en-US.json", - "output": "./packages/mask/src/plugins/FindTruman/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "org.findtruman", - "trans": "Translate" - } - }, - { - "input": "./packages/mask/src/plugins/MaskBox/locales/en-US.json", - "output": "./packages/mask/src/plugins/MaskBox/locales/i18n_generated", - "parser": { "type": "i18next", "contextSeparator": "$", "pluralSeparator": "_" }, - "generator": { - "type": "i18next/react-hooks", - "hooks": "useI18N", - "namespace": "com.maskbook.box", - "trans": "Translate" - } - } - ] -} diff --git a/.ignore b/.ignore new file mode 100644 index 00000000000..c98d244df8c --- /dev/null +++ b/.ignore @@ -0,0 +1,3 @@ +# Ignores for rg or ag +patches/ +**/locale/*.{po,json} diff --git a/.lintstagedrc.mjs b/.lintstagedrc.mjs deleted file mode 100644 index 50ca648f595..00000000000 --- a/.lintstagedrc.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - '*': 'prettier --write --ignore-unknown', - 'packages/**/*.{ts,tsx,js,jsx}': 'eslint -c packages/.eslintrc.json --fix', - 'packages/web3-constants/**/*': () => 'pnpm --filter ./packages/web3-constants start', - 'cspell.json': () => 'gulp reorder-spellcheck', -} diff --git a/.markdownlintignore b/.markdownlintignore index 3c3629e647f..0e0e791d2fa 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -1 +1,2 @@ node_modules +CHANGELOG.md \ No newline at end of file diff --git a/.node-version b/.node-version index b26a23938ad..4c8f24d74e1 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -v17.9.1 +v24.7.0 diff --git a/.npmrc b/.npmrc index 7ff61b49352..4dab0913055 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1 @@ -@dimensiondev:registry=https://npm.dimension.im/ -strict-peer-dependencies=false +@dimensiondev:registry=https://npm.pkg.github.com/ diff --git a/.npmrc.pages b/.npmrc.pages new file mode 100644 index 00000000000..16182d43237 --- /dev/null +++ b/.npmrc.pages @@ -0,0 +1,3 @@ +@dimensiondev:registry=https://npm.pkg.github.com/ +resolution-mode=time-based +//npm.pkg.github.com/:_authToken=${NPM_TOKEN} diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs index fe4337139e1..ece6548aa0f 100644 --- a/.pnpmfile.cjs +++ b/.pnpmfile.cjs @@ -1,37 +1,20 @@ -// !!! There is some relative path installation source in the dependency tree, -// !!! but if we do not allow those packages to run install scripts anyway, it might be safe. -// !!! If we can resolve 'link:../empty' to something like 'workspaceRoot:/projects/empty', it will be safe to install. -/** @type {Map} */ -// @ts-expect-error -const approvedList = new Map([ - // opensea-js https://github.com/ProjectOpenSea/opensea-js/issues/407 - [ - 'ethereumjs-abi', - [ - 'git+https://github.com/ProjectWyvern/ethereumjs-abi.git', - 'git+https://github.com/ethereumjs/ethereumjs-abi.git', - 'https://github.com/ProjectWyvern/ethereumjs-abi.git', - ], - ], - [ - 'wyvern-js', - ['git+https://github.com/ProjectOpenSea/wyvern-js.git#v3.2.1', 'github:ProjectOpenSea/wyvern-js#semver:^3.2.1'], - ], - ['wyvern-schemas', 'git+https://github.com/ProjectOpenSea/wyvern-schemas.git#v0.13.1'], - /* cspell:disable-next-line */ - ['async-eventemitter', 'github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c'], - // opensea-js (v1), (and more, run `pnpm -r why web3@0.20.7`) -> web3 - ['bignumber.js', 'git+https://github.com/frozeman/bignumber.js-nolookahead.git'], +// !!! 1. Be responsible. +// !!! 2. Open a new issue to the library author. +// !!! 3. Add a pnpm/resolution in package.json if the package specifier does not include git hash to pin the version. - // https://github.com/i18next/i18next-translation-parser/issues/11 - // @magic-works/i18n-codegen -> i18next-translation-parser - /* cspell:disable-next-line */ - ['html-parse-stringify2', 'github:locize/html-parse-stringify2'], +/* cspell:disable */ +/** @type {Map} */ +const approvedList = new Map() - // ipfs https://github.com/ipfs/js-ipfs-utils/issues/158 - ['node-fetch', 'https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz'], -]) +approvedList.set('@types/react', ['npm:types-react@beta']) +approvedList.set('@types/react-dom', ['npm:types-react-dom@beta']) +// glob -> jackspeak -> @isaacs/cliui -> ... +approvedList.set('string-width-cjs', 'npm:string-width@^4.2.0') +approvedList.set('strip-ansi-cjs', 'npm:strip-ansi@^6.0.1') +approvedList.set('wrap-ansi-cjs', ['npm:wrap-ansi@^6.0.1', 'npm:wrap-ansi@^7.0.0']) + +approvedList.set('cbw-sdk', ['npm:@coinbase/wallet-sdk@3.9.3']) /** * @param {string} parentPackage The current resolving parentPackage * @param {string} dependedPackage The package it depends on @@ -44,39 +27,39 @@ function assertInstallationSourceValid(parentPackage, dependedPackage, installat if (Array.isArray(source) && source.indexOf(installationSource) !== -1) return } - if (dependedPackage === 'lodash-es' && installationSource.startsWith('npm:lodash@^4')) return - - // !!! Relative path - if (installationSource === 'link:../empty' || installationSource === 'link:..\\empty') return - if (installationSource === '../empty' || installationSource === '..\\empty') return + if (dependedPackage === '@typescript/lib-dom' && installationSource.startsWith('npm:@types/web@^')) return throw new Error( `Unapproved dependency source: Package: ${dependedPackage} Source: ${installationSource} - Declared by: ${parentPackage}`, + Declared by: ${parentPackage} + + If you want to approve this new unusual dependency, please edit .pnpmfile.cjs.`, ) } -function validatePackage({ dependencies, devDependencies, optionalDependencies, peerDependencies, name }) { +/* cspell:enable */ + +function validatePackage({ dependencies, optionalDependencies, peerDependencies, name, exports }) { + if ( + exports && + !name.startsWith('@dimensiondev') && + !name.startsWith('@masknet') && + JSON.stringify(exports).includes('mask-src') + ) { + throw new Error( + 'A package ' + name + ' out of @dimensiondev or @masknet scope using mask-src in exports field.', + ) + } for (const [k, v] of notNormativeInstall(dependencies)) assertInstallationSourceValid(name, k, v) // devDependencies won't be installed for intermediate dependencies - // for (const [k, v] of notNormativeInstall(devDependencies)) assertInstallationSourceValid(name, k, v) for (const [k, v] of notNormativeInstall(optionalDependencies)) assertInstallationSourceValid(name, k, v) for (const [k, v] of notNormativeInstall(peerDependencies)) assertInstallationSourceValid(name, k, v) } -function lockPackage(pkg) { - if (pkg.name === 'opensea-js') { - const prefix = 'git+https://github.com/ProjectOpenSea/wyvern-' - pkg.dependencies['wyvern-js'] = `${prefix}js.git#fabb7660f23f2252c141077e32193d281036299e` - pkg.dependencies['wyvern-schemas'] = `${prefix}schemas.git#e1a08fcf8ce2b11a0fe9cbdc7c9f77c59fadef26` - } -} - function readPackage(pkg, context) { validatePackage(pkg) - lockPackage(pkg) return pkg } diff --git a/.prettierignore b/.prettierignore index 0f8cab04ff4..d9fa784fa8f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,14 +1,16 @@ +# https://github.com/prettier/prettier/issues/17784 +packages/theme/src/UIHelper/makeStyles.ts + +**/locale/*.json + .github/ .husky/ package.json package-lock.json pnpm-lock.yaml +**/CHANGELOG.md *generated* -storybook-static - -packages/storybook-shared/*.d.ts -packages/storybook-shared/*.js # VSCode personal settings .vscode/launch.json @@ -24,7 +26,6 @@ packages/storybook-shared/*.js # Build out dist/* /build -/storybook-static /MaskNetwork.*.zip # Environment files @@ -163,12 +164,3 @@ common/deploy/ common/temp/ common/autoinstallers/*/.npmrc **/.rush/temp/ - -# storybook-shared -packages/storybook-shared/*.js -packages/storybook-shared/*.map -packages/storybook-shared/*.d.ts - -# Requires Prettier support for typescript 4.7 -# https://github.com/prettier/prettier/issues/12640 -packages/web3-shared/base/src/specs/index.ts diff --git a/.prettierrc b/.prettierrc index e52bf866b09..7276bcf78c2 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,5 +3,17 @@ "printWidth": 120, "semi": false, "singleQuote": true, - "bracketSameLine": true + "bracketSameLine": true, + "tabWidth": 4, + "experimentalTernaries": true, + "overrides": [ + { + "files": ["*rc", "package.json", "tsconfig*", "*.md", "*.yaml", "*.yml"], + "options": { "tabWidth": 2 } + }, + { + "files": ["*.ts", "*.tsx"], + "options": { "parser": "babel-ts" } + } + ] } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f18d3a92cd5..ef62a2215a8 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,11 +6,10 @@ "recommendations": [ "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", - "editorconfig.editorconfig", "aaron-bond.better-comments", "davidanson.vscode-markdownlint", - "diegolincoln.vscode-styled-components", - "christian-kohler.path-intellisense" + "christian-kohler.path-intellisense", + "TypeScriptTeam.native-preview" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] diff --git a/.vscode/schema/constants.json b/.vscode/schema/constants.json index 4bff76476e1..d7c5c8ed9f0 100644 --- a/.vscode/schema/constants.json +++ b/.vscode/schema/constants.json @@ -30,7 +30,10 @@ "Matic", "Mumbai", "Arbitrum", - "Arbitrum_Rinkeby" + "Arbitrum_Rinkeby", + "Optimism", + "Optimism_Kovan", + "Optimism_Goerli" ] }, "primitive": { diff --git a/.vscode/settings.json b/.vscode/settings.json index 7932559d5cd..a1d2ff05326 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,17 @@ { "typescript.tsdk": "node_modules/typescript/lib", + "typescript.preferences.importModuleSpecifierEnding": "js", + "typescript.experimental.useTsgo": true, + "js/ts.implicitProjectConfig.module": "NodeNext", + "js/ts.implicitProjectConfig.target": "ESNext", "editor.formatOnSave": true, "editor.formatOnSaveMode": "file", + "explorer.fileNesting.patterns": { + "README.md": ".commitlintrc*, .ecrc, .markdownlint*, .node-version, .npm*, .prettier*, .unlock*, .ignore, CNAME, gulp*, LICENSE, lint-staged*, cspell*, svgo*, *.ts, crowdin*", + "package.json": "pnpm-*.yaml, .pnpmfile.cjs" + }, "editor.codeActionsOnSave": { - "source.fixAll": true + "source.fixAll": "explicit" }, "editor.tabSize": 4, "json.schemas": [ @@ -12,11 +20,11 @@ "url": "http://json.schemastore.org/tsconfig" }, { - "fileMatch": ["/packages/mask/src/manifest.json"], + "fileMatch": ["/packages/mask/.webpack/manifest/*.json"], "url": "http://json.schemastore.org/chrome-manifest" }, { - "fileMatch": ["/packages/mask/src/plugins/*/schema.json"], + "fileMatch": ["/packages/plugins/*/schema.json"], "url": "http://json-schema.org/draft-07/schema" }, { @@ -24,7 +32,6 @@ "url": "/.vscode/schema/constants.json" } ], - "cSpell.words": ["Reificated"], "files.associations": { "**/.env/*": "ini" }, diff --git a/.vscode/tasks.recommended.json b/.vscode/tasks.recommended.json index 8aed36ee58d..5457056e635 100644 --- a/.vscode/tasks.recommended.json +++ b/.vscode/tasks.recommended.json @@ -15,15 +15,6 @@ }, "runOptions": { "instanceLimit": 1, "runOn": "folderOpen" } }, - { - "type": "npm", - "script": "start", - "isBackground": true, - "group": "build", - "path": "packages/dashboard/", - "label": "Develop dashboard", - "problemMatcher": [] - }, { "type": "npm", "script": "start", @@ -35,7 +26,7 @@ }, { "type": "npm", - "script": "start", + "script": "start:mv3", "isBackground": true, "group": "build", "label": "Develop main extension", diff --git a/CNAME b/CNAME new file mode 100644 index 00000000000..dd1dee21719 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +code.mask.r2d2.to \ No newline at end of file diff --git a/README.md b/README.md index 5e3c2dad646..9b075e81eda 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,15 @@ # Mask Network [![GitHub license][badge-license]][license] -[![Circle CI][badge-ci]][circle-ci] [![Join the chat at https://gitter.im/Maskbook/community][badge-gitter]][gitter] [![Chrome Web Store][badge-chrome]][client-chrome] [![Mozilla Add-on][badge-firefox]][client-firefox] +[![Opera][badge-opera]][client-opera] [![FOSSA Status][badge-fossa]][fossa] [![Crowdin][badge-crowdin]][crowdin] Mask Network is a portal to the new, open internet, that bridge from Web2.0 to Web3.0 . -With Mask Network, you can send encrypted posts to your friends, trade your best token on Twitter, enjoy NFT pfps, +With Mask Network, you can send encrypted posts to your friends, trade your best token on X (formerly Twitter), enjoy NFT pfps, participate in crypto lucky-draws, and share encrypted files on the platforms you are already using. For general introductions, see [Mask.io](https://mask.io). @@ -27,20 +27,18 @@ For general introductions, see [Mask.io](https://mask.io). ## Downloads - [Mask Network on Chrome Web Store][client-chrome] -- [Mask Network on Firefox Addon Store][client-firefox] (Works on Firefox for Android too!) - -- [Mask Network for iOS][client-ios] -- (Testflight!) [Mask Network for iOS Testflight][client-ios-testflight] -- (Beta!) [Mask Network for Android][client-android] +- [Mask Network on Firefox Addon Store][client-firefox] +- [Mask Network on Opera Addon Store][client-opera] ## Useful Links - [User Forum](https://github.com/DimensionDev/Maskbook/discussions) - [Report Bug][report-bug] -- [Twitter](https://twitter.com/realMaskNetwork) +- [X (formerly Twitter)](https://x.com/masknetwork) - [Facebook](https://www.facebook.com/masknetwork) - [Telegram](https://t.me/maskbook_group) - [Discord](https://discord.gg/4SVXvj7) +- [YouTube](https://www.youtube.com/c/MaskNetwork) ## Developer documentation @@ -57,19 +55,15 @@ see [SECURITY.md](.github/SECURITY.md) Please submit your **resume** to `jobs (at) mask.io` [badge-chrome]: https://img.shields.io/chrome-web-store/v/jkoeaghipilijlahjplgbfiocjhldnap.svg?logo=Maskbook&logoColor=%231c68f3&style=flat-square&label=Chrome%20store -[badge-ci]: https://img.shields.io/circleci/project/github/DimensionDev/Maskbook.svg?style=flat-square&logo=circleci [badge-crowdin]: https://badges.crowdin.net/mask-network/localized.svg [badge-firefox]: https://img.shields.io/amo/v/maskbook?label=Firefox%20store&style=flat-square +[badge-opera]: https://img.shields.io/badge/Opera%20store-v2.32.0-blue.svg [badge-fossa]: https://app.fossa.io/api/projects/git%2Bgithub.com%2FDimensionDev%2FMaskbook.svg?type=shield [badge-gitter]: https://badges.gitter.im/Maskbook/community.svg [badge-license]: https://img.shields.io/badge/license-AGPL-blue.svg?style=flat-square -[client-android]: https://play.google.com/store/apps/details?id=com.dimension.maskbook [client-chrome]: https://chrome.google.com/webstore/detail/maskbook/jkoeaghipilijlahjplgbfiocjhldnap/ [client-firefox]: https://addons.mozilla.org/en-US/firefox/addon/maskbook/ -[client-ios-testflight]: https://testflight.apple.com/join/PYomz4pJ -[client-ios]: https://apps.apple.com/app/id1478382964 -[bounty]: https://github.com/DimensionDev/Maskbook/issues?q=is%3Aopen+is%3Aissue+label%3A%22Bounty%3A+Open%22 -[circle-ci]: https://circleci.com/gh/DimensionDev/Maskbook +[client-opera]: https://addons.opera.com/en/extensions/details/maskbook/ [crowdin]: https://crowdin.com/project/mask-network [fossa-status]: https://app.fossa.io/api/projects/git%2Bgithub.com%2FDimensionDev%2FMaskbook.svg?type=large [fossa]: https://app.fossa.io/projects/git%2Bgithub.com%2FDimensionDev%2FMaskbook diff --git a/crowdin.yml b/crowdin.yml index eb5e1ac758d..2cde1f846c3 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -2,9 +2,7 @@ preserve_hierarchy: true pull_request_title: 'docs(i18n): sync i18n files from Crowdin' commit_message: 'docs(i18n): sync translation %original_file_name% for %language%' files: - - source: /packages/**/locales/en-US.json - translation: /packages/**/locales/%locale%.json + - source: /packages/shared-base-ui/src/locale/en-US.json + translation: /packages/shared-base-ui/src/locale/%locale%.json update_option: 'update_as_unapproved' skip_untranslated_strings: true - ignore: - - /packages/plugins/example diff --git a/cspell.json b/cspell.json index 8bab630fe39..a83b26959ae 100644 --- a/cspell.json +++ b/cspell.json @@ -1,382 +1,269 @@ { + "version": "0.2", "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", - "dictionaries": ["typescript", "node", "html", "css", "fonts"], + "dictionaries": ["typescript", "node", "npm", "html", "css", "fonts"], "ignorePaths": [ + "./packages/gun-utils/gun.js", + "./packages/icons/**", + "./packages/mask/swap/webgl/**", + "./packages/web3-contracts/types/**", + "./patches/**", ".github", + ".gitignore", + ".patch", ".prettierignore", + "*.css", + "*.json", + "*.po", "*.snap", - "**/*.json", - "**/dist/**", - "**/node_modules/**", + "*.svg", + "*.tsbuildinfo", "*generated*", - "patches/**", - "pnpm-lock.yaml" + "build", + "dist", + "node_modules", + "packages/xcode", + "pnpm-lock.yaml", + "pnpm-workspace.yaml", + "qya-aa.json", + ".env/dev-preference.example" ], - "words": [ - "aave", - "adai", - "addrs", + "TODO: fix those words": ["bridgable", "clonable", "sniffings"], + "ignoreWords": [ "aeth", - "amountstate", - "ampl", - "ampleforth", + "algr", "anchorme", - "apikey", - "arbitrum", - "areth", + "apng", + "arbid", "artblocks", "arweave", - "attrace", - "avalanche", - "avax", - "bgcolor", + "astar", "bignumber", - "binancecoin", - "bips", - "birthdate", "bitcointalk", + "bitget", + "bitkeep", "blockhash", "blockie", "blockies", - "bluebar", - "boba", + "blocto", + "blurhash", "bonfida", - "caip", - "canonify", + "bridgable", + "bridgers", + "bscscan", + "bsct", "cashtag", "cbridge", - "checksummed", - "choudhary", - "cipherparams", - "ciphertext", + "celer", + "chainbase", + "chainid", "clonable", "codegen", - "commentid", - "composertitlebar", + "coincarp", "contribs", - "cooldown", - "corepack", + "cronos", + "crossbell", + "cryptopunks", + "cusd", "cyberconnect", "cyberlab", - "datas", + "darkweb", + "dataitem", "debank", - "defikingdoms", - "defn", - "denorm", - "deserialization", - "dfyn", - "dhedge", + "deficonnect", + "devnet", "dimensiondev", - "dklen", "dompurify", - "ecsign", - "endregion", + "dotbit", + "dsearch", "enhanceable", - "entitlee", - "ethersphere", - "ethersproject", - "everytime", - "fbid", + "evmos", + "farcaster", + "favourites", "filelist", "fileservice", - "flashloan", - "fortmatic", - "furucombo", - "futuna", - "gapcheck", - "gasnow", - "geckoview", - "gltf", - "goodghosting", - "gundb", - "hashmasks", + "funder", + "fusd", + "gopluslabs", + "gorli", + "healthz", + "heco", "holoflows", "hookz", - "iconbar", + "hovercard", + "husd", "idbp", - "ifclaimed", + "ifrandom", "imagebitmap", + "imagedelivery", "immer", - "imtokenv", - "investables", + "inpage", "ipfs", "ipfshttp", - "ittr", - "jsbi", - "juicebox", - "kdfparams", + "iqwiki", + "jkoeaghipilijlahjplgbfiocjhldnap", "keccak", "keybase", - "kred", + "keypair", + "kiwistand", + "klaytn", + "lamport", "lamports", "languagedetector", - "lendingpool", - "linkswap", + "lavamoat", + "leaderboard", + "lensprotocol", + "lenster", + "linea", + "lingui", + "linkify", + "lngs", "locationchange", "lockdown", - "logsearch", - "maarten", - "macbinary", + "looksrare", "magiceden", "maskbook", "masknet", "masknetwork", - "masknightly", - "maskswapv", - "masktext", + "maskwallet", "mastdon", - "mdex", - "merkel", "merkle", - "metas", - "metastate", + "metaswap", "metaverse", - "millify", + "milkomeda", "mintable", - "monofont", - "mooniswap", + "momoka", + "moonriver", + "msgid", "msgpack", + "msgstr", "multicall", - "multihop", - "newsfeed", - "nftapi", - "nftavatar", - "nftrss", + "multisigs", + "nftgo", + "nftredpackets", "nftscan", - "nums", - "openswap", + "nftx", + "nonfungiblefriends", + "notistack", + "nstructions", + "oembed", + "okex", + "okxwallet", + "onekey", + "opengraph", + "openocean", "openx", - "overridable", "overscan", + "ownerblock", "pageable", - "pagelet", - "pancakeswap", - "pangolindex", - "pathnames", - "perma", - "pids", - "plusplus", - "pooltogether", - "popc", - "popper", - "popperjs", - "porportion", - "portto", - "prefetch", - "presale", - "pressable", - "promi", - "proxied", - "pushstate", + "pausable", + "paytoken", + "poap", + "polygonscan", + "postop", + "prefund", + "profilecard", "pvtsutils", "qrcode", "quickswap", - "radisk", + "rabby", + "rari", "rarible", + "raycast", "raydium", - "realise", - "rebalance", + "rdns", + "realmasknetwork", + "recasted", "redpacket", - "regedit", - "repayer", - "replacestate", + "redpackets", + "rehype", "repost", - "reqs", - "resizer", - "rhonin", - "rindexed", "rpid", - "sablier", - "sashimiswap", + "rspack", + "rweb", + "savm", "scamsniffer", - "scroller", + "scenechange", + "schnorr", "secp", - "serializers", + "servie", + "shiden", + "signless", + "simplehash", + "sniffings", "solana", + "solanaart", + "solanart", "solflare", "sollet", - "steganographic", + "solsea", + "spaceid", + "stargate", "steganography", "stego", - "subrepo", - "sushiswap", + "suji", + "suspendable", "swappable", "sysvar", + "telos", "testid", - "thegraph", - "timelock", - "timelocked", - "titlebar", - "tokenid", - "topbar", - "toruslabs", - "traderjoe", + "tinycolor", + "tokenpocket", "transak", - "trisolaris", + "trustwallet", + "tsgo", "twimg", - "txid", + "twitterblue", + "txes", "typechain", - "typehash", "typeson", - "unencrypted", - "unreviewed", + "unfollow", + "unfollower", + "unitoken", + "unpadded", "unstake", - "unstyled", + "unstoppabledomains", + "upvoted", + "upvotes", "urlcat", - "usermenu", "vcent", - "venomswap", - "viewbox", - "viperswap", "visualcompletion", + "vitalik", "walletconnect", - "wannaswap", - "wault", - "wavax", + "wanchain", "webextension", - "webm", - "withdrawed", - "wmatic", + "winternitz", + "wnative", "xdai", "xlarge", + "xlayer", + "yumi", "zerion", - "zora", - "zubin" + "zkscan", + "zksync", + "zora" ], - "ignoreWords": [ - "aicanft", - "algr", - "anft", - "armv", - "blocto", - "bsct", - "btcb", - "canft", + "ignoreRegExpList": ["/[A-Za-z0-9]{44}/", "/[A-Za-z0-9]{46}/", "/[A-Za-z0-9]{59}/"], + "overrides": [], + "words": [ + "arbitrum", + "boba", + "caip", + "cashtags", "celo", - "ceur", - "chainid", - "circleci", - "clueid", - "consts", - "cotm", - "cryptoart", - "cryptoartai", - "csrftoken", - "cusd", - "defi", - "deletable", - "devnet", - "dodoex", - "drawed", - "energi", - "enjin", - "ethjs", - "fbclid", - "findtruman", - "frax", - "ftgs", - "ftpoap", - "fusd", - "gamification", - "gopluslabs", - "gorli", - "gusd", - "hookform", - "horiz", - "huobi", - "husd", - "ifadmin", - "ifrandom", - "iife", - "inpage", - "koda", - "kodav", - "lngs", - "maskface", - "maskwallet", - "mathwallet", - "metadate", - "metaplex", - "metaswap", - "nftred", - "nftx", - "nonfungiblefriends", - "northcutt", - "notistack", - "nrge", - "nrgt", - "numberish", - "nyfi", - "okex", - "openocean", - "pausable", - "pkts", - "pnpm", - "poap", - "poaps", - "powah", - "powahs", - "rawdata", - "redpackets", - "renfil", - "shapeclip", - "ssrb", - "steth", - "swaptoken", - "tabsindicator", - "testweb", - "tinycolor", - "tipable", - "traderjoexyz", - "treeshake", - "txes", - "txreceipt", - "uaddr", - "uipd", - "unauthenticate", - "unitoken", - "unlocklock", - "unlockprotocol", - "usdp", - "usei", - "vitalik", - "walletlink", - "wnative", - "xsushi" - ], - "ignoreRegExpList": ["/@servie/"], - "overrides": [ - { - "filename": "**/*.md", - "ignoreWords": ["guanbinrui", "jkoeaghipilijlahjplgbfiocjhldnap", "pnpx", "yisiliu", "zhouhancheng"] - }, - { - "filename": "packages/web3-contracts/types/GoodGhostingIncentives.d.ts", - "ignoreWords": ["adming", "ditribution"] - }, - { - "filename": "packages/web3-shared/evm/assets/**/*.json", - "ignoreWords": ["görli"] - }, - { - "filename": "packages/mask/src/plugins/ITO/assets/regions.json", - "enabled": false - }, - { - "filename": "**/qya-AA.json", - "enabled": false - }, - { - "filename": "**/pnpm-lock.yaml", - "enabled": false - }, - { - "filename": "**/*.html", - "enabled": false - }, - { - "filename": ".circleci/config.yml", - "ignoreWords": ["cimg"] - } + "endregion", + "linkedin", + "luma", + "muln", + "reposted", + "reposts", + "sepolia", + "tanstack", + "tiktok", + "tweetnacl", + "txid", + "wagmi", + "waitlist", + "youtube" ] } diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000000..a0790ad9bfc --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,684 @@ +// cSpell:disable +// @ts-check +import tseslint from 'typescript-eslint' +import UnicornPlugin from 'eslint-plugin-unicorn' +import UnusedImportsPlugin from 'eslint-plugin-unused-imports' +import UnusedClassesPlugin from 'eslint-plugin-tss-unused-classes' +import ReactHooksPlugin from 'eslint-plugin-react-hooks' +import ReactCompilerPlugin from 'eslint-plugin-react-compiler' +// @ts-expect-error +import ImportPlugin from 'eslint-plugin-i' +import ReactPlugin from '@eslint-react/eslint-plugin' +import MasknetPlugin from '@masknet/eslint-plugin' +import ReactQueryPlugin from '@tanstack/eslint-plugin-query' +import LinguiPlugin from 'eslint-plugin-lingui' +import { fixupPluginRules } from '@eslint/compat' + +const deferPackages = [ + 'wallet.ts', + 'anchorme', + '@blocto/fcl', + '@metamask/eth-sig-util', + '@masknet/gun-utils', + 'web3-eth', + 'web3-eth-accounts', + 'twitter-text', + 'web3-utils', + 'web3-eth-abi', + '@solana/web3.js', + // add package names here. +] + +// Prefer rules from @typescript-eslint > unicorn > other plugins +// Level: if the rule is fixable and can be tolerate during dev, use 'warn' is better. +// if the fix needs big rewrite (e.g. XHR => fetch), use 'error' to notice the developer early. +// for RegEx rules, always uses 'error'. + +const avoidMistakeRules = { + // Libraries + '@tanstack/query/exhaustive-deps': 'error', // avoid unstable results from the hook being deps + '@tanstack/query/stable-query-client': 'error', + '@tanstack/query/infinite-query-property-order': 'warn', // help TypeScript to infer type correctly + '@tanstack/query/no-rest-destructuring': 'error', + '@tanstack/query/no-unstable-deps': 'error', // avoid unstable results from the hook being deps + '@tanstack/query/no-void-query-fn': 'error', // query function should always return something + '@lingui/no-single-tag-to-translate': 'error', + // https://github.com/lingui/eslint-plugin/issues/104 + // '@lingui/no-single-variables-to-translate': 'error', + '@lingui/no-trans-inside-trans': 'error', + '@lingui/t-call-in-function': 'error', + + // Code quality + 'no-invalid-regexp': 'error', // RegEx + 'unicorn/no-abusive-eslint-disable': 'error', // disable a rule requires a reason + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': true, + 'ts-nocheck': true, + 'ts-check': false, + minimumDescriptionLength: 5, + }, + ], // disable a rule requires a reason + /// React bad practice + 'react/no-children-count': 'error', + 'react/no-children-for-each': 'error', + // 'react/no-children-map': 'error', + 'react/no-children-only': 'error', + // 'react/no-children-prop': 'error', + 'react/no-children-to-array': 'error', + // 'react/no-clone-element': 'error', + 'react-compiler/react-compiler': 'error', + /// TypeScript bad practice + '@typescript-eslint/no-restricted-types': [ + 'error', + { + types: { + FC: { + message: + "To declare a component, you don't have to use FC to annotate it. To type something that accepts/is a React Component, use ComponentType.", + fixWith: 'ComponentType', + }, + ReactElement: { + message: + 'In most cases, you want ReactNode. Only ignore this rule when you want to use cloneElement.', + fixWith: 'ReactNode', + }, + 'React.FC': { + message: + "To declare a component, you don't have to use React.FC to annotate it. To type something that accepts/is a React Component, use React.ComponentType.", + fixWith: 'React.ComponentType', + }, + 'React.ReactElement': { + message: + 'In most cases, you want React.ReactNode. Only ignore this rule when you want to use cloneElement.', + fixWith: 'React.ReactNode', + }, + }, + }, + ], + '@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'with-single-extends' }], + // '@typescript-eslint/no-invalid-void-type': 'warn', // Disallow void type outside of generic or return types + '@typescript-eslint/no-misused-new': 'error', // wrong 'new ()' or 'constructor()' signatures + '@typescript-eslint/no-unsafe-function-type': 'error', + // '@typescript-eslint/no-unsafe-type-assertion': 'error', // bans `expr as T` + '@typescript-eslint/no-wrapper-object-types': 'error', + /// Unicode support + 'no-misleading-character-class': 'error', // RegEx + 'require-unicode-regexp': 'error', // RegEx modern RegEx with Unicode support + 'unicorn/prefer-code-point': 'error', + // '@masknet/no-builtin-base64': 'warn', // Note: it fixes to Node's Buffer + /// type safety + // '@typescript-eslint/method-signature-style': 'warn', // method signature is bivariant + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', // bans foo?.bar! + // '@typescript-eslint/no-unsafe-argument': 'error', // bans call(any) + // '@typescript-eslint/no-unsafe-assignment': 'error', // bans a = any + // '@typescript-eslint/no-unsafe-call': 'error', // bans any() + // '@typescript-eslint/no-unsafe-member-access': 'error', // bans a = any.prop + // '@typescript-eslint/no-unsafe-return': 'error', // bans return any + '@typescript-eslint/prefer-return-this-type': 'error', // use `: this` properly + // '@typescript-eslint/restrict-plus-operands': 'error', // stronger `a + b` check + // '@typescript-eslint/restrict-template-expressions': 'error', // bans `${nonString}` + // '@typescript-eslint/strict-boolean-expressions': 'error', // stronger check for nullable string/number/boolean + // '@typescript-eslint/switch-exhaustiveness-check': 'error', // switch should be exhaustive + // '@typescript-eslint/unbound-method': 'error', // requires `this` to be set properly + // '@masknet/type-no-force-cast-via-top-type': 'error', // expr as any as T + + // Security + 'no-script-url': 'error', // javascript: + // 'unicorn/require-post-message-target-origin': 'warn', // postMessage(data, 'origin') + 'react/dom/no-dangerously-set-innerhtml': 'error', // dangerouslySetInnerHTML + 'react/dom/no-dangerously-set-innerhtml-with-children': 'error', // dangerouslySetInnerHTML + children + 'react/dom/no-missing-iframe-sandbox': 'error', //