diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml index 98c749d72dbb..b4a3e4fffc87 100644 --- a/.github/auto_assign.yml +++ b/.github/auto_assign.yml @@ -3,11 +3,7 @@ addReviewers: true addAssignees: false reviewers: - - guanbinrui - - Jack-Works - - jk234ert - - septs - - zhouhanseng + - Dev-Maskbook numberOfReviewers: 0 diff --git a/.github/stale.yml b/.github/stale.yml index e49614cf5d6e..48b408a73092 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,6 +1,6 @@ # https://github.com/probot/stale -daysUntilStale: 90 +daysUntilStale: 60 daysUntilClose: 7 exemptLabels: @@ -22,5 +22,3 @@ markComment: > for your contributions. limitPerRun: 30 - -only: issues diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml new file mode 100644 index 000000000000..d2d6bfa2efcc --- /dev/null +++ b/.github/workflows/bot.yml @@ -0,0 +1,18 @@ +name: Bot + +on: + push: + branches: [master, develop, released] + pull_request: + branches: [master, develop, released] + +jobs: + triage: + runs-on: ubuntu-20.04 + steps: + - uses: mschilde/auto-label-merge-conflicts@master + with: + CONFLICT_LABEL_NAME: "Blocked: Has Conflict" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MAX_RETRIES: 5 + WAIT_MS: 5000 diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 236069c8e4c9..584fbacb9497 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -73,7 +73,7 @@ jobs: key: ${{ runner.os }}-node-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: ${{ runner.os }}-node- - run: npx pnpm install - - run: npm run lint:ci + - run: npm run lint:ci -- --max-warnings=0 - run: npm run lint:ci -- --format junit -o reports/junit/eslint-results.xml - name: Upload eslint report uses: actions/upload-artifact@v2 diff --git a/.i18n-codegen.json b/.i18n-codegen.json index bd6dd0c67aeb..5ebcd65a0dbd 100644 --- a/.i18n-codegen.json +++ b/.i18n-codegen.json @@ -15,8 +15,8 @@ } }, { - "input": "./packages/theme/src/locales/en.json", - "output": "./packages/theme/src/locales/i18n_generated", + "input": "./packages/shared/src/locales/en.json", + "output": "./packages/shared/src/locales/i18n_generated", "parser": "i18next", "generator": { "type": "i18next/react-hooks", diff --git a/packages/constants/data/ito.json b/packages/constants/data/ito.json index 65c8094d7906..28c60094a307 100644 --- a/packages/constants/data/ito.json +++ b/packages/constants/data/ito.json @@ -21,6 +21,17 @@ "Matic": "", "Mumbai": "" }, + "ITO2_CONTRACT_ADDRESS": { + "Mainnet": "0xc2CFbF22d6Dc87D0eE18d38d73733524c109Ff46", + "Ropsten": "0xBD4c3Cf084B6F4d25430Ee5d44436e860Cc58Ee4", + "Rinkeby": "", + "Kovan": "", + "Gorli": "", + "BSC": "0x96c7D011cdFD467f551605f0f5Fce279F86F4186", + "BSCT": "0x981be454a930479d92C91a0092D204b64845A5D6", + "Matic": "0xF9F7C1496c21bC0180f4B64daBE0754ebFc8A8c0", + "Mumbai": "0x54a0A221C25Fc0a347EC929cFC5db0be17fA2a2B" + }, "ITO_BSC_POLYGON_CONTRACT_ADDRESS": { "Mainnet": "", "Ropsten": "", @@ -43,6 +54,17 @@ "Matic": "0x02Ea0720254F7fa4eca7d09A1b9C783F1020EbEF", "Mumbai": "0x5B966f3a32Db9C180843bCb40267A66b73E4f022" }, + "DEFAULT_QUALIFICATION2_ADDRESS": { + "Mainnet": "0x4dC5f343Fe57E4fbDA1B454d125D396A3181272c", + "Ropsten": "0xd5e6434bde165062b3d9572DEFd6393c7B3E2902", + "Rinkeby": "", + "Kovan": "", + "Gorli": "", + "BSC": "0xAb7B1bE4233A04e5C43a810E75657ECED8E5463B", + "BSCT": "", + "Matic": "0x2cf91AD8C175305EBe6970Bd8f81231585EFbd77", + "Mumbai": "" + }, "SUBGRAPH_URL": { "Mainnet": "https://api.thegraph.com/subgraphs/name/dimensiondev/mask-ito-mainnet", "Ropsten": "https://api.thegraph.com/subgraphs/name/dimensiondev/mask-ito", diff --git a/packages/constants/data/token-asset-base-url.json b/packages/constants/data/token-asset-base-url.json new file mode 100644 index 000000000000..a63b25ade36f --- /dev/null +++ b/packages/constants/data/token-asset-base-url.json @@ -0,0 +1,40 @@ +{ + "TOKEN_ASSET_BASE_URI": { + "Mainnet": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum" + ], + "Ropsten": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum" + ], + "Rinkeby": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum" + ], + "Kovan": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum" + ], + "Gorli": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/ethereum" + ], + "BSC": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/smartchain" + ], + "BSCT": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/smartchain" + ], + "Matic": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/polygon" + ], + "Mumbai": [ + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon", + "https://rawcdn.githack.com/trustwallet/assets/master/blockchains/polygon" + ] + } +} diff --git a/packages/contracts/CHANGELOG.md b/packages/contracts/CHANGELOG.md index 31126d604ca6..d94a314d5d1e 100644 --- a/packages/contracts/CHANGELOG.md +++ b/packages/contracts/CHANGELOG.md @@ -38,6 +38,17 @@ Bsc 0x54a0A221C25Fc0a347EC929cFC5db0be17fA2a2B Polygon 0x981be454a930479d92C91a0092D204b64845A5D6 ``` +> Jun-25-2021 +> branch: master +> commit: e05d299e80c1910fadd90bf021c52ced8b13f891 + +```plain +Mainnet 0xc2CFbF22d6Dc87D0eE18d38d73733524c109Ff46 +Ropsten 0xBD4c3Cf084B6F4d25430Ee5d44436e860Cc58Ee4 +Bsc 0x96c7D011cdFD467f551605f0f5Fce279F86F4186 +Polygon 0xF9F7C1496c21bC0180f4B64daBE0754ebFc8A8c0 +``` + ## MaskITO > Feb-21-2021 diff --git a/packages/contracts/abis/BscPolygonITO.json b/packages/contracts/abis/ITO2.json similarity index 91% rename from packages/contracts/abis/BscPolygonITO.json rename to packages/contracts/abis/ITO2.json index 688d13b358ff..ee3bc6003460 100644 --- a/packages/contracts/abis/BscPolygonITO.json +++ b/packages/contracts/abis/ITO2.json @@ -1,20 +1,15 @@ [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "bytes32", "name": "id", "type": "bytes32" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "claimer", "type": "address" @@ -45,13 +40,13 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "bytes32", "name": "id", "type": "bytes32" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "token_address", "type": "address" @@ -76,22 +71,22 @@ "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "total", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "creator", + "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "bytes32", "name": "id", "type": "bytes32" }, { "indexed": false, - "internalType": "address", - "name": "creator", - "type": "address" + "internalType": "uint256", + "name": "total", + "type": "uint256" }, { "indexed": false, @@ -155,13 +150,13 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "bytes32", "name": "id", "type": "bytes32" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "swapper", "type": "address" @@ -204,13 +199,13 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "bytes32", "name": "id", "type": "bytes32" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "token_address", "type": "address" @@ -225,6 +220,19 @@ "name": "WithdrawSuccess", "type": "event" }, + { + "inputs": [], + "name": "base_time", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -368,6 +376,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_base_time", + "type": "uint64" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -376,9 +397,9 @@ "type": "bytes32" }, { - "internalType": "uint256", + "internalType": "uint32", "name": "_unlock_time", - "type": "uint256" + "type": "uint32" } ], "name": "setUnlockTime", @@ -390,7 +411,7 @@ "inputs": [ { "internalType": "bytes32", - "name": "_id", + "name": "id", "type": "bytes32" }, { @@ -398,11 +419,6 @@ "name": "verification", "type": "bytes32" }, - { - "internalType": "bytes32", - "name": "validation", - "type": "bytes32" - }, { "internalType": "uint256", "name": "exchange_addr_i", @@ -410,8 +426,13 @@ }, { "internalType": "uint128", - "name": "_input_total", + "name": "input_total", "type": "uint128" + }, + { + "internalType": "bytes32[]", + "name": "data", + "type": "bytes32[]" } ], "name": "swap", diff --git a/packages/contracts/abis/Qualification2.json b/packages/contracts/abis/Qualification2.json new file mode 100644 index 000000000000..5a9a5ddad3e6 --- /dev/null +++ b/packages/contracts/abis/Qualification2.json @@ -0,0 +1,212 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_start_time", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "qualified", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "Qualification", + "type": "event" + }, + { + "inputs": [], + "name": "get_start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "data", + "type": "bytes32[]" + } + ], + "name": "ifQualified", + "outputs": [ + { + "internalType": "bool", + "name": "qualified", + "type": "bool" + }, + { + "internalType": "string", + "name": "errorMsg", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "data", + "type": "bytes32[]" + } + ], + "name": "logQualified", + "outputs": [ + { + "internalType": "bool", + "name": "qualified", + "type": "bool" + }, + { + "internalType": "string", + "name": "errorMsg", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_start_time", + "type": "uint256" + } + ], + "name": "set_start_time", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start_time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/contracts/types/BscPolygonITO.d.ts b/packages/contracts/types/ITO2.d.ts similarity index 93% rename from packages/contracts/types/BscPolygonITO.d.ts rename to packages/contracts/types/ITO2.d.ts index 39f626056d3e..ab99408f0192 100644 --- a/packages/contracts/types/BscPolygonITO.d.ts +++ b/packages/contracts/types/ITO2.d.ts @@ -44,9 +44,9 @@ export type DestructSuccess = ContractEventLog<{ 3: string[] }> export type FillSuccess = ContractEventLog<{ - total: string - id: string creator: string + id: string + total: string creation_time: string token_address: string message: string @@ -94,10 +94,12 @@ export type WithdrawSuccess = ContractEventLog<{ 2: string }> -export interface BscPolygonITO extends BaseContract { - constructor(jsonInterface: any[], address?: string, options?: ContractOptions): BscPolygonITO - clone(): BscPolygonITO +export interface ITO2 extends BaseContract { + constructor(jsonInterface: any[], address?: string, options?: ContractOptions): ITO2 + clone(): ITO2 methods: { + base_time(): NonPayableTransactionObject + check_availability(id: string | number[]): NonPayableTransactionObject<{ exchange_addrs: string[] remaining: string @@ -135,14 +137,16 @@ export interface BscPolygonITO extends BaseContract { _qualification: string, ): PayableTransactionObject + initialize(_base_time: number | string | BN): NonPayableTransactionObject + setUnlockTime(id: string | number[], _unlock_time: number | string | BN): NonPayableTransactionObject swap( - _id: string | number[], + id: string | number[], verification: string | number[], - validation: string | number[], exchange_addr_i: number | string | BN, - _input_total: number | string | BN, + input_total: number | string | BN, + data: (string | number[])[], ): PayableTransactionObject withdraw(id: string | number[], addr_i: number | string | BN): NonPayableTransactionObject diff --git a/packages/contracts/types/Qualification2.d.ts b/packages/contracts/types/Qualification2.d.ts new file mode 100644 index 000000000000..b4a28750afb1 --- /dev/null +++ b/packages/contracts/types/Qualification2.d.ts @@ -0,0 +1,94 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +import BN from 'bn.js' +import { ContractOptions } from 'web3-eth-contract' +import { EventLog } from 'web3-core' +import { EventEmitter } from 'events' +import { + Callback, + PayableTransactionObject, + NonPayableTransactionObject, + BlockType, + ContractEventLog, + BaseContract, +} from './types' + +interface EventOptions { + filter?: object + fromBlock?: BlockType + topics?: string[] +} + +export type OwnershipTransferred = ContractEventLog<{ + previousOwner: string + newOwner: string + 0: string + 1: string +}> +export type Qualification = ContractEventLog<{ + account: string + qualified: boolean + blockNumber: string + timestamp: string + 0: string + 1: boolean + 2: string + 3: string +}> + +export interface Qualification2 extends BaseContract { + constructor(jsonInterface: any[], address?: string, options?: ContractOptions): Qualification2 + clone(): Qualification2 + methods: { + get_start_time(): NonPayableTransactionObject + + ifQualified( + account: string, + data: (string | number[])[], + ): NonPayableTransactionObject<{ + qualified: boolean + errorMsg: string + 0: boolean + 1: string + }> + + logQualified( + account: string, + data: (string | number[])[], + ): NonPayableTransactionObject<{ + qualified: boolean + errorMsg: string + 0: boolean + 1: string + }> + + owner(): NonPayableTransactionObject + + renounceOwnership(): NonPayableTransactionObject + + set_start_time(_start_time: number | string | BN): NonPayableTransactionObject + + start_time(): NonPayableTransactionObject + + supportsInterface(interfaceId: string | number[]): NonPayableTransactionObject + + transferOwnership(newOwner: string): NonPayableTransactionObject + } + events: { + OwnershipTransferred(cb?: Callback): EventEmitter + OwnershipTransferred(options?: EventOptions, cb?: Callback): EventEmitter + + Qualification(cb?: Callback): EventEmitter + Qualification(options?: EventOptions, cb?: Callback): EventEmitter + + allEvents(options?: EventOptions, cb?: Callback): EventEmitter + } + + once(event: 'OwnershipTransferred', cb: Callback): void + once(event: 'OwnershipTransferred', options: EventOptions, cb: Callback): void + + once(event: 'Qualification', cb: Callback): void + once(event: 'Qualification', options: EventOptions, cb: Callback): void +} diff --git a/packages/dashboard/.storybook/main.js b/packages/dashboard/.storybook/main.js index c90d15c38f34..03ea76db5a15 100644 --- a/packages/dashboard/.storybook/main.js +++ b/packages/dashboard/.storybook/main.js @@ -4,12 +4,4 @@ module.exports = { reactOptions: { fastRefresh: true, }, - typescript: { - // todo, fixme: - // temporary workaround is disable doc gen - // related to PR: - // https://github.com/DimensionDev/Maskbook/issues/3253 - // https://github.com/styleguidist/react-docgen-typescript/issues/356 - reactDocgen: 'none', - }, } diff --git a/packages/dashboard/.storybook/preview.js b/packages/dashboard/.storybook/preview.js index a5e536c98736..954d3e275199 100644 --- a/packages/dashboard/.storybook/preview.js +++ b/packages/dashboard/.storybook/preview.js @@ -1,7 +1,7 @@ import React from 'react' import { ThemeProvider, StyledEngineProvider } from '@material-ui/core' import { StylesProvider } from '@material-ui/styles' -import { MaskLightTheme, addMaskThemeI18N, applyMaskColorVars } from '@masknet/theme' +import { MaskLightTheme, addMaskSharedI18N, applyMaskColorVars } from '@masknet/theme' import { withMatrix } from 'storybook-addon-matrix' import { addDashboardI18N } from '../src/locales' import { I18nextProvider, initReactI18next } from 'react-i18next' @@ -15,7 +15,7 @@ i18n.init({ }) i18n.use(initReactI18next) addDashboardI18N(i18n) -addMaskThemeI18N(i18n) +addMaskSharedI18N(i18n) export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, } diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 3d1f871bb863..4e29800782a3 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -11,8 +11,8 @@ "build": "build -- snowpack build" }, "dependencies": { - "@dimensiondev/holoflows-kit": "0.8.0-20210317064617-6c4792c", - "@dimensiondev/kit": "^0.0.0-20210221102734-0b4a937", + "@dimensiondev/holoflows-kit": "=0.8.0-20210429202414-74fb9a1", + "@dimensiondev/kit": "=0.0.0-20210630045432-e05621c", "@masknet/icons": "workspace:*", "@masknet/plugin-example": "workspace:*", "@masknet/plugin-infra": "workspace:*", @@ -40,12 +40,12 @@ "@babel/core": "^7.14.3", "@snowpack/plugin-dotenv": "^2.1.0", "@snowpack/plugin-react-refresh": "^2.5.0", - "@storybook/addon-actions": "^6.2.9", - "@storybook/addon-essentials": "^6.2.9", - "@storybook/addon-links": "^6.2.9", - "@storybook/addons": "^6.2.9", - "@storybook/react": "^6.2.9", - "@storybook/theming": "^6.2.9", + "@storybook/addon-actions": "^6.3.0-rc.12", + "@storybook/addon-essentials": "^6.3.0-rc.12", + "@storybook/addon-links": "^6.3.0-rc.12", + "@storybook/addons": "^6.3.0-rc.12", + "@storybook/react": "^6.3.0-rc.12", + "@storybook/theming": "^6.3.0-rc.12", "@types/snowpack-env": "^2.3.2", "babel-loader": "^8.2.2", "snowpack": "^3.5.1" diff --git a/packages/dashboard/src/components/DashboardFrame/index.tsx b/packages/dashboard/src/components/DashboardFrame/index.tsx index 4b3156ff0968..e27da5646062 100644 --- a/packages/dashboard/src/components/DashboardFrame/index.tsx +++ b/packages/dashboard/src/components/DashboardFrame/index.tsx @@ -14,7 +14,7 @@ import { } from '@material-ui/core' import { Menu as MenuIcon, Close as CloseIcon } from '@material-ui/icons' import Color from 'color' -import { ErrorBoundary } from '@masknet/theme' +import { ErrorBoundary } from '@masknet/shared' import { useState, useContext, useMemo, Suspense } from 'react' import { DashboardContext } from './context' import { Navigation } from './Navigation' diff --git a/packages/dashboard/src/components/FileUpload/index.tsx b/packages/dashboard/src/components/FileUpload/index.tsx index c2064d5bdc80..18e5f9759d3a 100644 --- a/packages/dashboard/src/components/FileUpload/index.tsx +++ b/packages/dashboard/src/components/FileUpload/index.tsx @@ -2,6 +2,7 @@ import { MaskColorVar } from '@masknet/theme' import { makeStyles, Typography } from '@material-ui/core' import { useEffect, useState } from 'react' import { File as FileIcon } from '@masknet/icons' +import { blobToText } from '@dimensiondev/kit' const useStyles = makeStyles(() => ({ root: { @@ -51,11 +52,7 @@ export default function FileUpload({ width, height, readAsText, onChange }: File useEffect(() => { if (file) { if (readAsText) { - const reader = new FileReader() - reader.readAsText(file) - reader.addEventListener('loadend', () => { - onChange(file, reader.result as string) - }) + blobToText(file).then((result) => onChange(file, result)) } else { onChange(file) } diff --git a/packages/dashboard/src/initialization/Dashboard.tsx b/packages/dashboard/src/initialization/Dashboard.tsx index ac38678a2e9f..0d5b0bfdade5 100644 --- a/packages/dashboard/src/initialization/Dashboard.tsx +++ b/packages/dashboard/src/initialization/Dashboard.tsx @@ -4,13 +4,13 @@ import { StylesProvider } from '@material-ui/styles' import { CustomSnackbarProvider, MaskLightTheme, - ErrorBoundary, applyMaskColorVars, MaskDarkTheme, useSystemPreferencePalatte, } from '@masknet/theme' import { ChainId } from '@masknet/web3-shared' import { Emitter } from '@servie/events' +import { ErrorBoundary } from '@masknet/shared' import i18n from 'i18next' import { I18nextProvider } from 'react-i18next' diff --git a/packages/dashboard/src/initialization/i18n.ts b/packages/dashboard/src/initialization/i18n.ts index 9f1c21aba0ee..25963a2f5d46 100644 --- a/packages/dashboard/src/initialization/i18n.ts +++ b/packages/dashboard/src/initialization/i18n.ts @@ -1,5 +1,5 @@ import i18n from 'i18next' -import { addMaskThemeI18N } from '@masknet/theme' +import { addMaskSharedI18N } from '@masknet/shared' import { addDashboardI18N } from '../locales' import { initReactI18next } from 'react-i18next' @@ -10,5 +10,5 @@ i18n.init({ fallbackLng: 'en', }) i18n.use(initReactI18next) -addMaskThemeI18N(i18n) +addMaskSharedI18N(i18n) addDashboardI18N(i18n) diff --git a/packages/dashboard/src/locales/en.json b/packages/dashboard/src/locales/en.json index 9d9f65f342af..40462651f651 100644 --- a/packages/dashboard/src/locales/en.json +++ b/packages/dashboard/src/locales/en.json @@ -73,6 +73,7 @@ "wallets_empty_collectible_tip": "No collectibles were found. Please add Collectibles.", "wallets_address_copied": "Address successfully copied", "wallets_address_copy": "Copy", + "wallets_loading_token": "Loading Token", "personas_setup_connect_tips": "Please connect to your {{type}} account.", "personas_setup_connect": "Connect", "personas_name_maximum_tips": "Maximum length is {{length}} characters long.", diff --git a/packages/dashboard/src/locales/zh.json b/packages/dashboard/src/locales/zh.json index 259b775e4412..db83d3dd5469 100644 --- a/packages/dashboard/src/locales/zh.json +++ b/packages/dashboard/src/locales/zh.json @@ -42,6 +42,7 @@ "wallets_balance_Buy": "購買", "wallets_balance_Swap": "交換", "wallets_balance_Receive": "接收", + "wallets_loading_token": "", "personas_setup_connect_tips": "", "personas_setup_connect": "", "personas_name_maximum_tips": "", diff --git a/packages/dashboard/src/pages/Wallets/components/AddCollectibleDialog/index.tsx b/packages/dashboard/src/pages/Wallets/components/AddCollectibleDialog/index.tsx index 0533f37f7319..497c59ca5d22 100644 --- a/packages/dashboard/src/pages/Wallets/components/AddCollectibleDialog/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/AddCollectibleDialog/index.tsx @@ -1,5 +1,6 @@ import { memo, useMemo, useState } from 'react' -import { MaskColorVar, MaskDialog, useSnackbarCallback } from '@masknet/theme' +import { MaskColorVar, MaskDialog } from '@masknet/theme' +import { useSnackbarCallback } from '@masknet/shared' import { Box, Button, DialogActions, DialogContent, makeStyles, TextField } from '@material-ui/core' import { useERC721TokenAssetDetailed, useERC721TokenDetailed, useWallet } from '@masknet/web3-shared' import { PluginServices } from '../../../../API' diff --git a/packages/dashboard/src/pages/Wallets/components/AddTokenConfirmUI/index.tsx b/packages/dashboard/src/pages/Wallets/components/AddTokenConfirmUI/index.tsx index 3742bd847d55..c83211ea9af8 100644 --- a/packages/dashboard/src/pages/Wallets/components/AddTokenConfirmUI/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/AddTokenConfirmUI/index.tsx @@ -1,8 +1,8 @@ import { memo } from 'react' import { useDashboardI18N } from '../../../../locales' import { Box, Button, DialogActions, DialogContent, makeStyles, Stack, Typography } from '@material-ui/core' -import { TokenIcon } from '../TokenIcon' import type { ERC20TokenDetailed } from '@masknet/web3-shared' +import { TokenIcon } from '@masknet/shared' export interface AddTokenConfirmUIProps { onBack: () => void diff --git a/packages/dashboard/src/pages/Wallets/components/AddTokenDialog/index.tsx b/packages/dashboard/src/pages/Wallets/components/AddTokenDialog/index.tsx index d3eb780bff26..171d52211db8 100644 --- a/packages/dashboard/src/pages/Wallets/components/AddTokenDialog/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/AddTokenDialog/index.tsx @@ -1,5 +1,6 @@ import { memo, useState } from 'react' -import { MaskDialog, useSnackbarCallback } from '@masknet/theme' +import { MaskDialog } from '@masknet/theme' +import { useSnackbarCallback } from '@masknet/shared' import { ERC20TokenDetailed, useERC20TokenBalance, useERC20TokenDetailed, useWallet } from '@masknet/web3-shared' import { useUpdateEffect } from 'react-use' import { PluginServices } from '../../../../API' diff --git a/packages/dashboard/src/pages/Wallets/components/CollectibleList/index.tsx b/packages/dashboard/src/pages/Wallets/components/CollectibleList/index.tsx index 1c44b5b5ab68..a4181aa33f3f 100644 --- a/packages/dashboard/src/pages/Wallets/components/CollectibleList/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/CollectibleList/index.tsx @@ -2,19 +2,19 @@ import { Dispatch, memo, SetStateAction, useState } from 'react' import { Box, makeStyles, TablePagination } from '@material-ui/core' import { ChainId, + CollectibleProvider, ERC1155TokenAssetDetailed, ERC721TokenAssetDetailed, EthereumTokenType, + formatEthereumAddress, useAccount, useChainId, - useWallet, - CollectibleProvider, useCollectibles, + useWallet, } from '@masknet/web3-shared' import { useCurrentCollectibleDataProvider } from '../../api' import { LoadingPlaceholder } from '../LoadingPlacholder' import { EmptyPlaceholder } from '../EmptyPlaceholder' -import { formatEthereumAddress } from '@masknet/shared' import { CollectibleCard } from '../CollectibleCard' import { useDashboardI18N } from '../../../../locales' diff --git a/packages/dashboard/src/pages/Wallets/components/ReceiveDialog/index.tsx b/packages/dashboard/src/pages/Wallets/components/ReceiveDialog/index.tsx index 2090c9752464..8d7273c9b6cb 100644 --- a/packages/dashboard/src/pages/Wallets/components/ReceiveDialog/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/ReceiveDialog/index.tsx @@ -1,6 +1,7 @@ import { memo } from 'react' import { useDashboardI18N } from '../../../../locales' -import { MaskColorVar, MaskDialog, QRCode, useSnackbarCallback } from '@masknet/theme' +import { MaskColorVar, MaskDialog } from '@masknet/theme' +import { QRCode, useSnackbarCallback } from '@masknet/shared' import { DialogContent, Typography, makeStyles, DialogActions, Button } from '@material-ui/core' import { WalletQRCodeContainer } from '../../../../components/WalletQRCodeContainer' import { useCopyToClipboard } from 'react-use' diff --git a/packages/dashboard/src/pages/Wallets/components/TokenIcon/index.tsx b/packages/dashboard/src/pages/Wallets/components/TokenIcon/index.tsx deleted file mode 100644 index 3fb41cddd13b..000000000000 --- a/packages/dashboard/src/pages/Wallets/components/TokenIcon/index.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { ChainId, resolveChainFullName, useBlockie, useChainDetailed, resolveTokenIconURL } from '@masknet/web3-shared' -import type { AvatarProps } from '@material-ui/core' -import { Avatar } from '@material-ui/core' -import { memo } from 'react' -import { useImageFailOver } from '../../../../hooks/useImageFailOver' - -export interface TokenIconProps { - address: string - name?: string - logoURL?: string - chainId?: ChainId - AvatarProps?: Partial -} - -export const TokenIcon = memo(({ address, name, logoURL, chainId, AvatarProps }) => { - const chainDetailed = useChainDetailed() - const tokenBlockie = useBlockie(address) - - const fullName = chainDetailed ? resolveChainFullName(chainId ?? chainDetailed.chainId) : '' - - const { value: baseURI, loading } = useImageFailOver( - chainDetailed - ? [ - `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/${fullName.toLowerCase()}`, - `https://rawcdn.githack.com/trustwallet/assets/master/blockchains/${fullName.toLowerCase()}`, - ] - : [], - '/info/logo.png', - ) - - return ( - - ) -}) - -export interface TokenIconUIProps { - logoURL?: string - loading: boolean - address: string - baseURI: string - AvatarProps?: Partial - tokenBlockie: string - name?: string -} - -export const TokenIconUI = memo( - ({ logoURL, loading, address, baseURI, AvatarProps, tokenBlockie, name }) => { - if (logoURL) { - return ( - - {name?.substr(0, 1).toLocaleUpperCase()} - - ) - } - - return ( - - {name?.substr(0, 1).toLocaleUpperCase()} - - ) - }, -) diff --git a/packages/dashboard/src/pages/Wallets/components/TokenTable/index.tsx b/packages/dashboard/src/pages/Wallets/components/TokenTable/index.tsx index e5f70cb138c9..68b3cccdbf84 100644 --- a/packages/dashboard/src/pages/Wallets/components/TokenTable/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/TokenTable/index.tsx @@ -1,25 +1,24 @@ import { Dispatch, memo, SetStateAction, useState } from 'react' import { - Table, - TableContainer, - TableHead, - TableRow, - TableCell, Box, makeStyles, - TableBody, Pagination, PaginationItem, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, } from '@material-ui/core' import { MaskColorVar } from '@masknet/theme' import { useDashboardI18N } from '../../../../locales' import { EmptyPlaceholder } from '../EmptyPlaceholder' import { LoadingPlaceholder } from '../LoadingPlacholder' import { TokenTableRow } from '../TokenTableRow' -import { formatBalance } from '@masknet/shared' +import { Asset, formatBalance, useAssets, useERC20TokensPaged } from '@masknet/web3-shared' import BigNumber from 'bignumber.js' import { ceil } from 'lodash-es' -import { Asset, useAssets, useERC20TokensPaged } from '@masknet/web3-shared' const useStyles = makeStyles((theme) => ({ container: { diff --git a/packages/dashboard/src/pages/Wallets/components/TokenTableRow/index.tsx b/packages/dashboard/src/pages/Wallets/components/TokenTableRow/index.tsx index 1e34cb91cd47..33a1283a18a3 100644 --- a/packages/dashboard/src/pages/Wallets/components/TokenTableRow/index.tsx +++ b/packages/dashboard/src/pages/Wallets/components/TokenTableRow/index.tsx @@ -1,14 +1,18 @@ import { memo } from 'react' -import { Box, TableRow, Typography, makeStyles, TableCell, Button } from '@material-ui/core' -import { TokenIcon } from '../TokenIcon' -import { formatBalance, formatCurrency, FormattedCurrency, pow10 } from '@masknet/shared' -import { CurrencyType, Asset, getTokenUSDValue } from '@masknet/web3-shared' +import { Box, Button, makeStyles, TableCell, TableRow, Typography } from '@material-ui/core' +import { FormattedCurrency } from '@masknet/shared' +import { Asset, CurrencyType, formatBalance, formatCurrency, getTokenUSDValue, pow10 } from '@masknet/web3-shared' import BigNumber from 'bignumber.js' import { useNavigate } from 'react-router' import { RoutePaths } from '../../../../type' import { useDashboardI18N } from '../../../../locales' +import { TokenIcon } from '@masknet/shared' const useStyles = makeStyles((theme) => ({ + icon: { + width: 36, + height: 36, + }, symbol: { marginLeft: 14, fontSize: theme.typography.pxToRem(14), @@ -31,6 +35,7 @@ export const TokenTableRow = memo(({ asset }) => { (({ asset }) => { {getTokenUSDValue(asset) < 0.01 ? ( '<0.01' ) : ( - + )} diff --git a/packages/dashboard/src/pages/Wallets/hooks/useERC20TokensDetailed.ts b/packages/dashboard/src/pages/Wallets/hooks/useERC20TokensDetailed.ts new file mode 100644 index 000000000000..342621253428 --- /dev/null +++ b/packages/dashboard/src/pages/Wallets/hooks/useERC20TokensDetailed.ts @@ -0,0 +1,49 @@ +import { + EthereumTokenType, + isSameAddress, + TokenListsState, + useAssetsFromChain, + useERC20TokensDetailedFromTokenLists, + useEthereumConstants, + useNativeTokenDetailed, + useTokenConstants, +} from '@masknet/web3-shared' +import { uniqBy } from 'lodash-es' +import { useMemo } from 'react' + +export function useERC20TokensDetailed() { + const { ERC20_TOKEN_LISTS } = useEthereumConstants() + const { value: nativeTokenDetailed } = useNativeTokenDetailed() + const { state, tokensDetailed: erc20TokensDetailed } = useERC20TokensDetailedFromTokenLists(ERC20_TOKEN_LISTS) + + //#region mask token + const { MASK_ADDRESS } = useTokenConstants() + //#endregion + + const tokens = useMemo( + () => + uniqBy( + nativeTokenDetailed ? [nativeTokenDetailed, ...erc20TokensDetailed] : [...erc20TokensDetailed], + (x) => x.address.toLowerCase(), + ).sort((a, z) => { + if (a.type === EthereumTokenType.Native) return -1 + if (z.type === EthereumTokenType.Native) return 1 + if (isSameAddress(a.address, MASK_ADDRESS)) return -1 + if (isSameAddress(z.address, MASK_ADDRESS)) return 1 + return 0 + }), + [nativeTokenDetailed, erc20TokensDetailed.length], + ) + + const { + value: assetsDetailedChain = [], + loading: assetsDetailedChainLoading, + error: assetsDetailedChainError, + } = useAssetsFromChain(tokens) + + return { + value: assetsDetailedChain, + loading: state !== TokenListsState.READY || assetsDetailedChainLoading, + error: assetsDetailedChainError, + } +} diff --git a/packages/dashboard/src/web3/context.ts b/packages/dashboard/src/web3/context.ts index 6ff32e27d8a5..9e015a4068f5 100644 --- a/packages/dashboard/src/web3/context.ts +++ b/packages/dashboard/src/web3/context.ts @@ -62,6 +62,7 @@ export const Web3Context: Web3ProviderType = { getAssetList: PluginServices.Wallet.getAssetsList, getAssetsListNFT: PluginServices.Wallet.getAssetsListNFT, getERC721TokensPaged, + fetchERC20TokensFromTokenLists: Services.Ethereum.fetchERC20TokensFromTokenLists, } export function createExternalProvider() { diff --git a/packages/theme/stories/components/CrashUI.stories.tsx b/packages/dashboard/stories/components/Shared/CrashUI.tsx similarity index 75% rename from packages/theme/stories/components/CrashUI.stories.tsx rename to packages/dashboard/stories/components/Shared/CrashUI.tsx index 1a52cb817e17..060da70ce0b0 100644 --- a/packages/theme/stories/components/CrashUI.stories.tsx +++ b/packages/dashboard/stories/components/Shared/CrashUI.tsx @@ -1,5 +1,5 @@ -import { CrashUI as C } from '../../src/Components/ErrorBoundary' -import { story } from '../utils' +import { CrashUI as C } from '@masknet/shared' +import { story } from '@masknet/storybook-shared' const { meta, of } = story(C) export default meta({ diff --git a/packages/dashboard/tsconfig.json b/packages/dashboard/tsconfig.json index 9095416d10f2..886915c80df3 100644 --- a/packages/dashboard/tsconfig.json +++ b/packages/dashboard/tsconfig.json @@ -4,7 +4,7 @@ "rootDir": "./", "outDir": "./dist/" }, - "include": ["./src/", "./stories/", "./src/locales/*.json"], + "include": ["./src/", "./stories/", "./src/**/*.json"], "references": [ { "path": "../theme/" }, { "path": "../maskbook/" }, diff --git a/packages/maskbook/package.json b/packages/maskbook/package.json index 0960dc09aff2..e48e6e6faa65 100644 --- a/packages/maskbook/package.json +++ b/packages/maskbook/package.json @@ -8,8 +8,8 @@ "dependencies": { "@balancer-labs/sor": "^1.0.0", "@dimensiondev/common-protocols": "1.6.0-20201027083702-d0ae6e2", - "@dimensiondev/holoflows-kit": "0.8.0-20210317064617-6c4792c", - "@dimensiondev/kit": "0.0.0-20210221102734-0b4a937", + "@dimensiondev/holoflows-kit": "=0.8.0-20210429202414-74fb9a1", + "@dimensiondev/kit": "=0.0.0-20210630045432-e05621c", "@dimensiondev/metamask-extension-provider": "3.0.6-20210519045409-1835d4d", "@dimensiondev/stego-js": "=0.11.1-20201027083223-8ab41be", "@dimensiondev/uniswap-sdk": "=3.0.4-20210619092641-a270dc0", diff --git a/packages/maskbook/src/UIRoot.tsx b/packages/maskbook/src/UIRoot.tsx index 7544665c4062..6051ccb54e5e 100644 --- a/packages/maskbook/src/UIRoot.tsx +++ b/packages/maskbook/src/UIRoot.tsx @@ -3,7 +3,7 @@ import { StylesProvider } from '@material-ui/styles' import { CssBaseline, StyledEngineProvider, ThemeProvider } from '@material-ui/core' import { Web3Provider } from '@masknet/web3-shared' import { SnackbarProvider } from '@masknet/theme' -import { ErrorBoundary, ErrorBoundaryBuildInfoContext } from '@masknet/theme' +import { ErrorBoundary, ErrorBoundaryBuildInfoContext } from '@masknet/shared' import i18nNextInstance from './utils/i18n-next' import { useClassicMaskTheme } from './utils/theme' import { Web3Context } from './web3/context' diff --git a/packages/maskbook/src/_locales/en/messages.json b/packages/maskbook/src/_locales/en/messages.json index 189136cec79e..41266792f4a5 100644 --- a/packages/maskbook/src/_locales/en/messages.json +++ b/packages/maskbook/src/_locales/en/messages.json @@ -24,7 +24,6 @@ "backup_persona": "Backup Your Persona", "backup_wallet": "Backup Wallet", "backup_wallet_hint": "Keep the private key below carefully in a safe place. You will need them to restore this wallet.", - "block_number": "Block number", "cancel": "Cancel", "comment_box__placeholder": "Add an encrypted comment…", "confirm": "Confirm", @@ -515,6 +514,7 @@ "plugin_ito_dialog_claim_reminder_text4": "THE RIGHTS ARE NOT BEING OFFERED OR SOLD AND MAY NOT BE OFFERED OR SOLD, DIRECTLY OR INDIRECTLY, IN WHOLE OR IN PART, IN JURISDICTIONS OR TO WHOM SUCH AN OFFER WOULD BE UNLAWFUL.", "plugin_ito_expired": "Expired", "plugin_ito_create_new": "New", + "plugin_ito_claim_all_title": "Claim Token", "plugin_ito_claim_all_status_unclaimed": "Unclaimed", "plugin_ito_claim_all_status_locked": "Locked", "plugin_ito_claim_all_unlock_time": "Unlock Time: {{time}}", @@ -535,6 +535,8 @@ "plugin_ito_claim": "Claim", "plugin_ito_claiming": "Claiming...", "plugin_ito_claim_all": "Claim All", + "plugin_ito_claim_all_old_contract": "Old ITO Contract", + "plugin_ito_claim_all_new_contract": "New ITO Contract", "plugin_ito_claimed": "Claimed", "plugin_ito_qualification_start_time": "Qualification Start Time:", "plugin_ito_error_qualification_start_time": "Invalid: Qualification start time should be earlier than ITO end time", diff --git a/packages/maskbook/src/_locales/ja/messages.json b/packages/maskbook/src/_locales/ja/messages.json index 05ba76ad43a8..6d31ef94c0be 100644 --- a/packages/maskbook/src/_locales/ja/messages.json +++ b/packages/maskbook/src/_locales/ja/messages.json @@ -24,7 +24,6 @@ "backup_persona": "ペルソナをバックアップする", "backup_wallet": "ウォレットをバックアップする", "backup_wallet_hint": "以下の 秘密鍵大切に保管します。これがあればウォレットを復元できます。", - "block_number": "ブロック番号", "cancel": "取り消す", "comment_box__placeholder": "コメントを暗号化するには…", "confirm": "確認する", @@ -515,6 +514,7 @@ "plugin_ito_dialog_claim_reminder_text4": "本権利は裁判において、もしくは正当な請求ではないと判断される者に対して、全体もしくは一部、直接的もしくは間接的に提供または販売されておらず、今後されることもありません。", "plugin_ito_expired": "期限切れ", "plugin_ito_create_new": "新しいもの", + "plugin_ito_claim_all_title": "", "plugin_ito_claim_all_status_unclaimed": "未請求", "plugin_ito_claim_all_status_locked": "ロックされています", "plugin_ito_claim_all_unlock_time": "ロック解除:{{time}}", @@ -535,6 +535,8 @@ "plugin_ito_claim": "請求", "plugin_ito_claiming": "請求中", "plugin_ito_claim_all": "全て請求", + "plugin_ito_claim_all_old_contract": "", + "plugin_ito_claim_all_new_contract": "", "plugin_ito_claimed": "請求しました", "plugin_ito_qualification_start_time": "参加資格開始時間:", "plugin_ito_error_qualification_start_time": "無効:資格開始時間は ITO の終了時間よりも前でなくてはいけません", diff --git a/packages/maskbook/src/_locales/ko/messages.json b/packages/maskbook/src/_locales/ko/messages.json index 596957bb0463..bfcecf09f481 100644 --- a/packages/maskbook/src/_locales/ko/messages.json +++ b/packages/maskbook/src/_locales/ko/messages.json @@ -24,7 +24,6 @@ "backup_persona": "페르소나 백업", "backup_wallet": "지갑 백업", "backup_wallet_hint": "아래의 개인 키를 안전한 곳에 저장하세요 . 개인 키만으로 지갑을 초기화할 수 있습니다.", - "block_number": "불록번호", "cancel": "취소", "comment_box__placeholder": "암호화된 코멘트 추가", "confirm": "확인", @@ -515,6 +514,7 @@ "plugin_ito_dialog_claim_reminder_text4": "THE RIGHTS ARE NOT BEING OFFERED OR SOLD AND MAY NOT BE OFFERED OR SOLD, DIRECTLY OR INDIRECTLY, IN WHOLE OR IN PART, IN JURISDICTIONS OR TO WHOM SUCH AN OFFER WOULD BE UNLAWFUL", "plugin_ito_expired": "만료됨", "plugin_ito_create_new": "새로", + "plugin_ito_claim_all_title": "", "plugin_ito_claim_all_status_unclaimed": "수령되지 않음", "plugin_ito_claim_all_status_locked": "락", "plugin_ito_claim_all_unlock_time": "언락 시간: {{time}}", @@ -535,6 +535,8 @@ "plugin_ito_claim": "수령", "plugin_ito_claiming": "수령 중", "plugin_ito_claim_all": "모두 수령", + "plugin_ito_claim_all_old_contract": "", + "plugin_ito_claim_all_new_contract": "", "plugin_ito_claimed": "수령됨", "plugin_ito_qualification_start_time": "자격 인정 시작 시간", "plugin_ito_error_qualification_start_time": "주의: 자격 인정 시작 시간이 ITO 종료 시간보다 빨아야 합니다.", diff --git a/packages/maskbook/src/_locales/zh/messages.json b/packages/maskbook/src/_locales/zh/messages.json index e51a5954fc07..5efa1ecd77af 100644 --- a/packages/maskbook/src/_locales/zh/messages.json +++ b/packages/maskbook/src/_locales/zh/messages.json @@ -24,7 +24,6 @@ "backup_persona": "備份你的角色", "backup_wallet": "備份錢包", "backup_wallet_hint": "將私密金鑰放在安全的地方。你需要他來復原這個錢包", - "block_number": "區塊編號", "cancel": "取消", "comment_box__placeholder": "添加加密留言…", "confirm": "確認", @@ -515,6 +514,7 @@ "plugin_ito_dialog_claim_reminder_text4": "該等權利並未在司法管轄區內全部或部分提供或出售,也不得直接或間接提供或出售,或向其提供或出售該等權利將是非法的。", "plugin_ito_expired": "已過期", "plugin_ito_create_new": "新增", + "plugin_ito_claim_all_title": "", "plugin_ito_claim_all_status_unclaimed": "未被認領", "plugin_ito_claim_all_status_locked": "已鎖定", "plugin_ito_claim_all_unlock_time": "解鎖時間:{{time}}", @@ -535,6 +535,8 @@ "plugin_ito_claim": "認領", "plugin_ito_claiming": "認領中", "plugin_ito_claim_all": "認領全部", + "plugin_ito_claim_all_old_contract": "", + "plugin_ito_claim_all_new_contract": "", "plugin_ito_claimed": "已認領", "plugin_ito_qualification_start_time": "資格開始時間:", "plugin_ito_error_qualification_start_time": "錯誤:資格開始時間應早於 ITO 結束時間", diff --git a/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx b/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx index f13a4b3c0225..0e3f7e5c9f05 100644 --- a/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx +++ b/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx @@ -1,5 +1,6 @@ -import { useMemo, useState, useEffect, useReducer, Fragment } from 'react' -import { unreachable, makeTypedMessageTuple, TypedMessageTuple } from '@masknet/shared' +import { Fragment, useEffect, useMemo, useReducer, useState } from 'react' +import { makeTypedMessageTuple, TypedMessageTuple } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import { delay } from '../../../utils/utils' import { ServicesWithProgress } from '../../../extension/service' @@ -11,8 +12,8 @@ import type { SuccessDecryption, } from '../../../extension/background-script/CryptoServices/decryptFrom' import { DecryptPostSuccess, DecryptPostSuccessProps } from './DecryptedPostSuccess' -import { DecryptPostAwaitingProps, DecryptPostAwaiting } from './DecryptPostAwaiting' -import { DecryptPostFailedProps, DecryptPostFailed } from './DecryptPostFailed' +import { DecryptPostAwaiting, DecryptPostAwaitingProps } from './DecryptPostAwaiting' +import { DecryptPostFailed, DecryptPostFailedProps } from './DecryptPostFailed' import { DecryptedPostDebug } from './DecryptedPostDebug' import { usePostClaimedAuthor, usePostInfoDetails, usePostInfoSharedPublic } from '../../DataSource/usePostInfo' import { asyncIteratorWithResult } from '../../../utils/type-transform/asyncIteratorHelpers' @@ -65,7 +66,7 @@ export function DecryptPost(props: DecryptPostProps) { const { whoAmI, profiles, alreadySelectedPreviously, onDecrypted } = props const deconstructedPayload = usePostInfoDetails.postPayload() const authorInPayload = usePostClaimedAuthor() - const current = usePostInfo() + const current = usePostInfo()! const currentPostBy = usePostInfoDetails.postBy() const decryptedPayloadForImage = usePostInfoDetails.decryptedPayloadForImage() const postBy = or(authorInPayload, currentPostBy) diff --git a/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx b/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx index 159e7020b419..751668841959 100644 --- a/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx +++ b/packages/maskbook/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx @@ -90,7 +90,7 @@ function OldPluginSuccessDecryptionPostInspectorForEach(props: { pluginConfig: P const post = usePostInfo() useEffect(() => { if (!ref.current || !F || typeof F === 'function') return - return F.init(post, { message }, ref.current) + return F.init(post!, { message }, ref.current) }, [F, post, message]) if (!F) return null if (typeof F === 'function') return diff --git a/packages/maskbook/src/components/InjectedComponents/PostInspector.tsx b/packages/maskbook/src/components/InjectedComponents/PostInspector.tsx index 29f93b28a47a..14c80ceb8e0f 100644 --- a/packages/maskbook/src/components/InjectedComponents/PostInspector.tsx +++ b/packages/maskbook/src/components/InjectedComponents/PostInspector.tsx @@ -143,7 +143,7 @@ function PluginPostInspectorForEach({ config }: { config: PluginConfig }) { const post = usePostInfo() useEffect(() => { if (!ref.current || !F || typeof F === 'function') return - return F.init(post, {}, ref.current) + return F.init(post!, {}, ref.current) }, [F, post]) if (!F) return null if (typeof F === 'function') return diff --git a/packages/maskbook/src/components/InjectedComponents/SteganographyTextPayload.ts b/packages/maskbook/src/components/InjectedComponents/SteganographyTextPayload.ts index 285ca47f4872..df1b18b3eb22 100644 --- a/packages/maskbook/src/components/InjectedComponents/SteganographyTextPayload.ts +++ b/packages/maskbook/src/components/InjectedComponents/SteganographyTextPayload.ts @@ -1,4 +1,4 @@ -import { decodeArrayBuffer } from '@dimensiondev/kit' +import { blobToArrayBuffer, decodeArrayBuffer } from '@dimensiondev/kit' import { GrayscaleAlgorithm } from '@dimensiondev/stego-js/esm/grayscale' import Services from '../../extension/service' import { ImageTemplateTypes, ImagePayloadURLs } from '../../resources/image-payload' @@ -7,7 +7,7 @@ import { downloadUrl } from '../../utils/utils' export async function SteganographyTextPayload(template: ImageTemplateTypes, text: string) { const pass = activatedSocialNetworkUI.configuration.steganography?.password?.() || 'mask' - const blankImage = await downloadUrl(ImagePayloadURLs[template]).then((x) => x.arrayBuffer()) + const blankImage = await downloadUrl(ImagePayloadURLs[template]).then(blobToArrayBuffer) const secretImage = new Uint8Array( decodeArrayBuffer( await Services.Steganography.encodeImage(new Uint8Array(blankImage), { diff --git a/packages/maskbook/src/components/InjectedComponents/Toolbar.tsx b/packages/maskbook/src/components/InjectedComponents/Toolbar.tsx deleted file mode 100644 index 300f4b9739e4..000000000000 --- a/packages/maskbook/src/components/InjectedComponents/Toolbar.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { makeStyles, Paper } from '@material-ui/core' -import { useStylesExtends } from '../custom-ui-helper' - -const useStyle = makeStyles((theme) => { - return { - root: { - borderRadius: 0, - position: 'relative', - }, - } -}) - -export interface ToolbarProps extends withClasses<'root'> { - children: React.ReactNode -} - -export function Toolbar(props: ToolbarProps) { - const classes = useStylesExtends(useStyle(), props) - - return ( - - {props.children} - - ) -} diff --git a/packages/maskbook/src/components/InjectedComponents/ToolbarAtTwitter.tsx b/packages/maskbook/src/components/InjectedComponents/ToolbarAtTwitter.tsx deleted file mode 100644 index 3fa5e24edb13..000000000000 --- a/packages/maskbook/src/components/InjectedComponents/ToolbarAtTwitter.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { makeStyles, IconButton } from '@material-ui/core' -import DoubleArrowIcon from '@material-ui/icons/DoubleArrow' -import { useMemo, useState } from 'react' -import classNames from 'classnames' -import { useEffectOnce, useWindowScroll, useWindowSize, useLocation } from 'react-use' -import { MaskbookIcon } from '../../resources/MaskbookIcon' -import { EthereumAccountButton } from '../../web3/UI/EthereumAccountButton' -import { EthereumMaskBalanceButton } from '../../web3/UI/EthereumMaskBalanceButton' -import { Toolbar } from './Toolbar' - -export const TOOLBAR_STICKY_POSITION = 300 -export const TOOLBAR_STICKY_ANIMATION_DISTANCE = 150 -export const TOOLBAR_HEIGHT = 54 - -const useStyles = makeStyles((theme) => { - return { - root: { - height: TOOLBAR_HEIGHT, - borderRadius: 0, - position: 'relative', - borderBottom: `1px solid ${theme.palette.divider}`, - }, - rootSticky: { - zIndex: 1, - left: '0 !important', - width: '100% !important', - position: 'fixed', - backgroundColor: theme.palette.background.paper, - boxShadow: `${ - theme.palette.mode === 'dark' - ? 'rgba(255, 255, 255, 0.2) 0px 0px 15px, rgba(255, 255, 255, 0.15) 0px 0px 3px 1px' - : 'rgba(101, 119, 134, 0.2) 0px 0px 15px, rgba(101, 119, 134, 0.15) 0px 0px 3px 1px' - }`, - }, - content: { - position: 'relative', - display: 'flex', - alignItems: 'center', - }, - left: { - height: TOOLBAR_HEIGHT, - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - padding: '0 10px', - boxSizing: 'border-box', - ['@media (min-width: 600)']: { - padding: '0 5px', - }, - }, - right: { - height: TOOLBAR_HEIGHT, - display: 'flex', - alignItems: 'center', - }, - logo: { - width: 36, - height: 36, - }, - accountButton: { - marginLeft: theme.spacing(1), - }, - maskBalanceButton: { - marginRight: theme.spacing(1), - }, - sizeButton: { - marginLeft: theme.spacing(1), - marginRight: theme.spacing(1), - }, - rotate: { - transform: 'rotate(-180deg)', - }, - rootStickyShrink: { - left: '10px !important', - position: 'fixed', - backgroundColor: theme.palette.background.paper, - height: TOOLBAR_HEIGHT, - }, - } -}) - -export interface ToolbarAtTwitterProps {} - -export function ToolbarAtTwitter(props: ToolbarAtTwitterProps) { - const classes = useStyles() - const location = useLocation() - const isPhotoPage = /\/status\/\d+\/photo\/\d+$/.test(location.pathname ?? '') - const [isExpand, setExpand] = useState(false) - - // inject global css - useEffectOnce(() => { - const sidebarResetStyle = document.createElement('style') - sidebarResetStyle.innerHTML = ` - [data-testid="sidebarColumn"] > div:first-child > div:nth-child(2) > div:first-child > div:first-child > div:first-child { - padding-top: 10px; - } - [data-testid="sidebarColumn"] > div:first-child > div:nth-child(2) > div:first-child > div:first-child > div:first-child > div:nth-child(2) { - display: none; - } - ` - document.querySelector('head')?.appendChild(sidebarResetStyle) - }) - - //#region compute toolbar status according to scroll position - const { y } = useWindowScroll() - const isSticky = y - TOOLBAR_STICKY_POSITION > 0 - //#endregion - - //#region resize toolbar - const { width: windowWidth } = useWindowSize() - const { left, right, width, menuWidth, mainWidth } = useMemo(() => { - const menu = document.querySelector('[role="banner"] > div:first-child > div:first-child') - const main = document.querySelector('[role="main"] > div:first-child') - const { width: menuWidth = 0, left: menuLeft = 0 } = menu ? menu.getBoundingClientRect() : {} - const { width: mainWidth = 0 } = main ? main.getBoundingClientRect() : {} - return { - left: menuLeft, - right: 'auto', - width: menuWidth + mainWidth, - menuWidth, - mainWidth, - } - }, [windowWidth]) - //#endregion - - // There's an animation effect when click button which would keep showing after expanded or shrinked, - // so re-render IconButton immediately when isExpand changes. - const IconButtonMemo = useMemo( - () => () => - ( - setExpand(!isExpand)} - color="primary" - className={classNames(classes.sizeButton, isExpand ? classes.rotate : '')}> - - - ), - [isExpand], - ) - - return isPhotoPage ? null : ( - -
-
- {isExpand ? ( -
- -
- ) : null} -
- - {isExpand ? : null} - -
-
-
-
- ) -} diff --git a/packages/maskbook/src/components/InjectedComponents/ToolboxHint.tsx b/packages/maskbook/src/components/InjectedComponents/ToolboxHint.tsx index af5bff00b0a5..783b1b5d2d0a 100644 --- a/packages/maskbook/src/components/InjectedComponents/ToolboxHint.tsx +++ b/packages/maskbook/src/components/InjectedComponents/ToolboxHint.tsx @@ -1,12 +1,13 @@ -import { makeStyles, Typography, MenuItem } from '@material-ui/core' +import { makeStyles, MenuItem, Typography } from '@material-ui/core' import classNames from 'classnames' import { - useAccount, - useChainId, + formatEthereumAddress, + NetworkType, resolveChainColor, + useAccount, useChainDetailed, + useChainId, useChainIdValid, - NetworkType, } from '@masknet/web3-shared' import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord' import { MaskbookSharpIconOfSize, WalletSharp } from '../../resources/MaskbookIcon' @@ -16,7 +17,7 @@ import { useMenu } from '../../utils/hooks/useMenu' import { useCallback } from 'react' import { MaskMessage } from '../../utils/messages' import { RedPacketPluginID } from '../../plugins/RedPacket/constants' -import { FileServiceCompositionEntry } from '../../plugins/FileService/UI-define' +import { FileServicePluginID } from '../../plugins/FileService/constants' import { ITO_CompositionEntry } from '../../plugins/ITO/define' import { useControlledDialog } from '../../plugins/Collectible/SNSAdaptor/useControlledDialog' import { useRemoteControlledDialog } from '../../utils/hooks/useRemoteControlledDialog' @@ -27,7 +28,7 @@ import { Flags } from '../../utils/flags' import { useStylesExtends } from '../custom-ui-helper' import { ClaimAllDialog } from '../../plugins/ITO/UI/ClaimAllDialog' import { WalletIcon } from '../shared/WalletIcon' -import { formatEthereumAddress, useValueRef } from '@masknet/shared' +import { useValueRef } from '@masknet/shared' import { useI18N } from '../../utils' import { currentNetworkSettings } from '../../plugins/Wallet/settings' @@ -164,7 +165,7 @@ export function ToolboxHint(props: ToolboxHintProps) { const openFileService = useCallback(() => { openEncryptedMessage() setTimeout(() => { - FileServiceCompositionEntry.onClick() + MaskMessage.events.activatePluginCompositionEntry.sendToLocal(FileServicePluginID) }) }, [openEncryptedMessage]) //#endregion diff --git a/packages/maskbook/src/components/shared-settings/useSettingsUI.tsx b/packages/maskbook/src/components/shared-settings/useSettingsUI.tsx index 11b707b2f152..fba3c0bb6f7b 100644 --- a/packages/maskbook/src/components/shared-settings/useSettingsUI.tsx +++ b/packages/maskbook/src/components/shared-settings/useSettingsUI.tsx @@ -1,5 +1,6 @@ import type { ValueRef } from '@dimensiondev/holoflows-kit' -import { useValueRef, getEnumAsArray } from '@masknet/shared' +import { useValueRef } from '@masknet/shared' +import { getEnumAsArray } from '@dimensiondev/kit' import { ListItem, ListItemIcon, diff --git a/packages/maskbook/src/components/shared/ErrorBoundary.tsx b/packages/maskbook/src/components/shared/ErrorBoundary.tsx index 0eaa0e7cdd78..581aca2b7081 100644 --- a/packages/maskbook/src/components/shared/ErrorBoundary.tsx +++ b/packages/maskbook/src/components/shared/ErrorBoundary.tsx @@ -1 +1 @@ -export { ErrorBoundary, withErrorBoundary } from '@masknet/theme' +export { ErrorBoundary, withErrorBoundary } from '@masknet/shared' diff --git a/packages/maskbook/src/components/shared/InjectedDialog.tsx b/packages/maskbook/src/components/shared/InjectedDialog.tsx index 7f3ad8bddb87..20a543799212 100644 --- a/packages/maskbook/src/components/shared/InjectedDialog.tsx +++ b/packages/maskbook/src/components/shared/InjectedDialog.tsx @@ -16,7 +16,7 @@ import { Children, cloneElement } from 'react' import { useI18N, usePortalShadowRoot } from '../../utils' import { mergeClasses, useStylesExtends } from '../custom-ui-helper' import { DialogDismissIconUI } from '../InjectedComponents/DialogDismissIcon' -import { ErrorBoundary } from '@masknet/theme' +import { ErrorBoundary } from '@masknet/shared' import { activatedSocialNetworkUI } from '../../social-network' const useStyles = makeStyles((theme) => ({ diff --git a/packages/maskbook/src/components/shared/SelectWallet/WalletInList.tsx b/packages/maskbook/src/components/shared/SelectWallet/WalletInList.tsx index 995ed5a217b4..d9829ed557e9 100644 --- a/packages/maskbook/src/components/shared/SelectWallet/WalletInList.tsx +++ b/packages/maskbook/src/components/shared/SelectWallet/WalletInList.tsx @@ -1,17 +1,16 @@ import { Avatar, ListItem, + ListItemAvatar, + ListItemIcon, ListItemText, + ListTypeMap, makeStyles, Theme, - ListTypeMap, - ListItemAvatar, - ListItemIcon, } from '@material-ui/core' import CheckIcon from '@material-ui/icons/Check' import type { DefaultComponentProps } from '@material-ui/core/OverridableComponent' -import { Wallet, useBlockie } from '@masknet/web3-shared' -import { formatEthereumAddress } from '@masknet/shared' +import { formatEthereumAddress, useBlockie, Wallet } from '@masknet/web3-shared' import { useI18N } from '../../../utils' import { useStylesExtends } from '../../custom-ui-helper' diff --git a/packages/maskbook/src/database/Persona/consistency.ts b/packages/maskbook/src/database/Persona/consistency.ts index a3ba6ad193e0..5903cc5ebad1 100644 --- a/packages/maskbook/src/database/Persona/consistency.ts +++ b/packages/maskbook/src/database/Persona/consistency.ts @@ -1,8 +1,8 @@ import type { FullPersonaDBTransaction } from './Persona.db' -import { ProfileIdentifier, PersonaIdentifier, Identifier, ECKeyIdentifier } from '../type' +import { ECKeyIdentifier, Identifier, PersonaIdentifier, ProfileIdentifier } from '../type' import type { IdentifierMap } from '../IdentifierMap' import { restorePrototype } from '../../utils/type' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' type ReadwriteFullPersonaDBTransaction = FullPersonaDBTransaction<'readwrite'> diff --git a/packages/maskbook/src/database/helpers/avatar.ts b/packages/maskbook/src/database/helpers/avatar.ts index 1f129c1d3a69..b56cb3945539 100644 --- a/packages/maskbook/src/database/helpers/avatar.ts +++ b/packages/maskbook/src/database/helpers/avatar.ts @@ -3,6 +3,7 @@ import { queryAvatarDB, isAvatarOutdatedDB, storeAvatarDB } from '../avatar' import { memoizePromise } from '../../utils/memoize' import { MaskMessage } from '../../utils/messages' import { downloadUrl } from '../../utils/utils' +import { blobToArrayBuffer, blobToDataURL } from '@dimensiondev/kit' /** * Get a (cached) blob url for an identifier. @@ -12,20 +13,11 @@ export const queryAvatarDataURL = memoizePromise( async function (identifier: ProfileIdentifier | GroupIdentifier): Promise { const buffer = await queryAvatarDB(identifier) if (!buffer) throw new Error('Avatar not found') - return ArrayBufferToBase64(buffer) + return blobToDataURL(new Blob([buffer], { type: 'image/png' })) }, (id) => id.toText(), ) -function ArrayBufferToBase64(buffer: ArrayBuffer) { - const f = new Blob([buffer], { type: 'image/png' }) - const fr = new FileReader() - return new Promise((resolve) => { - fr.onload = () => resolve(fr.result as string) - fr.readAsDataURL(f) - }) -} - /** * Store an avatar with a url for an identifier. * @param identifier - This avatar belongs to. @@ -43,7 +35,7 @@ export async function storeAvatar( if (typeof avatar === 'string') { if (avatar.startsWith('http') === false) return if (force || (await isAvatarOutdatedDB(identifier, 'lastUpdateTime'))) { - await storeAvatarDB(identifier, await (await downloadUrl(avatar)).arrayBuffer()) + await storeAvatarDB(identifier, await blobToArrayBuffer(await downloadUrl(avatar))) } // else do nothing } else { diff --git a/packages/maskbook/src/extension/background-script/CryptoServices/prepareRecipientDetail.ts b/packages/maskbook/src/extension/background-script/CryptoServices/prepareRecipientDetail.ts index c6082f555b78..68255b46b2e2 100644 --- a/packages/maskbook/src/extension/background-script/CryptoServices/prepareRecipientDetail.ts +++ b/packages/maskbook/src/extension/background-script/CryptoServices/prepareRecipientDetail.ts @@ -1,10 +1,10 @@ -import { ProfileIdentifier, GroupIdentifier } from '../../../database/type' +import { GroupIdentifier, ProfileIdentifier } from '../../../database/type' import { queryPublicKey } from '../../../database' import { IdentifierMap } from '../../../database/IdentifierMap' import type { RecipientDetail, RecipientReason } from '../../../database/post' import { queryUserGroup } from '../UserGroupService' import type { EC_Public_JsonWebKey } from '../../../modules/CryptoAlgorithm/interfaces/utils' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' export async function prepareRecipientDetail(to: (ProfileIdentifier | GroupIdentifier)[]) { const recipients = new IdentifierMap(new Map(), ProfileIdentifier) diff --git a/packages/maskbook/src/extension/background-script/EthereumService.ts b/packages/maskbook/src/extension/background-script/EthereumService.ts index 309536dce81e..40d1c79c7f20 100644 --- a/packages/maskbook/src/extension/background-script/EthereumService.ts +++ b/packages/maskbook/src/extension/background-script/EthereumService.ts @@ -3,4 +3,3 @@ export * from './EthereumServices/network' export * from './EthereumServices/provider' export * from './EthereumServices/tokenList' export * from './EthereumServices/nonce' -export * from './EthereumServices/chainState' diff --git a/packages/maskbook/src/extension/background-script/EthereumServices/chainState.ts b/packages/maskbook/src/extension/background-script/EthereumServices/chainState.ts deleted file mode 100644 index 1684e1921d0a..000000000000 --- a/packages/maskbook/src/extension/background-script/EthereumServices/chainState.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { debounce } from 'lodash-es' -import { ChainId, ProviderType, getNetworkTypeFromChainId } from '@masknet/web3-shared' -import { WalletMessages } from '../../../plugins/Wallet/messages' -import { - currentBlockNumberSettings, - currentBalanceSettings, - currentChainIdSettings, - currentProviderSettings, - currentNetworkSettings, - currentAccountSettings, -} from '../../../plugins/Wallet/settings' -import { pollingTask } from '../../../utils/utils' -import { getBalance, getBlockNumber } from './network' -import { startEffects } from '../../../utils/side-effects' -import { getWalletCached } from './wallet' -import { resetAllNonce } from './nonce' - -const effect = startEffects(import.meta.webpackHot) - -//#region tracking chain state -const updateChainState = debounce( - async (chainId?: ChainId) => { - // update network type - if (chainId) currentNetworkSettings.value = getNetworkTypeFromChainId(chainId) - - // update chat state - const wallet = getWalletCached() - currentBlockNumberSettings.value = await getBlockNumber() - if (wallet) currentBalanceSettings.value = await getBalance(wallet.address) - - // reset the polling if chain state updated successfully - if (typeof resetPoolTask === 'function') resetPoolTask() - }, - 3 /* seconds */ * 1000 /* milliseconds */, - { - trailing: true, - }, -) - -// polling the newest chain state -let resetPoolTask: () => void -effect(() => { - const { reset } = pollingTask( - async () => { - await updateChainState() - return false // never stop the polling - }, - { - delay: 30 /* seconds */ * 1000 /* milliseconds */, - }, - ) - resetPoolTask = reset - return reset -}) - -// revalidate ChainState if the chainId of current provider was changed -effect(() => - currentChainIdSettings.addListener((chainId) => { - updateChainState(chainId) - if (currentProviderSettings.value === ProviderType.Maskbook) resetAllNonce() - }), -) - -// revaldiate if the current wallet was changed -effect(() => - currentAccountSettings.addListener(() => { - updateChainState() - }), -) -//#endregion - -// revaldiate if the current wallet was updated -effect(() => WalletMessages.events.walletsUpdated.on(() => updateChainState())) -//#endregion diff --git a/packages/maskbook/src/extension/background-script/EthereumServices/send.ts b/packages/maskbook/src/extension/background-script/EthereumServices/send.ts index eb754c083cde..7bc047002505 100644 --- a/packages/maskbook/src/extension/background-script/EthereumServices/send.ts +++ b/packages/maskbook/src/extension/background-script/EthereumServices/send.ts @@ -2,13 +2,12 @@ import type { HttpProvider, TransactionConfig } from 'web3-core' import type { JsonRpcPayload, JsonRpcResponse } from 'web3-core-helpers' import { addGasMargin, EthereumMethodType, ProviderType } from '@masknet/web3-shared' import type { IJsonRpcRequest } from '@walletconnect/types' -import { safeUnreachable } from '@masknet/shared' +import { safeUnreachable } from '@dimensiondev/kit' import { createWeb3 } from './web3' import * as WalletConnect from './providers/WalletConnect' import { currentAccountSettings, currentProviderSettings } from '../../../plugins/Wallet/settings' -import { addRecentTransaction } from '../../../plugins/Wallet/services' +import { addRecentTransaction, getWallet } from '../../../plugins/Wallet/services' import { commitNonce, getNonce, resetNonce } from './nonce' -import { getWalletCached } from './wallet' import { getGasPrice } from './network' import { EthereumAddress } from 'wallet.ts' @@ -26,10 +25,13 @@ export async function INTERNAL_send( console.log(new Error().stack) } - const web3 = createWeb3() const account = currentAccountSettings.value - const provider = web3.currentProvider as HttpProvider | undefined const providerType = currentProviderSettings.value + const wallet = providerType === ProviderType.Maskbook ? await getWallet() : null + const web3 = createWeb3({ + privKeys: wallet?._private_key_ ? [wallet._private_key_] : [], + }) + const provider = web3.currentProvider as HttpProvider | undefined // unable to create provider if (!provider) { @@ -92,7 +94,6 @@ export async function INTERNAL_send( // send the transaction switch (providerType) { case ProviderType.Maskbook: - const wallet = getWalletCached() const _private_key_ = wallet?._private_key_ if (!wallet || !_private_key_) throw new Error('Unable to sign transaction.') diff --git a/packages/maskbook/src/extension/background-script/EthereumServices/tokenList.ts b/packages/maskbook/src/extension/background-script/EthereumServices/tokenList.ts index 64c7b5b3f341..e7c1a18a48d1 100644 --- a/packages/maskbook/src/extension/background-script/EthereumServices/tokenList.ts +++ b/packages/maskbook/src/extension/background-script/EthereumServices/tokenList.ts @@ -1,6 +1,11 @@ import { memoizePromise } from '@dimensiondev/kit' -import { formatEthereumAddress } from '@masknet/shared' -import { EthereumTokenType, ChainId, ERC20TokenDetailed, getChainDetailed } from '@masknet/web3-shared' +import { + ChainId, + ERC20TokenDetailed, + EthereumTokenType, + formatEthereumAddress, + getChainDetailed, +} from '@masknet/web3-shared' interface TokenList { keywords: string[] @@ -13,6 +18,7 @@ interface TokenList { name: string symbol: string decimals: number + logoURI?: string }[] version: { major: number diff --git a/packages/maskbook/src/extension/background-script/EthereumServices/web3.ts b/packages/maskbook/src/extension/background-script/EthereumServices/web3.ts index 4e275fcf4bed..02ecf3d03e0d 100644 --- a/packages/maskbook/src/extension/background-script/EthereumServices/web3.ts +++ b/packages/maskbook/src/extension/background-script/EthereumServices/web3.ts @@ -1,21 +1,20 @@ import { ProviderType } from '@masknet/web3-shared' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import * as Maskbook from './providers/Maskbook' import * as MetaMask from './providers/MetaMask' import * as WalletConnect from './providers/WalletConnect' import { currentChainIdSettings, currentProviderSettings } from '../../../plugins/Wallet/settings' -import { getWalletCached } from './wallet' export function createWeb3({ chainId = currentChainIdSettings.value, providerType = currentProviderSettings.value, + privKeys = [] as string[], } = {}) { switch (providerType) { case ProviderType.Maskbook: - const _private_key_ = getWalletCached()?._private_key_ return Maskbook.createWeb3({ chainId, - privKeys: _private_key_ ? [_private_key_] : [], + privKeys, }) case ProviderType.MetaMask: return MetaMask.createWeb3() diff --git a/packages/maskbook/src/extension/background-script/SteganographyService.ts b/packages/maskbook/src/extension/background-script/SteganographyService.ts index 9b64e41ad0ae..1048e54fe092 100644 --- a/packages/maskbook/src/extension/background-script/SteganographyService.ts +++ b/packages/maskbook/src/extension/background-script/SteganographyService.ts @@ -5,10 +5,10 @@ import type { EncodeOptions, DecodeOptions } from '@dimensiondev/stego-js/cjs/st import { downloadUrl } from '../../utils/utils' import { memoizePromise } from '../../utils/memoize' import { getDimension } from '../../utils/image' -import { decodeArrayBuffer, encodeArrayBuffer } from '../../utils/type-transform/String-ArrayBuffer' - +import { decodeArrayBuffer, encodeArrayBuffer, blobToArrayBuffer } from '@dimensiondev/kit' import { assertEnvironment, Environment } from '@dimensiondev/holoflows-kit' import type { ImageTemplateTypes } from '../../resources/image-payload' + assertEnvironment(Environment.ManifestBackground) type Mask = 'v1' | 'v2' | 'v4' | 'transparent' @@ -62,7 +62,7 @@ const images: Record = { v4: new URL('./SteganographyResources/mask-v4.png', import.meta.url).toString(), transparent: new URL('./SteganographyResources/mask-transparent.png', import.meta.url).toString(), } -const getMaskBuf = memoizePromise(async (type: Mask) => (await downloadUrl(images[type])).arrayBuffer(), void 0) +const getMaskBuf = memoizePromise(async (type: Mask) => blobToArrayBuffer(await downloadUrl(images[type])), void 0) type EncodeImageOptions = { template?: ImageTemplateTypes @@ -99,5 +99,5 @@ export async function decodeImage(buf: string | ArrayBuffer, options: DecodeImag } export async function decodeImageUrl(url: string, options: DecodeImageOptions) { - return decodeImage(await (await downloadUrl(url)).arrayBuffer(), options) + return decodeImage(await blobToArrayBuffer(await downloadUrl(url)), options) } diff --git a/packages/maskbook/src/extension/background-script/WelcomeServices/restoreBackup.ts b/packages/maskbook/src/extension/background-script/WelcomeServices/restoreBackup.ts index c56a50ba0c5a..d778935b4a08 100644 --- a/packages/maskbook/src/extension/background-script/WelcomeServices/restoreBackup.ts +++ b/packages/maskbook/src/extension/background-script/WelcomeServices/restoreBackup.ts @@ -51,9 +51,9 @@ export async function restoreBackup(json: object, whoAmI?: ProfileIdentifier) { }) } - for (const x of data.wallets) { + for (const [i, x] of data.wallets.entries()) { const record = WalletRecordFromJSONFormat(x) - if (record.mnemonic || record._private_key_) await importNewWallet(record) + if (record.mnemonic || record._private_key_) await importNewWallet(record, i !== 0) } for (const x of data.posts) { diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/CollectibleList/index.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/CollectibleList/index.tsx index e33281d56dfa..9a757560994b 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/CollectibleList/index.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/CollectibleList/index.tsx @@ -1,5 +1,5 @@ -import { formatEthereumAddress, useValueRef } from '@masknet/shared' -import { EthereumTokenType, useAccount, Wallet } from '@masknet/web3-shared' +import { useValueRef } from '@masknet/shared' +import { EthereumTokenType, formatEthereumAddress, useAccount, Wallet } from '@masknet/web3-shared' import { Box, Button, makeStyles, Skeleton, TablePagination, Typography } from '@material-ui/core' import { createContext, useState } from 'react' import { useUpdateEffect } from 'react-use' diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/DatabasePreviewCard.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/DatabasePreviewCard.tsx index b62a2f807b72..9996c7301092 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/DatabasePreviewCard.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/DatabasePreviewCard.tsx @@ -1,8 +1,8 @@ import classNames from 'classnames' import CheckCircleOutlineIcon from '@material-ui/icons/CheckCircleOutline' import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked' -import { Table, TableBody, TableRow, TableCell, Typography, makeStyles, Theme } from '@material-ui/core' -import { unreachable } from '@masknet/shared' +import { makeStyles, Table, TableBody, TableCell, TableRow, Theme, Typography } from '@material-ui/core' +import { unreachable } from '@dimensiondev/kit' import { useI18N } from '../../../utils' import { useStylesExtends } from '../../../components/custom-ui-helper' diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/FixedTokenList.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/FixedTokenList.tsx index cf3f1cb09f4a..02d79cb43469 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/FixedTokenList.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/FixedTokenList.tsx @@ -1,7 +1,9 @@ import { currySameAddress, - EthereumTokenType, + useERC20TokensDetailedFromTokenLists, + TokenListsState, FungibleTokenDetailed, + EthereumTokenType, isSameAddress, useEthereumConstants, useTokenConstants, @@ -11,10 +13,6 @@ import { uniqBy } from 'lodash-es' import { useState } from 'react' import { FixedSizeList, FixedSizeListProps } from 'react-window' import { useStylesExtends } from '../../../components/custom-ui-helper' -import { - TokenListsState, - useERC20TokensDetailedFromTokenLists, -} from '../../../web3/hooks/useERC20TokensDetailedFromTokenLists' import { TokenInList } from './TokenInList' const useStyles = makeStyles((theme) => ({ diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromBackupBox.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromBackupBox.tsx index b6c4eaa3e5e2..7261513a65a6 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromBackupBox.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromBackupBox.tsx @@ -4,6 +4,7 @@ import { makeStyles } from '@material-ui/core' import { useI18N } from '../../../utils' import { useStylesExtends } from '../../../components/custom-ui-helper' import { RestoreBox } from './RestoreBox' +import { blobToText } from '@dimensiondev/kit' const useStyles = makeStyles((theme) => ({ root: { @@ -36,9 +37,7 @@ export function RestoreFromBackupBox(props: RestoreFromBackupBoxProps) { // invoke callback useEffect(() => { if (file) { - const fr = new FileReader() - fr.readAsText(file) - fr.addEventListener('loadend', () => props.onChange?.(file, fr.result as string)) + blobToText(file).then((result) => props.onChange?.(file, result)) } }, [file, props.onChange]) diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromQRCodeImageBox.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromQRCodeImageBox.tsx index 908f56fda621..dbf105bdff3d 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromQRCodeImageBox.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/RestoreFromQRCodeImageBox.tsx @@ -5,6 +5,7 @@ import { useI18N } from '../../../utils' import { RestoreBox } from './RestoreBox' import { useStylesExtends } from '../../../components/custom-ui-helper' import { QRCodeImageScanner } from './QRCodeImageScanner' +import { blobToDataURL } from '@dimensiondev/kit' const useStyles = makeStyles((theme) => ({ root: { @@ -58,10 +59,7 @@ export function RestoreFromQRCodeImageBox(props: RestoreFromQRCodeImageBoxProps) // read file as data URL useEffect(() => { if (file) { - const fr = new FileReader() - fr.readAsDataURL(file) - fr.addEventListener('loadend', () => setDataURL(fr.result as string)) - fr.addEventListener('error', () => setDataURL('')) + blobToDataURL(file).then(setDataURL, () => setDataURL('')) } else { setDataURL('') } diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/TokenIcon.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/TokenIcon.tsx deleted file mode 100644 index a8d8eb18ce6a..000000000000 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/TokenIcon.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { formatEthereumAddress } from '@masknet/shared' -import { ChainId, getChainFullName, getTokenConstants, useBlockie, useChainDetailed } from '@masknet/web3-shared' -import { Avatar, AvatarProps, makeStyles, Theme } from '@material-ui/core' -import { useStylesExtends } from '../../../components/custom-ui-helper' -import { useImageFailover } from '../../../utils/hooks/useImageFailover' - -//#region fix icon image -function resolveTokenIconURL(address: string, baseURI: string) { - const iconMap = { - [getTokenConstants().NATIVE_TOKEN_ADDRESS]: `${baseURI}/info/logo.png`, - '0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074': - 'https://dimensiondev.github.io/Maskbook-VI/assets/Logo/MB--Logo--Geo--ForceCircle--Blue.svg', // MASK - '0x32a7C02e79c4ea1008dD6564b35F131428673c41': 'https://s2.coinmarketcap.com/static/img/coins/64x64/6747.png', // CRUST - '0x04abEdA201850aC0124161F037Efd70c74ddC74C': 'https://s2.coinmarketcap.com/static/img/coins/64x64/5841.png', // NEST - '0x14de81C71B3F73874659082b971433514E201B27': 'https://etherscan.io/token/images/ykyctoken_32.png', // Yes KYC - '0x3B73c1B2ea59835cbfcADade5462b6aB630D9890': - 'https://raw.githubusercontent.com/chainswap/chainswap-assets/main/logo_white_256.png', // TOKEN - } - const checksummedAddress = formatEthereumAddress(address) - if (iconMap[checksummedAddress]) return iconMap[checksummedAddress] - return `${baseURI}/assets/${checksummedAddress}/logo.png` -} -//#endregion - -const useStyles = makeStyles((theme: Theme) => ({ - icon: { - width: 16, - height: 16, - backgroundColor: theme.palette.common.white, - margin: 0, - }, -})) - -export interface TokenIconProps extends withClasses { - name?: string - logoURL?: string - chainId?: ChainId - address: string - AvatarProps?: Partial -} - -export function TokenIcon(props: TokenIconProps) { - const { address, logoURL, name, chainId, AvatarProps } = props - - const classes = useStylesExtends(useStyles(), props) - const chainDetailed = useChainDetailed() - const tokenBlockie = useBlockie(address) - - const fullName = chainDetailed ? getChainFullName(chainId ?? chainDetailed.chainId) : '' - const { value: baseURI, loading } = useImageFailover( - chainDetailed - ? [ - `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/${fullName.toLowerCase()}`, - `https://rawcdn.githack.com/trustwallet/assets/master/blockchains/${fullName.toLowerCase()}`, - ] - : [], - '/info/logo.png', - ) - - if (logoURL) - return ( - - {name?.substr(0, 1).toLocaleUpperCase()} - - ) - return ( - - - {name?.substr(0, 1).toLocaleUpperCase()} - - - ) -} diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/TokenInList.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/TokenInList.tsx index bdec2ad67476..08a3042027d2 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/TokenInList.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/TokenInList.tsx @@ -1,6 +1,6 @@ -import { formatEthereumAddress } from '@masknet/shared' import { currySameAddress, + formatEthereumAddress, FungibleTokenDetailed, resolveTokenLinkOnExplorer, useTokenConstants, @@ -9,12 +9,12 @@ import { Link, ListItem, ListItemIcon, ListItemText, Typography } from '@materia import { makeStyles, Theme } from '@material-ui/core/styles' import OpenInNewIcon from '@material-ui/icons/OpenInNew' import { useCallback } from 'react' -import { TokenIcon } from './TokenIcon' +import { TokenIcon } from '@masknet/shared' const useStyles = makeStyles((theme: Theme) => ({ icon: { - width: 28, - height: 28, + width: 36, + height: 36, }, text: { display: 'flex', @@ -76,7 +76,7 @@ export function TokenInList({ data, index, style }: TokenInListProps) { const token = data.tokens[index] if (!token) return null - const { address, name, symbol } = token + const { address, name, symbol, logoURI } = token return ( data.onSelect(address)}> - + diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/TransactionList/Record.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/TransactionList/Record.tsx index 068a0a79734f..eeafb663c578 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/TransactionList/Record.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/TransactionList/Record.tsx @@ -1,6 +1,6 @@ import { makeStyles, Typography } from '@material-ui/core' import type { FC } from 'react' -import { TokenIcon } from '../TokenIcon' +import { TokenIcon } from '@masknet/shared' import classNames from 'classnames' import type { Transaction } from '../../../../plugins/Wallet/types' import { DebankTransactionDirection, ZerionTransactionDirection } from '../../../../plugins/Wallet/types' diff --git a/packages/maskbook/src/extension/options-page/DashboardComponents/WalletAssetsTable.tsx b/packages/maskbook/src/extension/options-page/DashboardComponents/WalletAssetsTable.tsx index e3cc906eddcd..1c4b4a5e6ee0 100644 --- a/packages/maskbook/src/extension/options-page/DashboardComponents/WalletAssetsTable.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardComponents/WalletAssetsTable.tsx @@ -19,24 +19,26 @@ import BigNumber from 'bignumber.js' import classNames from 'classnames' import ExpandLessIcon from '@material-ui/icons/ExpandLess' import ExpandMoreIcon from '@material-ui/icons/ExpandMore' +import type { Asset } from '@masknet/web3-shared' import { CurrencyType, + currySameAddress, EthereumTokenType, - Wallet, - useStableTokensDebank, - useChainDetailed, + formatBalance, + formatCurrency, getChainIdFromName, - currySameAddress, + isGreaterThan, + useAssets, + useChainDetailed, + useStableTokensDebank, + Wallet, } from '@masknet/web3-shared' import { useStylesExtends } from '../../../components/custom-ui-helper' -import { formatBalance, formatCurrency, FormattedCurrency, isGreaterThan } from '@masknet/shared' -import { useMatchXS, useI18N } from '../../../utils' -import { TokenIcon } from './TokenIcon' +import { FormattedCurrency, TokenIcon } from '@masknet/shared' +import { useI18N, useMatchXS } from '../../../utils' import { ActionsBarFT } from './ActionsBarFT' import { useTrustedERC20TokensFromDB } from '../../../plugins/Wallet/hooks/useERC20Tokens' -import type { Asset } from '../../../plugins/Wallet/types' import { getTokenUSDValue } from '../../../plugins/Wallet/helpers' -import { useAssets } from '../../../plugins/Wallet/hooks/useAssets' const useStyles = makeStyles< Theme, @@ -116,7 +118,7 @@ function ViewDetailed(props: ViewDetailedProps) { chainId={getChainIdFromName(asset.chain)} /> {asset.token.symbol} - {asset.chain !== chainDetailed.chain.toLowerCase() ? ( + {asset.chain !== chainDetailed.shortName.toLowerCase() ? ( ) : null} , diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Base.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Base.tsx index c4d08f5ac411..d14e3ad8d532 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Base.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Base.tsx @@ -272,4 +272,4 @@ export function DashboardDialogWrapper(props: DashboardDialogWrapperProps) { ) } -export { useSnackbarCallback } from '@masknet/theme' +export { useSnackbarCallback } from '@masknet/shared' diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Backup.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Backup.tsx index aa261d523abf..6d15cadd51b9 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Backup.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Backup.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import { User } from 'react-feather' import { useI18N, compressBackupFile, encodeArrayBuffer, encodeText } from '../../../../utils' -import { QRCode } from '@masknet/theme' +import { QRCode } from '@masknet/shared' import Services from '../../../service' import AbstractTab, { AbstractTabProps } from '../../../../components/shared/AbstractTab' import ShowcaseBox from '../../DashboardComponents/ShowcaseBox' diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Create.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Create.tsx index f520dacc2434..68331a24cfb8 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Create.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Persona/Create.tsx @@ -27,7 +27,7 @@ export function DashboardPersonaCreateDialog(props: WrappedDialogProps) { icon={} iconColor="#5FDD97" primary={t('create_a_persona')} - secondary={' '} + secondary=" " content={ <>
@@ -49,9 +49,14 @@ export function DashboardPersonaCreateDialog(props: WrappedDialogProps) { onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault() - createPersonaAndNext() + if (!checkInputLengthExceed(name) && name.length > 0) { + createPersonaAndNext() + } } }} + inputProps={{ + maxlength: WALLET_OR_PERSONA_NAME_MAX_LEN, + }} variant="outlined" />
diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Plugin.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Plugin.tsx index 1318afb10dc9..6b1be2173996 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Plugin.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Plugin.tsx @@ -73,7 +73,7 @@ export function DashboardPluginDetailDialog({ ComponentProps, ...rest }: Wrapped {ComponentProps?.plugin.pluginIcon}} primary={ComponentProps?.plugin.pluginName ?? '-'} - secondary={' '} + secondary=" " content={ diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/HideTokenConfirm.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/HideTokenConfirm.tsx index 5f304ed9b44c..b8264bbd6612 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/HideTokenConfirm.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/HideTokenConfirm.tsx @@ -1,14 +1,14 @@ import { Trash2 as TrashIcon } from 'react-feather' import { Button } from '@material-ui/core' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import { - isNative, ERC1155TokenDetailed, ERC20TokenDetailed, ERC721TokenDetailed, + EthereumTokenType, FungibleTokenDetailed, + isNative, NonFungibleTokenDetailed, - EthereumTokenType, } from '@masknet/web3-shared' import { WalletRPC } from '../../../../plugins/Wallet/messages' import { useI18N } from '../../../../utils' diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/Import.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/Import.tsx index 28d4a54a8503..a3416dd16dea 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/Import.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/Import.tsx @@ -247,12 +247,16 @@ export function DashboardWalletImportDialog(props: WrappedDialogProps) { onCreate(walletName) }, [state[0], walletName, hdWallet?.address, onCreate, onDeriveOrImport]) - const disabled = (() => { - const isFill = - !(state[0] === 1 && walletName && keystoreContent && keystorePassword) && - !(state[0] === 2 && walletName && mnemonic) && - !(state[0] === 3 && walletName && privateKey) - return isFill || checkInputLengthExceed(walletName) + const formInvalid = (() => { + if (walletName.length === 0 || checkInputLengthExceed(walletName)) { + return true + } + const isFilled = + (state[0] === 0 && confirmed) || + (state[0] === 1 && keystoreContent && keystorePassword) || + (state[0] === 2 && mnemonic) || + (state[0] === 3 && privateKey) + return !isFilled })() return ( @@ -264,7 +268,7 @@ export function DashboardWalletImportDialog(props: WrappedDialogProps) { primary={t(state[0] === 0 ? 'plugin_wallet_on_create' : 'import_wallet')} content={} footer={ - + {t(state[0] === 0 ? 'create' : 'import')} } diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/ReceiveTab.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/ReceiveTab.tsx index 50469cb8debe..2a099b94d54f 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/ReceiveTab.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/ReceiveTab.tsx @@ -2,7 +2,7 @@ import { IconButton, InputAdornment, makeStyles, TextField, Theme } from '@mater import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined' import { useCopyToClipboard } from 'react-use' import { useI18N } from '../../../../utils' -import { QRCode } from '@masknet/theme' +import { QRCode } from '@masknet/shared' import type { Wallet } from '@masknet/web3-shared' import { useSnackbarCallback } from '../Base' diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferNFT.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferNFT.tsx index 48759d1e49d4..c826e53f25af 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferNFT.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferNFT.tsx @@ -2,15 +2,15 @@ import { Button, makeStyles, TextField } from '@material-ui/core' import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { EthereumAddress } from 'wallet.ts' import { - useTokenTransferCallback, - TransactionStateType, ERC1155TokenAssetDetailed, ERC721TokenAssetDetailed, + formatEthereumAddress, + TransactionStateType, + useTokenTransferCallback, } from '@masknet/web3-shared' -import { useRemoteControlledDialog, useI18N } from '../../../../utils' +import { useI18N, useRemoteControlledDialog } from '../../../../utils' import { Image } from '../../../../components/shared/Image' import { WalletMessages } from '../../../../plugins/Wallet/messages' -import { formatEthereumAddress } from '@masknet/shared' import { MaskbookIconOutlined } from '../../../../resources/MaskbookIcon' import { CollectibleContext } from '../../DashboardComponents/CollectibleList' import { DashboardDialogCore, DashboardDialogWrapper, WrappedDialogProps } from '../Base' diff --git a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferTab.tsx b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferTab.tsx index ee84a3bcdb4c..7069d161b75e 100644 --- a/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferTab.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardDialogs/Wallet/TransferTab.tsx @@ -2,16 +2,20 @@ import { Button, makeStyles, TextField } from '@material-ui/core' import BigNumber from 'bignumber.js' import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react' import { EthereumAddress } from 'wallet.ts' -import { formatBalance, formatEthereumAddress, isGreaterThan, isZero, pow10 } from '@masknet/shared' import { - Wallet, + EthereumTokenType, + formatBalance, + formatEthereumAddress, + FungibleTokenDetailed, + isGreaterThan, + isZero, + pow10, + TransactionStateType, useTokenBalance, useTokenTransferCallback, - TransactionStateType, - FungibleTokenDetailed, - EthereumTokenType, + Wallet, } from '@masknet/web3-shared' -import { useRemoteControlledDialog, useI18N } from '../../../../utils' +import { useI18N, useRemoteControlledDialog } from '../../../../utils' import { WalletMessages } from '../../../../plugins/Wallet/messages' import { TokenAmountPanel } from '../../../../web3/UI/TokenAmountPanel' diff --git a/packages/maskbook/src/extension/options-page/DashboardRouters/Setup.tsx b/packages/maskbook/src/extension/options-page/DashboardRouters/Setup.tsx index 42a5f08ac0b8..ebc28f2d168d 100644 --- a/packages/maskbook/src/extension/options-page/DashboardRouters/Setup.tsx +++ b/packages/maskbook/src/extension/options-page/DashboardRouters/Setup.tsx @@ -27,6 +27,8 @@ import { UpgradeBackupJSONFile, BackupJSONFileLatest, decompressBackupFile, + WALLET_OR_PERSONA_NAME_MAX_LEN, + checkInputLengthExceed, } from '../../../utils' import ActionButton from '../DashboardComponents/ActionButton' import DashboardRouterContainer from './Container' @@ -156,7 +158,8 @@ const useConsentDataCollectionStyles = makeStyles((theme) => ({ color: theme.palette.text.primary, fontSize: 16, lineHeight: 1.75, - width: 660, + maxWidth: 660, + width: '100%', minHeight: 256, marginTop: 78, }, @@ -256,13 +259,23 @@ export function CreatePersona() { onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault() - createPersonaAndNext() + if (!checkInputLengthExceed(name) && name.length > 0) { + createPersonaAndNext() + } } }} label={t('name')} - helperText={' '} + helperText={ + checkInputLengthExceed(name) + ? t('input_length_exceed_prompt', { + name: t('persona_name').toLowerCase(), + length: WALLET_OR_PERSONA_NAME_MAX_LEN, + }) + : undefined + } inputProps={{ 'data-testid': 'username_input', + maxlength: WALLET_OR_PERSONA_NAME_MAX_LEN, }} variant="outlined" /> @@ -274,7 +287,7 @@ export function CreatePersona() { className={setupFormClasses.button} variant="contained" onClick={createPersonaAndNext} - disabled={!name} + disabled={!name || checkInputLengthExceed(name)} data-testid="next_button"> {t('set_up_button_next')} diff --git a/packages/maskbook/src/manifest.json b/packages/maskbook/src/manifest.json index df6c0a4706e2..345649117068 100644 --- a/packages/maskbook/src/manifest.json +++ b/packages/maskbook/src/manifest.json @@ -1,6 +1,6 @@ { "name": "Mask Network", - "version": "1.33.1", + "version": "1.33.2", "manifest_version": 2, "permissions": ["storage", "downloads", "webNavigation", "activeTab"], "optional_permissions": ["", "notifications", "clipboardRead"], diff --git a/packages/maskbook/src/plugin-infra/register.ts b/packages/maskbook/src/plugin-infra/register.ts index 3f5db7002a0f..ab6737b2d49d 100644 --- a/packages/maskbook/src/plugin-infra/register.ts +++ b/packages/maskbook/src/plugin-infra/register.ts @@ -7,6 +7,10 @@ import '../plugins/RedPacket' import '../plugins/Snapshot' import '../plugins/Collectible' import '../plugins/External' +import '../plugins/Transak' import '../plugins/Gitcoin' +import '../plugins/Polls' +import '../plugins/FileService' +import '../plugins/VCent' // import '../plugins/NFT' // import '../plugins/Airdrop' diff --git a/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/AirdropClaimCard.tsx b/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/AirdropClaimCard.tsx index 713db6fc9d64..01fbdf5c02bb 100644 --- a/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/AirdropClaimCard.tsx +++ b/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/AirdropClaimCard.tsx @@ -6,10 +6,17 @@ import { useStylesExtends } from '../../../components/custom-ui-helper' import { usePostLink } from '../../../components/DataSource/usePostInfo' import { AirdropIcon } from '../../../resources/AirdropIcon' import { activatedSocialNetworkUI } from '../../../social-network' -import { useRemoteControlledDialog } from '../../../utils/hooks/useRemoteControlledDialog' -import { useAccount, TransactionStateType, ERC20TokenDetailed, useChainId } from '@masknet/web3-shared' +import { useRemoteControlledDialog } from '../../../utils' +import { + ERC20TokenDetailed, + formatPercentage, + isZero, + pow10, + TransactionStateType, + useAccount, + useChainId, +} from '@masknet/web3-shared' import { WalletMessages } from '../../Wallet/messages' -import { formatPercentage, isZero, pow10 } from '@masknet/shared' import { useAirdropPacket } from '../hooks/useAirdropPacket' import { useClaimCallback } from '../hooks/useClaimCallback' import { CheckStateType, useCheckCallback } from '../hooks/useCheckCallback' diff --git a/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/ClaimDialog.tsx b/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/ClaimDialog.tsx index b987d2ef0ff1..4e1f57e3958f 100644 --- a/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/ClaimDialog.tsx +++ b/packages/maskbook/src/plugins/Airdrop/SNSAdaptor/ClaimDialog.tsx @@ -1,7 +1,7 @@ import { InjectedDialog, InjectedDialogProps } from '../../../components/shared/InjectedDialog' import { DialogContent, Box, Theme, makeStyles, DialogActions, Button, Typography } from '@material-ui/core' import { useStylesExtends } from '../../../components/custom-ui-helper' -import { TokenIcon } from '../../../extension/options-page/DashboardComponents/TokenIcon' +import { TokenIcon } from '@masknet/shared' import type { ERC20TokenDetailed } from '@masknet/web3-shared' const useStyles = makeStyles((theme: Theme) => ({ diff --git a/packages/maskbook/src/plugins/Airdrop/hooks/useCheckCallback.ts b/packages/maskbook/src/plugins/Airdrop/hooks/useCheckCallback.ts index 6facaa147b5c..304c0cdee117 100644 --- a/packages/maskbook/src/plugins/Airdrop/hooks/useCheckCallback.ts +++ b/packages/maskbook/src/plugins/Airdrop/hooks/useCheckCallback.ts @@ -1,7 +1,7 @@ import BigNumber from 'bignumber.js' import { useCallback, useState } from 'react' import { EthereumAddress } from 'wallet.ts' -import { formatEthereumAddress, isGreaterThan, ONE } from '@masknet/shared' +import { formatEthereumAddress, isGreaterThan, ONE } from '@masknet/web3-shared' import type { AirdropPacket } from '../apis' import { useAirdropContract } from '../contracts/useAirdropContract' import { AirdropRPC } from '../messages' diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/Collectible.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/Collectible.tsx index e4abbaae783e..eb3f7c1b8886 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/Collectible.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/Collectible.tsx @@ -1,13 +1,13 @@ import { useCallback } from 'react' import { - makeStyles, Avatar, Box, Button, - CardHeader, - CardContent, CardActions, + CardContent, + CardHeader, Link, + makeStyles, Paper, Tab, Tabs, @@ -36,7 +36,7 @@ import { resolveAssetLinkOnOpenSea, resolveCollectibleProviderName } from '../pi import { Markdown } from '../../Snapshot/SNSAdaptor/Markdown' import { ActionBar } from './ActionBar' import { useChainId } from '@masknet/web3-shared' -import { getEnumAsArray } from '@masknet/shared' +import { getEnumAsArray } from '@dimensiondev/kit' const useStyles = makeStyles((theme) => { return { diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/CollectibleProviderIcon.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/CollectibleProviderIcon.tsx index 4c679ed4309c..d7d6ed2e8854 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/CollectibleProviderIcon.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/CollectibleProviderIcon.tsx @@ -1,7 +1,7 @@ import { makeStyles } from '@material-ui/core' import { OpenSeaIcon } from '../../../resources/OpenSeaIcon' import { RaribleIcon } from '../../../resources/RaribleIcon' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import { CollectibleProvider } from '../types' const useStyles = makeStyles((theme) => { diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/HistoryTab/Row.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/HistoryTab/Row.tsx index 2db3932c6107..875c7a80eaa6 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/HistoryTab/Row.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/HistoryTab/Row.tsx @@ -1,6 +1,7 @@ import { Avatar, Link, makeStyles, TableCell, TableRow, Typography } from '@material-ui/core' import LinkIcon from '@material-ui/icons/Link' -import { formatBalance, FormattedBalance } from '@masknet/shared' +import { FormattedBalance } from '@masknet/shared' +import { formatBalance } from '@masknet/web3-shared' import { formatElapsed } from '../../../Wallet/formatter' import BigNumber from 'bignumber.js' import { useMemo } from 'react' diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByHighestBidCard.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByHighestBidCard.tsx index 1ac30edae710..c0a9a9a2fb1f 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByHighestBidCard.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByHighestBidCard.tsx @@ -1,7 +1,15 @@ -import { useState, useMemo, useCallback, useEffect } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { useSnackbar } from '@masknet/theme' -import { makeStyles, Card, CardContent, CardActions } from '@material-ui/core' -import { FungibleTokenDetailed, EthereumTokenType, useAccount, TokenWatched, isNative } from '@masknet/web3-shared' +import { Card, CardActions, CardContent, makeStyles } from '@material-ui/core' +import { + EthereumTokenType, + FungibleTokenDetailed, + isLessThan, + isNative, + isZero, + TokenWatched, + useAccount, +} from '@masknet/web3-shared' import { format as formatDateTime } from 'date-fns' import { useI18N } from '../../../utils' import { ActionButtonPromise } from '../../../extension/options-page/DashboardComponents/ActionButton' @@ -11,7 +19,6 @@ import { DateTimePanel } from '../../../web3/UI/DateTimePanel' import type { useAsset } from '../hooks/useAsset' import { PluginCollectibleRPC } from '../messages' import { toAsset, toUnixTimestamp } from '../helpers' -import { isLessThan, isZero } from '@masknet/shared' const useStyles = makeStyles((theme) => { return { diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByPriceCard.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByPriceCard.tsx index 9a277237f3c4..d47c27caa8fa 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByPriceCard.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingByPriceCard.tsx @@ -1,18 +1,26 @@ -import { ChangeEvent, useState, useMemo, useCallback, useEffect } from 'react' +import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react' import { EthereumAddress } from 'wallet.ts' import { useSnackbar } from '@masknet/theme' import { - makeStyles, Box, - Checkbox, Card, - CardContent, CardActions, + CardContent, + Checkbox, FormControlLabel, - Typography, + makeStyles, TextField, + Typography, } from '@material-ui/core' -import { FungibleTokenDetailed, EthereumTokenType, useAccount, TokenWatched, isNative } from '@masknet/web3-shared' +import { + EthereumTokenType, + FungibleTokenDetailed, + isGreaterThan, + isNative, + isZero, + TokenWatched, + useAccount, +} from '@masknet/web3-shared' import { format as formatDateTime } from 'date-fns' import { useI18N } from '../../../utils' import { ActionButtonPromise } from '../../../extension/options-page/DashboardComponents/ActionButton' @@ -22,7 +30,6 @@ import { DateTimePanel } from '../../../web3/UI/DateTimePanel' import { PluginCollectibleRPC } from '../messages' import { toAsset, toUnixTimestamp } from '../helpers' import type { useAsset } from '../hooks/useAsset' -import { isGreaterThan, isZero } from '@masknet/shared' const useStyles = makeStyles((theme) => { return { diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingTab.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingTab.tsx index 5152699353cf..7c6ecd7331af 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingTab.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/ListingTab.tsx @@ -8,8 +8,7 @@ import { OrderRow } from './OrderRow' import { TableListPagination } from './Pagination' import { CollectibleProvider } from '../types' import { LoadingTable } from './LoadingTable' -import { useAccount } from '@masknet/web3-shared' -import { isZero } from '@masknet/shared' +import { isZero, useAccount } from '@masknet/web3-shared' const useStyles = makeStyles((theme) => { return { diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OfferTab.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OfferTab.tsx index be9ad81958e8..fdb18808dcdb 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OfferTab.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OfferTab.tsx @@ -8,8 +8,7 @@ import { OrderRow } from './OrderRow' import { TableListPagination } from './Pagination' import { CollectibleProvider } from '../types' import { LoadingTable } from './LoadingTable' -import { useAccount } from '@masknet/web3-shared' -import { isZero } from '@masknet/shared' +import { isZero, useAccount } from '@masknet/web3-shared' const useStyles = makeStyles((theme) => { return { diff --git a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OrderRow.tsx b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OrderRow.tsx index c5a774d50ad2..f772d80a6f56 100644 --- a/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OrderRow.tsx +++ b/packages/maskbook/src/plugins/Collectible/SNSAdaptor/OrderRow.tsx @@ -2,11 +2,10 @@ import { Avatar, Link, makeStyles, TableCell, TableRow, Typography } from '@mate import { CollectibleProvider, NFTOrder } from '../types' import formatDistanceToNow from 'date-fns/formatDistanceToNow' import BigNumber from 'bignumber.js' -import { resolveAddressLinkOnExplorer } from '@masknet/web3-shared' -import { ChainId } from '@masknet/web3-shared' +import { ChainId, isZero, resolveAddressLinkOnExplorer } from '@masknet/web3-shared' import { CollectibleState } from '../hooks/useCollectibleState' import { Account } from './Account' -import { FormattedBalance, isZero } from '@masknet/shared' +import { FormattedBalance } from '@masknet/shared' const useStyles = makeStyles((theme) => { return { diff --git a/packages/maskbook/src/plugins/Collectible/helpers.ts b/packages/maskbook/src/plugins/Collectible/helpers.ts index 7f200b804083..fbca561b3266 100644 --- a/packages/maskbook/src/plugins/Collectible/helpers.ts +++ b/packages/maskbook/src/plugins/Collectible/helpers.ts @@ -1,11 +1,10 @@ import type { Asset, OpenSeaFungibleToken, WyvernSchemaName } from 'opensea-js/lib/types' import BigNumber from 'bignumber.js' -import { createERC20Token, createNativeToken, ChainId } from '@masknet/web3-shared' -import { createTypedMessageMetadataReader, createRenderWithMetadata } from '../../protocols/typed-message' +import { ChainId, createERC20Token, createNativeToken, pow10 } from '@masknet/web3-shared' +import { createRenderWithMetadata, createTypedMessageMetadataReader } from '../../protocols/typed-message' import { PLUGIN_META_KEY, RaribleIPFSURL } from './constants' import type { CollectibleJSON_Payload, CollectibleToken } from './types' import schema from './schema.json' -import { pow10 } from '@masknet/shared' export const CollectibleMetadataReader = createTypedMessageMetadataReader( PLUGIN_META_KEY, diff --git a/packages/maskbook/src/plugins/Collectible/hooks/useAsset.ts b/packages/maskbook/src/plugins/Collectible/hooks/useAsset.ts index 8a90a32c84e1..7f394f677d56 100644 --- a/packages/maskbook/src/plugins/Collectible/hooks/useAsset.ts +++ b/packages/maskbook/src/plugins/Collectible/hooks/useAsset.ts @@ -1,4 +1,4 @@ -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import { currySameAddress, EthereumTokenType, diff --git a/packages/maskbook/src/plugins/Collectible/hooks/useOrders.ts b/packages/maskbook/src/plugins/Collectible/hooks/useOrders.ts index c8a12a3dddaf..e25214399c0e 100644 --- a/packages/maskbook/src/plugins/Collectible/hooks/useOrders.ts +++ b/packages/maskbook/src/plugins/Collectible/hooks/useOrders.ts @@ -1,7 +1,7 @@ import { useAsyncRetry } from 'react-use' import BigNumber from 'bignumber.js' import { OrderSide } from 'opensea-js/lib/types' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import type { CollectibleToken, NFTOrder, OpenSeaCustomAccount } from '../types' import { CollectibleProvider } from '../types' import { PluginCollectibleRPC } from '../messages' diff --git a/packages/maskbook/src/plugins/Collectible/pipes/index.ts b/packages/maskbook/src/plugins/Collectible/pipes/index.ts index e90e6b79d9f8..4a8e035a42e5 100644 --- a/packages/maskbook/src/plugins/Collectible/pipes/index.ts +++ b/packages/maskbook/src/plugins/Collectible/pipes/index.ts @@ -1,5 +1,5 @@ import { Network } from 'opensea-js' -import { unreachable } from '@masknet/shared' +import { unreachable } from '@dimensiondev/kit' import { ChainId } from '@masknet/web3-shared' import { NullAddress, RaribleRopstenUserURL, RaribleUserURL } from '../constants' import { CollectibleProvider, OpenSeaAssetEventType, RaribleEventType } from '../types' diff --git a/packages/maskbook/src/plugins/Collectible/utils.ts b/packages/maskbook/src/plugins/Collectible/utils.ts index ec8a02d2cceb..52f542876008 100644 --- a/packages/maskbook/src/plugins/Collectible/utils.ts +++ b/packages/maskbook/src/plugins/Collectible/utils.ts @@ -7,8 +7,7 @@ import { raribleHostnames, rariblePathnameRegexMatcher, } from './constants' -import { formatBalance } from '@masknet/shared' -import { ChainId } from '@masknet/web3-shared' +import { ChainId, formatBalance } from '@masknet/web3-shared' export function checkUrl(url: string): boolean { const protocol = 'https://' diff --git a/packages/maskbook/src/plugins/External/components/CompositionEntry.tsx b/packages/maskbook/src/plugins/External/components/CompositionEntry.tsx index 6897a8303333..2dd32a00168a 100644 --- a/packages/maskbook/src/plugins/External/components/CompositionEntry.tsx +++ b/packages/maskbook/src/plugins/External/components/CompositionEntry.tsx @@ -1,4 +1,4 @@ -import type { Plugin } from '@masknet/plugin-infra/src' +import type { Plugin } from '@masknet/plugin-infra' import { usePortalShadowRoot } from '@masknet/shared' import { MaskDialog } from '@masknet/theme' import { DialogContent } from '@material-ui/core' diff --git a/packages/maskbook/src/plugins/FileService/MainDialog.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/MainDialog.tsx similarity index 80% rename from packages/maskbook/src/plugins/FileService/MainDialog.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/MainDialog.tsx index 52019cde4028..e9a83381aebd 100644 --- a/packages/maskbook/src/plugins/FileService/MainDialog.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/MainDialog.tsx @@ -2,17 +2,15 @@ import { Button, DialogActions, DialogContent, makeStyles } from '@material-ui/c import { isNil } from 'lodash-es' import { useSnackbar } from '@masknet/theme' import { useState } from 'react' -import { useBeforeUnload } from 'react-use' -import { useI18N } from '../../utils' -import { useStylesExtends } from '../../components/custom-ui-helper' -import { InjectedDialog, InjectedDialogProps } from '../../components/shared/InjectedDialog' -import { editActivatedPostMetadata } from '../../protocols/typed-message/global-state' +import { useI18N } from '../../../utils' +import { InjectedDialog, InjectedDialogProps } from '../../../components/shared/InjectedDialog' +import { editActivatedPostMetadata } from '../../../protocols/typed-message/global-state' import { Entry } from './components' -import { META_KEY_2 } from './constants' +import { META_KEY_2 } from '../constants' import { Exchange } from './hooks/Exchange' -import type { FileInfo } from './types' +import type { FileInfo } from '../types' -interface Props extends withClasses, InjectedDialogProps { +interface Props extends InjectedDialogProps { onConfirm: (file: FileInfo | undefined) => void onDecline: () => void } @@ -32,11 +30,10 @@ const useStyles = makeStyles({ }) const FileServiceDialog: React.FC = (props) => { const { t } = useI18N() - const classes = useStylesExtends(useStyles(), props) + const classes = useStyles() const snackbar = useSnackbar() const [uploading, setUploading] = useState(false) const [selectedFileInfo, setSelectedFileInfo] = useState(null) - useBeforeUnload(uploading) const onInsert = () => { if (isNil(selectedFileInfo)) { return diff --git a/packages/maskbook/src/plugins/FileService/Preview.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/Preview.tsx similarity index 95% rename from packages/maskbook/src/plugins/FileService/Preview.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/Preview.tsx index 201143b100fc..dd8fbf86a538 100644 --- a/packages/maskbook/src/plugins/FileService/Preview.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/Preview.tsx @@ -1,13 +1,9 @@ import { formatFileSize } from '@dimensiondev/kit' import { makeStyles, Paper, Typography } from '@material-ui/core' import { DownloadCloud, File } from 'react-feather' -import { useI18N } from '../../utils' +import { useI18N } from '../../../utils' import { CopyableCode } from './components/Copyable' -import type { FileInfo } from './types' - -interface Props { - info: FileInfo -} +import type { FileInfo } from '../types' const useStyles = makeStyles((theme) => ({ root: { diff --git a/packages/maskbook/src/plugins/FileService/components/Copyable.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Copyable.tsx similarity index 100% rename from packages/maskbook/src/plugins/FileService/components/Copyable.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Copyable.tsx diff --git a/packages/maskbook/src/plugins/FileService/components/FileName.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/FileName.tsx similarity index 100% rename from packages/maskbook/src/plugins/FileService/components/FileName.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/FileName.tsx diff --git a/packages/maskbook/src/plugins/FileService/components/ProgressBar.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/ProgressBar.tsx similarity index 98% rename from packages/maskbook/src/plugins/FileService/components/ProgressBar.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/ProgressBar.tsx index 8de7c981ae00..e598ec08ad80 100644 --- a/packages/maskbook/src/plugins/FileService/components/ProgressBar.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/ProgressBar.tsx @@ -1,6 +1,6 @@ import { formatFileSize } from '@dimensiondev/kit' import { makeStyles, Typography, LinearProgress, Box } from '@material-ui/core' -import { useI18N } from '../../../utils' +import { useI18N } from '../../../../utils' const useStyles = makeStyles({ container: { diff --git a/packages/maskbook/src/plugins/FileService/components/RecentFiles.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/RecentFiles.tsx similarity index 95% rename from packages/maskbook/src/plugins/FileService/components/RecentFiles.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/RecentFiles.tsx index 90d0bd6425db..b91d1d1f13c1 100644 --- a/packages/maskbook/src/plugins/FileService/components/RecentFiles.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/RecentFiles.tsx @@ -1,10 +1,10 @@ import { Button, List, ListItem, ListItemIcon, ListItemText, makeStyles, Typography } from '@material-ui/core' +import formatDateTime from 'date-fns/format' import { File } from 'react-feather' import { useHistory } from 'react-router' -import { useI18N } from '../../../utils' -import formatDateTime from 'date-fns/format' -import { FileRouter } from '../constants' -import type { FileInfo } from '../types' +import { useI18N } from '../../../../utils' +import { FileRouter } from '../../constants' +import type { FileInfo } from '../../types' const useStyles = makeStyles((theme) => ({ container: { diff --git a/packages/maskbook/src/plugins/FileService/components/Upload.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Upload.tsx similarity index 90% rename from packages/maskbook/src/plugins/FileService/components/Upload.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Upload.tsx index 926328b74808..125c2f57eb2a 100644 --- a/packages/maskbook/src/plugins/FileService/components/Upload.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Upload.tsx @@ -1,17 +1,17 @@ import { Attachment } from '@dimensiondev/common-protocols' -import { encodeArrayBuffer } from '@dimensiondev/kit' -import { Checkbox, FormControlLabel, makeStyles, Typography, Link } from '@material-ui/core' +import { blobToArrayBuffer, encodeArrayBuffer } from '@dimensiondev/kit' +import { Checkbox, FormControlLabel, Link, makeStyles, Typography } from '@material-ui/core' import { isNil } from 'lodash-es' +import { useState } from 'react' import { Trans } from 'react-i18next' import { useHistory } from 'react-router' import { useAsync } from 'react-use' -import { useI18N } from '../../../utils' -import { PluginFileServiceRPC } from '../utils' -import { makeFileKey } from '../arweave/makeFileKey' -import { FileRouter, MAX_FILE_SIZE } from '../constants' +import { useI18N } from '../../../../utils' +import { makeFileKey } from '../../file-key' +import { FileRouter, MAX_FILE_SIZE } from '../../constants' +import { PluginFileServiceRPC } from '../../Worker/rpc' import { RecentFiles } from './RecentFiles' import { UploadDropArea } from './UploadDropArea' -import { useState } from 'react' const useStyles = makeStyles((theme) => ({ container: { @@ -64,7 +64,7 @@ export const Upload: React.FC = () => { if (encrypted) { key = makeFileKey() } - const block = new Uint8Array(await file.arrayBuffer()) + const block = new Uint8Array(await blobToArrayBuffer(file)) const checksum = encodeArrayBuffer(await Attachment.checksum(block)) const item = await PluginFileServiceRPC.getFileInfo(checksum) if (isNil(item)) { diff --git a/packages/maskbook/src/plugins/FileService/components/UploadDropArea.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/UploadDropArea.tsx similarity index 98% rename from packages/maskbook/src/plugins/FileService/components/UploadDropArea.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/UploadDropArea.tsx index fb26cb053e69..5ce0f9a790bb 100644 --- a/packages/maskbook/src/plugins/FileService/components/UploadDropArea.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/UploadDropArea.tsx @@ -1,11 +1,11 @@ import { formatFileSize } from '@dimensiondev/kit' +import { useSnackbar } from '@masknet/theme' import { makeStyles, Typography } from '@material-ui/core' import classNames from 'classnames' import { isNil } from 'lodash-es' -import { useSnackbar } from '@masknet/theme' import { UploadCloud } from 'react-feather' import { useDropArea } from 'react-use' -import { useI18N } from '../../../utils' +import { useI18N } from '../../../../utils' const useStyles = makeStyles((theme) => ({ label: { diff --git a/packages/maskbook/src/plugins/FileService/components/Uploaded.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Uploaded.tsx similarity index 95% rename from packages/maskbook/src/plugins/FileService/components/Uploaded.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Uploaded.tsx index 0702d5af3f04..d579ae0b6067 100644 --- a/packages/maskbook/src/plugins/FileService/components/Uploaded.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Uploaded.tsx @@ -1,13 +1,13 @@ import { formatFileSize } from '@dimensiondev/kit' import { Button, Grid, makeStyles, Typography } from '@material-ui/core' +import formatDateTime from 'date-fns/format' import { useEffect } from 'react' import { File } from 'react-feather' import { useHistory, useLocation } from 'react-router' -import { useI18N } from '../../../utils' -import formatDateTime from 'date-fns/format' -import { FileRouter } from '../constants' import { useExchange } from '../hooks/Exchange' -import type { FileInfo } from '../types' +import { useI18N } from '../../../../utils' +import { FileRouter } from '../../constants' +import type { FileInfo } from '../../types' import { FileName } from './FileName' const useStyles = makeStyles({ diff --git a/packages/maskbook/src/plugins/FileService/components/Uploading.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Uploading.tsx similarity index 94% rename from packages/maskbook/src/plugins/FileService/components/Uploading.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Uploading.tsx index e5a39a7d86f8..1cb2ec4920d8 100644 --- a/packages/maskbook/src/plugins/FileService/components/Uploading.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/Uploading.tsx @@ -1,13 +1,13 @@ import { Grid, makeStyles, Typography } from '@material-ui/core' -import { useState, useEffect } from 'react' +import { useEffect, useState } from 'react' import { File } from 'react-feather' import { useHistory, useLocation } from 'react-router' import { useAsync } from 'react-use' -import { useI18N, timeout } from '../../../utils' -import { PluginFileServiceRPC, PluginFileServiceRPCGenerator } from '../utils' -import { FileRouter } from '../constants' +import { timeout, useI18N } from '../../../../utils' +import { FileRouter } from '../../constants' +import type { FileInfo } from '../../types' +import { PluginFileServiceRPC, PluginFileServiceRPCGenerator } from '../../Worker/rpc' import { useExchange } from '../hooks/Exchange' -import type { FileInfo } from '../types' import { FileName } from './FileName' import { ProgressBar } from './ProgressBar' diff --git a/packages/maskbook/src/plugins/FileService/components/index.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/index.tsx similarity index 91% rename from packages/maskbook/src/plugins/FileService/components/index.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/components/index.tsx index 00dfaa0a2dcc..03b9465229f0 100644 --- a/packages/maskbook/src/plugins/FileService/components/index.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/components/index.tsx @@ -1,5 +1,5 @@ import { MemoryRouter, Redirect, Route } from 'react-router' -import { FileRouter } from '../constants' +import { FileRouter } from '../../constants' import { Upload } from './Upload' import { Uploaded } from './Uploaded' import { Uploading } from './Uploading' diff --git a/packages/maskbook/src/plugins/FileService/hooks/Exchange.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/hooks/Exchange.tsx similarity index 91% rename from packages/maskbook/src/plugins/FileService/hooks/Exchange.tsx rename to packages/maskbook/src/plugins/FileService/SNSAdaptor/hooks/Exchange.tsx index d481c1eac31b..a2815feb20e2 100644 --- a/packages/maskbook/src/plugins/FileService/hooks/Exchange.tsx +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/hooks/Exchange.tsx @@ -1,6 +1,6 @@ import { noop, omit } from 'lodash-es' import { createContext, useContext } from 'react' -import type { FileInfo } from '../types' +import type { FileInfo } from '../../types' export interface Props { onInsert(info: FileInfo | null): void diff --git a/packages/maskbook/src/plugins/FileService/SNSAdaptor/index.tsx b/packages/maskbook/src/plugins/FileService/SNSAdaptor/index.tsx new file mode 100644 index 000000000000..f5b8c5f89000 --- /dev/null +++ b/packages/maskbook/src/plugins/FileService/SNSAdaptor/index.tsx @@ -0,0 +1,36 @@ +import { formatFileSize } from '@dimensiondev/kit' +import type { Plugin } from '@masknet/plugin-infra' +import { truncate } from 'lodash-es' +import { base } from '../base' +import { META_KEY_1, META_KEY_2 } from '../constants' +import { FileInfoMetadataReader } from '../helpers' +import type { FileInfo } from '../types' +import FileServiceDialog from './MainDialog' +import { Preview } from './Preview' + +const definition: Plugin.SNSAdaptor.Definition = { + ...base, + init(signal) {}, + DecryptedInspector(props) { + const metadata = FileInfoMetadataReader(props.message.meta) + if (!metadata.ok) return null + return + }, + CompositionDialogMetadataBadgeRender: new Map([ + [META_KEY_1, onAttachedFile], + [META_KEY_2, onAttachedFile], + ]), + CompositionDialogEntry: { + label: '📃 File Service', + dialog({ open, onClose }) { + return + }, + }, +} + +export default definition + +function onAttachedFile(payload: FileInfo) { + const name = truncate(payload.name, { length: 10 }) + return `Attached File: ${name} (${formatFileSize(payload.size)})` +} diff --git a/packages/maskbook/src/plugins/FileService/UI-define.tsx b/packages/maskbook/src/plugins/FileService/UI-define.tsx deleted file mode 100644 index 985be7c7c78e..000000000000 --- a/packages/maskbook/src/plugins/FileService/UI-define.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { formatFileSize } from '@dimensiondev/kit' -import { truncate } from 'lodash-es' -import { PluginConfig, PluginScope, PluginStage } from '../types' -import { createCompositionDialog } from '../utils/createCompositionDialog' -import { identifier, META_KEY_1, META_KEY_2, pluginIcon, pluginName, pluginDescription } from './constants' -import { FileInfoMetadataReader } from './define' -import FileServiceDialog from './MainDialog' -import { Preview } from './Preview' -import type { FileInfo } from './types' - -export const [FileServiceCompositionEntry, FileServiceCompositionUI] = createCompositionDialog( - '📃 File Service', - (props) => , -) -export const FileServicePluginDefine: PluginConfig = { - id: identifier, - pluginIcon, - pluginName, - pluginDescription, - identifier, - stage: PluginStage.Production, - scope: PluginScope.Public, - successDecryptionInspector(props) { - const metadata = FileInfoMetadataReader(props.message.meta) - if (!metadata.ok) return null - return - }, - postDialogMetadataBadge: new Map([ - [META_KEY_1, onAttachedFile], - [META_KEY_2, onAttachedFile], - ]), - PageComponent: FileServiceCompositionUI, - postDialogEntries: [FileServiceCompositionEntry], -} - -function onAttachedFile(payload: FileInfo) { - const name = truncate(payload.name, { length: 10 }) - return `Attached File: ${name} (${formatFileSize(payload.size)})` -} diff --git a/packages/maskbook/src/plugins/FileService/arweave/token.json b/packages/maskbook/src/plugins/FileService/Worker/arweave-token.json similarity index 100% rename from packages/maskbook/src/plugins/FileService/arweave/token.json rename to packages/maskbook/src/plugins/FileService/Worker/arweave-token.json diff --git a/packages/maskbook/src/plugins/FileService/arweave/index.ts b/packages/maskbook/src/plugins/FileService/Worker/arweave.ts similarity index 98% rename from packages/maskbook/src/plugins/FileService/arweave/index.ts rename to packages/maskbook/src/plugins/FileService/Worker/arweave.ts index 603ee0fe70e6..71a6580f2748 100644 --- a/packages/maskbook/src/plugins/FileService/arweave/index.ts +++ b/packages/maskbook/src/plugins/FileService/Worker/arweave.ts @@ -5,7 +5,7 @@ import type Transaction from 'arweave/web/lib/transaction' import { isEmpty, isNil } from 'lodash-es' import { landing, mesonPrefix } from '../constants' import { sign } from './remote-signing' -import token from './token.json' +import TOKEN from './arweave-token.json' const stage: Record = {} @@ -72,7 +72,7 @@ export async function uploadLandingPage(metadata: LandingPageMetadata) { } async function makePayload(data: Uint8Array, type: string) { - const transaction = await instance.createTransaction({ data }, token as any) + const transaction = await instance.createTransaction({ data }, TOKEN as any) transaction.addTag('Content-Type', type) await sign(transaction) return transaction diff --git a/packages/maskbook/src/plugins/FileService/database.ts b/packages/maskbook/src/plugins/FileService/Worker/database.ts similarity index 68% rename from packages/maskbook/src/plugins/FileService/database.ts rename to packages/maskbook/src/plugins/FileService/Worker/database.ts index 36e68d8322ec..ab5a7a6d6f9b 100644 --- a/packages/maskbook/src/plugins/FileService/database.ts +++ b/packages/maskbook/src/plugins/FileService/Worker/database.ts @@ -1,12 +1,12 @@ -import { createPluginDatabase } from '../../database/Plugin/wrap-plugin-database' -import { asyncIteratorToArray } from '../../utils/type-transform/asyncIteratorHelpers' -import { identifier } from './constants' -import { FileInfoV1ToV2 } from './define' -import type { FileInfo, FileInfoV1 } from './types' +import { createPluginDatabase } from '../../../database/Plugin/wrap-plugin-database' +import { asyncIteratorToArray } from '../../../utils/type-transform/asyncIteratorHelpers' +import { base } from '../base' +import { FileInfoV1ToV2 } from '../helpers' +import type { FileInfo, FileInfoV1 } from '../types' type TaggedTypes = FileInfo | FileInfoV1 -const Database = createPluginDatabase(identifier) +const Database = createPluginDatabase(base.ID) let migrationDone = false async function migrationV1_V2() { diff --git a/packages/maskbook/src/plugins/FileService/Worker/index.ts b/packages/maskbook/src/plugins/FileService/Worker/index.ts new file mode 100644 index 000000000000..9a10cd948023 --- /dev/null +++ b/packages/maskbook/src/plugins/FileService/Worker/index.ts @@ -0,0 +1,10 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { base } from '../base' +import './rpc' + +const worker: Plugin.Worker.Definition = { + ...base, + init(signal) {}, +} + +export default worker diff --git a/packages/maskbook/src/plugins/FileService/arweave/remote-signing.ts b/packages/maskbook/src/plugins/FileService/Worker/remote-signing.ts similarity index 100% rename from packages/maskbook/src/plugins/FileService/arweave/remote-signing.ts rename to packages/maskbook/src/plugins/FileService/Worker/remote-signing.ts diff --git a/packages/maskbook/src/plugins/FileService/utils/index.ts b/packages/maskbook/src/plugins/FileService/Worker/rpc.ts similarity index 61% rename from packages/maskbook/src/plugins/FileService/utils/index.ts rename to packages/maskbook/src/plugins/FileService/Worker/rpc.ts index a0009d272c3a..edd3c5c3618d 100644 --- a/packages/maskbook/src/plugins/FileService/utils/index.ts +++ b/packages/maskbook/src/plugins/FileService/Worker/rpc.ts @@ -1,16 +1,19 @@ import { createPluginMessage } from '../../utils/createPluginMessage' import { createPluginRPC, createPluginRPCGenerator } from '../../utils/createPluginRPC' -import { pluginId } from '../constants' +import { FileServicePluginID } from '../constants' + +import.meta.webpackHot?.accept() + +const PluginFileServiceMessage = createPluginMessage<{ _: unknown; _2: unknown }>(FileServicePluginID) -if (import.meta.webpackHot) import.meta.webpackHot.accept() -const PluginFileServiceMessage = createPluginMessage<{ _: unknown; _2: unknown }>(pluginId) export const PluginFileServiceRPC = createPluginRPC( - pluginId, - () => import('../service'), + FileServicePluginID, + () => import('./service'), PluginFileServiceMessage.events._, ) + export const PluginFileServiceRPCGenerator = createPluginRPCGenerator( - pluginId, - () => import('../service').then(({ upload }) => ({ upload })), + FileServicePluginID, + () => import('./service').then(({ upload }) => ({ upload })), PluginFileServiceMessage.events._2, ) diff --git a/packages/maskbook/src/plugins/FileService/service.ts b/packages/maskbook/src/plugins/FileService/Worker/service.ts similarity index 100% rename from packages/maskbook/src/plugins/FileService/service.ts rename to packages/maskbook/src/plugins/FileService/Worker/service.ts diff --git a/packages/maskbook/src/plugins/FileService/base.ts b/packages/maskbook/src/plugins/FileService/base.ts new file mode 100644 index 000000000000..8ae5ec60f326 --- /dev/null +++ b/packages/maskbook/src/plugins/FileService/base.ts @@ -0,0 +1,15 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { FileServicePluginID } from './constants' + +export const base: Plugin.Shared.Definition = { + ID: FileServicePluginID, + icon: '📃', + name: { fallback: 'File Service' }, + description: { fallback: 'Upload and share files on top of Arweave network. Store data, permanently.' }, + publisher: { name: { fallback: 'Mask Network' }, link: 'https://mask.io' }, + enableRequirement: { + architecture: { app: true, web: true }, + networks: { type: 'opt-out', networks: {} }, + target: 'stable', + }, +} diff --git a/packages/maskbook/src/plugins/FileService/constants.ts b/packages/maskbook/src/plugins/FileService/constants.ts index 9516e3e5c679..fa2501a74db8 100644 --- a/packages/maskbook/src/plugins/FileService/constants.ts +++ b/packages/maskbook/src/plugins/FileService/constants.ts @@ -1,8 +1,4 @@ -export const pluginIcon = '📃' -export const pluginName = 'File Service' -export const pluginDescription = 'Upload and share files on top of Arweave network. Store data, permanently.' -export const identifier = 'com.maskbook.fileservice' -export const pluginId = 'maskbook.fileservice' +export const FileServicePluginID = 'com.maskbook.fileservice' export const META_KEY_1 = 'com.maskbook.fileservice:1' export const META_KEY_2 = 'com.maskbook.fileservice:2' diff --git a/packages/maskbook/src/plugins/FileService/arweave/makeFileKey.ts b/packages/maskbook/src/plugins/FileService/file-key.ts similarity index 100% rename from packages/maskbook/src/plugins/FileService/arweave/makeFileKey.ts rename to packages/maskbook/src/plugins/FileService/file-key.ts diff --git a/packages/maskbook/src/plugins/FileService/define.tsx b/packages/maskbook/src/plugins/FileService/helpers.ts similarity index 99% rename from packages/maskbook/src/plugins/FileService/define.tsx rename to packages/maskbook/src/plugins/FileService/helpers.ts index 75df4f541d6f..dc1cf76fac26 100644 --- a/packages/maskbook/src/plugins/FileService/define.tsx +++ b/packages/maskbook/src/plugins/FileService/helpers.ts @@ -8,11 +8,13 @@ import type { TypedMessage } from '../../protocols/typed-message' const reader_v1 = createTypedMessageMetadataReader(META_KEY_1, schemaV1) const reader_v2 = createTypedMessageMetadataReader(META_KEY_2, schemaV2) + export function FileInfoMetadataReader(meta: TypedMessage['meta']): Result { const v2 = reader_v2(meta) if (v2.ok) return v2 return reader_v1(meta).map(FileInfoV1ToV2) } + export function FileInfoV1ToV2(info: FileInfoV1): FileInfo { return { ...info, type: 'file', provider: 'arweave' } } diff --git a/packages/maskbook/src/plugins/FileService/index.ts b/packages/maskbook/src/plugins/FileService/index.ts new file mode 100644 index 000000000000..a902f2667183 --- /dev/null +++ b/packages/maskbook/src/plugins/FileService/index.ts @@ -0,0 +1,18 @@ +import { registerPlugin } from '@masknet/plugin-infra' +import { base } from './base' + +registerPlugin({ + ...base, + SNSAdaptor: { + load: () => import('./SNSAdaptor'), + hotModuleReload: (hot) => { + import.meta.webpackHot?.accept('./SNSAdaptor/index', () => hot(import('./SNSAdaptor'))) + }, + }, + Worker: { + load: () => import('./Worker'), + hotModuleReload: (hot) => { + import.meta.webpackHot?.accept('./Worker/index', () => hot(import('./Worker'))) + }, + }, +}) diff --git a/packages/maskbook/src/plugins/FileService/types.ts b/packages/maskbook/src/plugins/FileService/types.ts index bbe435cd07df..d6974a67719d 100644 --- a/packages/maskbook/src/plugins/FileService/types.ts +++ b/packages/maskbook/src/plugins/FileService/types.ts @@ -11,6 +11,7 @@ export interface FileInfo { payloadTxID: string landingTxID: string } + export type FileInfoV1 = Omit & { type: 'arweave' } diff --git a/packages/maskbook/src/plugins/Gitcoin/SNSAdaptor/DonateDialog.tsx b/packages/maskbook/src/plugins/Gitcoin/SNSAdaptor/DonateDialog.tsx index f221e0ef961c..5bd87681614e 100644 --- a/packages/maskbook/src/plugins/Gitcoin/SNSAdaptor/DonateDialog.tsx +++ b/packages/maskbook/src/plugins/Gitcoin/SNSAdaptor/DonateDialog.tsx @@ -1,7 +1,8 @@ -import { formatBalance, pow10 } from '@masknet/shared' import { EthereumTokenType, + formatBalance, FungibleTokenDetailed, + pow10, TransactionStateType, useAccount, useChainId, @@ -15,7 +16,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { Trans } from 'react-i18next' import { v4 as uuid } from 'uuid' import { useStylesExtends } from '../../../components/custom-ui-helper' -import { usePostLink } from '../../../components/DataSource/usePostInfo' import { InjectedDialog } from '../../../components/shared/InjectedDialog' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' import { activatedSocialNetworkUI } from '../../../social-network' @@ -119,7 +119,6 @@ export function DonateDialog(props: DonateDialogProps) { //#region transaction dialog const cashTag = isTwitter(activatedSocialNetworkUI) ? '$' : '' - const postLink = usePostLink() const shareLink = activatedSocialNetworkUI.utils .getShareLinkURL?.( token @@ -128,7 +127,6 @@ export function DonateDialog(props: DonateDialogProps) { token.symbol }. Follow @realMaskbook (mask.io) to donate Gitcoin grants.`, '#mask_io', - postLink, ].join('\n') : '', ) diff --git a/packages/maskbook/src/plugins/Gitcoin/messages.ts b/packages/maskbook/src/plugins/Gitcoin/messages.ts index 1c57e88e2457..818c995debc2 100644 --- a/packages/maskbook/src/plugins/Gitcoin/messages.ts +++ b/packages/maskbook/src/plugins/Gitcoin/messages.ts @@ -1,6 +1,7 @@ import { createPluginMessage } from '../utils/createPluginMessage' import { createPluginRPC } from '../utils/createPluginRPC' import { GITCOIN_PLUGIN_ID } from './constants' +import type { WebExtensionMessage } from '@dimensiondev/holoflows-kit' type DonationDialogUpdated = | { @@ -21,7 +22,8 @@ interface GitcoinMessages { rpc: unknown } -export const PluginGitcoinMessages = createPluginMessage(GITCOIN_PLUGIN_ID) +export const PluginGitcoinMessages: WebExtensionMessage = + createPluginMessage(GITCOIN_PLUGIN_ID) export const PluginGitcoinRPC = createPluginRPC( GITCOIN_PLUGIN_ID, () => import('./services'), diff --git a/packages/maskbook/src/plugins/ITO/UI/ClaimAllDialog.tsx b/packages/maskbook/src/plugins/ITO/UI/ClaimAllDialog.tsx index a54a1decd26c..017957d08ce3 100644 --- a/packages/maskbook/src/plugins/ITO/UI/ClaimAllDialog.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/ClaimAllDialog.tsx @@ -1,13 +1,20 @@ import { useCallback, useEffect } from 'react' -import { uniq, flatten } from 'lodash-es' +import { flatten, uniq } from 'lodash-es' import formatDateTime from 'date-fns/format' import { useSnackbar, VariantType } from '@masknet/theme' -import { formatBalance, FormattedBalance } from '@masknet/shared' +import { FormattedBalance } from '@masknet/shared' import { makeStyles, DialogContent, CircularProgress, Typography, List, ListItem } from '@material-ui/core' -import { TransactionStateType, resolveTransactionLinkOnExplorer, useChainId } from '@masknet/web3-shared' +import { + formatBalance, + TransactionStateType, + resolveTransactionLinkOnExplorer, + useChainId, + useITOConstants, + ChainId, +} from '@masknet/web3-shared' import { useRemoteControlledDialog, useI18N } from '../../../utils' import { InjectedDialog } from '../../../components/shared/InjectedDialog' -import { useClaimAll } from '../hooks/useClaimAll' +import { useClaimAll, SwappedToken } from '../hooks/useClaimAll' import { WalletMessages } from '../../Wallet/messages' import { useClaimCallback } from '../hooks/useClaimCallback' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' @@ -51,16 +58,15 @@ const useStyles = makeStyles((theme) => ({ width: '100%', color: 'white', maxHeight: 450, - marginBottom: theme.spacing(1), overflow: 'auto', - padding: theme.spacing(1, 0), + paddingTop: theme.spacing(1), + marginBottom: theme.spacing(0.5), }, tokenCard: { width: '100%', color: 'white', height: 95, background: 'linear-gradient(.25turn, #0ACFFE, 40%, #2b3ef0)', - marginBottom: theme.spacing(2), borderRadius: 10, flexDirection: 'column', paddingTop: theme.spacing(2), @@ -78,6 +84,13 @@ const useStyles = makeStyles((theme) => ({ cardContent: { fontSize: 18, }, + content: { + marginBottom: theme.spacing(2), + }, + contentTitle: { + fontSize: 18, + fontWeight: 300, + }, })) interface ClaimAllDialogProps { @@ -89,11 +102,14 @@ export function ClaimAllDialog(props: ClaimAllDialogProps) { const { t } = useI18N() const { open, onClose } = props const { value: swappedTokens, loading, retry } = useClaimAll() + const { ITO_CONTRACT_ADDRESS: ITO_CONTRACT_ADDRESS_MAINNET } = useITOConstants(ChainId.Mainnet) + // Todo: Remove the code after the period that old ITO is being used and continues to be used for a while + const { value: swappedTokensOld, loading: loadingOld, retry: retryOld } = useClaimAll(true) const classes = useStyles() const { enqueueSnackbar } = useSnackbar() const popEnqueueSnackbar = useCallback( (variant: VariantType) => - enqueueSnackbar('Claim Token', { + enqueueSnackbar(t('plugin_ito_claim_all_title'), { variant, preventDuplicate: true, anchorOrigin: { @@ -105,25 +121,69 @@ export function ClaimAllDialog(props: ClaimAllDialogProps) { ) const chainId = useChainId() const claimablePids = uniq(flatten(swappedTokens?.filter((t) => t.isClaimable).map((t) => t.pids))) + const claimablePidsOld = uniq(flatten(swappedTokensOld?.filter((t) => t.isClaimable).map((t) => t.pids))) const [claimState, claimCallback, resetClaimCallback] = useClaimCallback(claimablePids) + const [claimStateOld, claimCallbackOld, resetClaimCallbackOld] = useClaimCallback( + claimablePidsOld, + ITO_CONTRACT_ADDRESS_MAINNET, + ) const onClaimButtonClick = useCallback(() => { claimCallback() }, [claimCallback]) + const onClaimButtonClickOld = useCallback(() => { + claimCallbackOld() + }, [claimCallbackOld]) + const { setDialog: setClaimTransactionDialog } = useRemoteControlledDialog( WalletMessages.events.transactionDialogUpdated, (ev) => { if (ev.open) return - if (claimState.type === TransactionStateType.FAILED) popEnqueueSnackbar('error') - if (claimState.type !== TransactionStateType.CONFIRMED) return - resetClaimCallback() - retry() - onClose() - popEnqueueSnackbar('success') + + if (claimState.type === TransactionStateType.FAILED || claimStateOld.type === TransactionStateType.FAILED) + popEnqueueSnackbar('error') + + if (claimState.type === TransactionStateType.CONFIRMED) { + resetClaimCallback() + retry() + onClose() + popEnqueueSnackbar('success') + } + + if (claimStateOld.type === TransactionStateType.CONFIRMED) { + resetClaimCallbackOld() + retryOld() + onClose() + popEnqueueSnackbar('success') + } }, ) + useEffect(() => { + if (claimStateOld.type === TransactionStateType.UNKNOWN) return + + if (claimStateOld.type === TransactionStateType.HASH) { + const { hash } = claimStateOld + setTimeout(() => { + window.open(resolveTransactionLinkOnExplorer(chainId, hash), '_blank', 'noopener noreferrer') + }, 2000) + return + } + const claimableTokens = swappedTokensOld!.filter((t) => t.isClaimable) + const summary = + 'Claim ' + + new Intl.ListFormat('en').format( + claimableTokens.map((t) => formatBalance(t.amount, t.token.decimals) + ' ' + t.token.symbol), + ) + setClaimTransactionDialog({ + open: true, + state: claimStateOld, + title: t('plugin_ito_claim_all_title'), + summary, + }) + }, [claimStateOld, swappedTokensOld /* update tx dialog only if state changed */]) + useEffect(() => { if (claimState.type === TransactionStateType.UNKNOWN) return @@ -143,7 +203,7 @@ export function ClaimAllDialog(props: ClaimAllDialogProps) { setClaimTransactionDialog({ open: true, state: claimState, - title: 'Claim Token', + title: t('plugin_ito_claim_all_title'), summary, }) }, [claimState, swappedTokens /* update tx dialog only if state changed */]) @@ -151,57 +211,98 @@ export function ClaimAllDialog(props: ClaimAllDialogProps) { return ( - {loading || !swappedTokens ? ( + {loading || loadingOld || !swappedTokens || !swappedTokensOld ? ( - ) : swappedTokens.length > 0 ? ( + ) : swappedTokens.length > 0 || swappedTokensOld.length > 0 ? ( <> - - {swappedTokens.map((swappedToken, i) => ( - -
- - {swappedToken.token.symbol}{' '} - {swappedToken.isClaimable - ? t('plugin_ito_claim_all_status_unclaimed') - : t('plugin_ito_claim_all_status_locked')} - : - - {swappedToken.isClaimable ? null : ( - - {t('plugin_ito_claim_all_unlock_time', { - time: formatDateTime( - swappedToken.unlockTime, - 'yyyy-MM-dd HH:mm:ss', - ), - })} - - )} -
- - + {swappedTokensOld.length > 0 ? ( +
+ {swappedTokens.length > 0 && swappedTokensOld.length > 0 ? ( + + {t('plugin_ito_claim_all_old_contract')} - - ))} - - - - {t('plugin_ito_claim_all')} - - + ) : null} + +
+ ) : null} + {swappedTokens.length > 0 ? ( +
+ {swappedTokens.length > 0 && swappedTokensOld.length > 0 ? ( + + {t('plugin_ito_claim_all_new_contract')} + + ) : null} + +
+ ) : null} ) : ( - {t('plugin_ito_no_claimable_token')} + {t('plugin_ito_no_claimable_token')} )}
) } + +interface ContentProps { + onClaimButtonClick: () => void + swappedTokens: SwappedToken[] + claimablePids: string[] +} + +function Content(props: ContentProps) { + const { t } = useI18N() + const classes = useStyles() + const { onClaimButtonClick, swappedTokens, claimablePids } = props + return ( + <> + + {swappedTokens.map((swappedToken, i) => ( + +
+ + {swappedToken.token.symbol}{' '} + {swappedToken.isClaimable + ? t('plugin_ito_claim_all_status_unclaimed') + : t('plugin_ito_claim_all_status_locked')} + : + + {swappedToken.isClaimable ? null : ( + + {t('plugin_ito_claim_all_unlock_time', { + time: formatDateTime(swappedToken.unlockTime, 'yyyy-MM-dd HH:mm:ss'), + })} + + )} +
+ + + +
+ ))} +
+ + + {t('plugin_ito_claim_all')} + + + + ) +} diff --git a/packages/maskbook/src/plugins/ITO/UI/CompositionDialog.tsx b/packages/maskbook/src/plugins/ITO/UI/CompositionDialog.tsx index f76c1929943b..9cc420ffe3c4 100644 --- a/packages/maskbook/src/plugins/ITO/UI/CompositionDialog.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/CompositionDialog.tsx @@ -1,7 +1,7 @@ import { useCallback, useEffect, useState } from 'react' import Web3Utils from 'web3-utils' import { DialogContent } from '@material-ui/core' -import { formatBalance, usePortalShadowRoot } from '@masknet/shared' +import { usePortalShadowRoot } from '@masknet/shared' import { useI18N, useRemoteControlledDialog } from '../../../utils' import { InjectedDialog, InjectedDialogProps } from '../../../components/shared/InjectedDialog' import { ITO_MetaKey, MSG_DELIMITER } from '../constants' @@ -13,11 +13,10 @@ import { payloadOutMask } from '../helpers' import { PoolList } from './PoolList' import { PluginITO_RPC } from '../messages' import Services from '../../../extension/service' -import { useChainId, useAccount, TransactionStateType } from '@masknet/web3-shared' +import { formatBalance, useChainId, useAccount, TransactionStateType, useITOConstants } from '@masknet/web3-shared' import { PoolSettings, useFillCallback } from '../hooks/useFill' import { ConfirmDialog } from './ConfirmDialog' import { currentGasPriceSettings, currentGasNowSettings } from '../../Wallet/settings' -import { useITO_ContractAddress } from '../contracts/useITO_ContractAddress' import { WalletMessages } from '../../Wallet/messages' export enum ITOCreateFormPageStep { @@ -36,7 +35,7 @@ export function CompositionDialog(props: CompositionDialogProps) { const account = useAccount() const chainId = useChainId() - const ITO_CONTRACT_ADDRESS = useITO_ContractAddress() + const { ITO2_CONTRACT_ADDRESS } = useITOConstants() //#region step const [step, setStep] = useState(ITOCreateFormPageStep.NewItoPage) @@ -88,7 +87,7 @@ export function CompositionDialog(props: CompositionDialogProps) { // assemble JSON payload const payload: JSON_PayloadInMask = { - contract_address: ITO_CONTRACT_ADDRESS, + contract_address: ITO2_CONTRACT_ADDRESS, pid: FillSuccess.id, password: fillSettings.password, message: FillSuccess.message, diff --git a/packages/maskbook/src/plugins/ITO/UI/ConfirmDialog.tsx b/packages/maskbook/src/plugins/ITO/UI/ConfirmDialog.tsx index 02cd803da8f9..cc38edd3ccc5 100644 --- a/packages/maskbook/src/plugins/ITO/UI/ConfirmDialog.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/ConfirmDialog.tsx @@ -1,7 +1,10 @@ -import { formatAmountPrecision, formatBalance, FormattedAddress, FormattedBalance, ONE } from '@masknet/shared' +import { FormattedAddress, FormattedBalance } from '@masknet/shared' import { + formatAmountPrecision, + formatBalance, FungibleTokenDetailed, isNative, + ONE, resolveAddressLinkOnExplorer, resolveTokenLinkOnExplorer, useChainId, @@ -113,10 +116,10 @@ export function ConfirmDialog(props: ConfirmDialogProps) { const classes = useStyles() const { t } = useI18N() const chainId = useChainId() - const { DEFAULT_QUALIFICATION_ADDRESS } = useITOConstants() + const { DEFAULT_QUALIFICATION2_ADDRESS } = useITOConstants() const showQualification = poolSettings?.advanceSettingData.contract && - poolSettings?.qualificationAddress !== DEFAULT_QUALIFICATION_ADDRESS + poolSettings?.qualificationAddress !== DEFAULT_QUALIFICATION2_ADDRESS const stop = useCallback((ev: React.MouseEvent) => ev.stopPropagation(), []) const fillParamsResult = useFillParams(poolSettings) diff --git a/packages/maskbook/src/plugins/ITO/UI/CreateForm.tsx b/packages/maskbook/src/plugins/ITO/UI/CreateForm.tsx index 5721d6ec9cae..066f25ac08f1 100644 --- a/packages/maskbook/src/plugins/ITO/UI/CreateForm.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/CreateForm.tsx @@ -1,7 +1,10 @@ -import { formatAmount, formatBalance, isGreaterThan, isZero } from '@masknet/shared' import { ERC20TokenDetailed, EthereumTokenType, + formatAmount, + formatBalance, + isGreaterThan, + isZero, useAccount, useITOConstants, useTokenBalance, @@ -21,13 +24,11 @@ import { sliceTextByUILength, useI18N } from '../../../utils' import { DateTimePanel } from '../../../web3/UI/DateTimePanel' import { EthereumERC20TokenApprovedBoundary } from '../../../web3/UI/EthereumERC20TokenApprovedBoundary' import { EthereumWalletConnectedBoundary } from '../../../web3/UI/EthereumWalletConnectedBoundary' -import { useITO_ContractAddress } from '../contracts/useITO_ContractAddress' import type { ExchangeTokenAndAmountState } from '../hooks/useExchangeTokenAmountstate' import type { PoolSettings } from '../hooks/useFill' import { useQualificationVerify } from '../hooks/useQualificationVerify' import { decodeRegionCode, encodeRegionCode, regionCodes, useRegionSelect } from '../hooks/useRegion' -import type { AdvanceSettingData } from './AdvanceSetting' -import { AdvanceSetting } from './AdvanceSetting' +import { AdvanceSettingData, AdvanceSetting } from './AdvanceSetting' import { ExchangeTokenPanelGroup } from './ExchangeTokenPanelGroup' import { RegionSelect } from './RegionSelect' @@ -103,8 +104,7 @@ export function CreateForm(props: CreateFormProps) { const classes = useStylesExtends(useStyles(), props) const account = useAccount() - const ITO_CONTRACT_ADDRESS = useITO_ContractAddress() - const { DEFAULT_QUALIFICATION_ADDRESS } = useITOConstants() + const { ITO2_CONTRACT_ADDRESS, DEFAULT_QUALIFICATION2_ADDRESS } = useITOConstants() const currentIdentity = useCurrentIdentity() const senderName = currentIdentity?.identifier.userId ?? currentIdentity?.linkedPersona?.nickname ?? 'Unknown User' @@ -168,11 +168,14 @@ export function CreateForm(props: CreateFormProps) { // qualificationAddress const [qualificationAddress, setQualificationAddress] = useState( - origin?.qualificationAddress && origin.qualificationAddress !== DEFAULT_QUALIFICATION_ADDRESS + origin?.qualificationAddress && origin.qualificationAddress !== DEFAULT_QUALIFICATION2_ADDRESS ? origin.qualificationAddress : '', ) - const { value: qualification, loading: loadingQualification } = useQualificationVerify(qualificationAddress) + const { value: qualification, loading: loadingQualification } = useQualificationVerify( + qualificationAddress, + ITO2_CONTRACT_ADDRESS, + ) // advance settings const [advanceSettingData, setAdvanceSettingData] = useState(origin?.advanceSettingData || {}) @@ -202,7 +205,7 @@ export function CreateForm(props: CreateFormProps) { qualificationAddress: qualification?.isQualification && advanceSettingData.contract ? qualificationAddress - : DEFAULT_QUALIFICATION_ADDRESS, + : DEFAULT_QUALIFICATION2_ADDRESS, startTime, endTime, unlockTime: unlockTime > endTime && advanceSettingData.delayUnlocking ? unlockTime : undefined, @@ -412,7 +415,7 @@ export function CreateForm(props: CreateFormProps) { diff --git a/packages/maskbook/src/plugins/ITO/UI/ITO.tsx b/packages/maskbook/src/plugins/ITO/UI/ITO.tsx index 49536613146c..a791384572bb 100644 --- a/packages/maskbook/src/plugins/ITO/UI/ITO.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/ITO.tsx @@ -1,14 +1,19 @@ -import { formatAmountPrecision, formatBalance, formatEthereumAddress, isZero, pow10, ZERO } from '@masknet/shared' import { + formatAmountPrecision, + formatBalance, + formatEthereumAddress, FungibleTokenDetailed, getChainDetailed, isSameAddress, + isZero, + pow10, resolveLinkOnExplorer, TransactionStateType, useAccount, useChainId, useChainIdValid, useTokenConstants, + ZERO, } from '@masknet/web3-shared' import { Box, Card, Grid, Link, makeStyles, Theme, Typography } from '@material-ui/core' import OpenInNewIcon from '@material-ui/icons/OpenInNew' @@ -18,7 +23,7 @@ import formatDateTime from 'date-fns/format' import { useCallback, useEffect, useMemo, useState } from 'react' import { usePostLink } from '../../../components/DataSource/usePostInfo' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' -import { TokenIcon } from '../../../extension/options-page/DashboardComponents/TokenIcon' +import { TokenIcon } from '@masknet/shared' import { activatedSocialNetworkUI } from '../../../social-network' import { getAssetAsBlobURL, getTextUILength, useI18N, useRemoteControlledDialog } from '../../../utils' import { WalletMessages } from '../../Wallet/messages' @@ -203,7 +208,7 @@ export function ITO(props: ITO_Props) { const postLink = usePostLink() const chainId = useChainId() const chainIdValid = useChainIdValid() - const [destructState, destructCallback, resetDestructCallback] = useDestructCallback() + const [destructState, destructCallback, resetDestructCallback] = useDestructCallback(props.payload.contract_address) const [openClaimDialog, setOpenClaimDialog] = useState(false) const [claimDialogStatus, setClaimDialogStatus] = useState(SwapStatus.Remind) @@ -240,15 +245,15 @@ export function ITO(props: ITO_Props) { const { value: currentRegion, loading: loadingRegion } = useIPRegion() const allowRegions = decodeRegionCode(regions) const isRegionRestrict = checkRegionRestrict(allowRegions) - const isRegionAllow = !isRegionRestrict || (!loadingRegion && allowRegions.includes(currentRegion!.code)) + const isRegionAllow = + !isRegionRestrict || !currentRegion || (!loadingRegion && allowRegions.includes(currentRegion.code)) //#region if qualified const { value: ifQualified = false, loading: loadingIfQualified, - error: errorIfQualified, retry: retryIfQualified, - } = useIfQualified(payload.qualification_address) + } = useIfQualified(payload.qualification_address, payload.contract_address) //#endregion const { listOfStatus, startTime, unlockTime, isUnlocked, hasLockTime } = availabilityComputed @@ -266,9 +271,10 @@ export function ITO(props: ITO_Props) { //#region buy info const { value: tradeInfo, loading: loadingTradeInfo, retry: retryPoolTradeInfo } = usePoolTradeInfo(pid, account) const isBuyer = - chainId === payload.chain_id && - (payload.buyers.map((val) => val.address.toLowerCase()).includes(account.toLowerCase()) || - tradeInfo?.buyInfo?.buyer.address.toLowerCase() === account.toLowerCase()) + (chainId === payload.chain_id && + (payload.buyers.map((val) => val.address.toLowerCase()).includes(account.toLowerCase()) || + tradeInfo?.buyInfo?.buyer.address.toLowerCase() === account.toLowerCase())) || + new BigNumber(availability ? availability.swapped : 0).isGreaterThan(0) const shareSuccessLink = activatedSocialNetworkUI.utils .getShareLinkURL?.( t('plugin_ito_claim_success_share', { @@ -279,7 +285,11 @@ export function ITO(props: ITO_Props) { ) .toString() const canWithdraw = useMemo( - () => isAccountSeller && !tradeInfo?.destructInfo && (listOfStatus.includes(ITO_Status.expired) || noRemain), + () => + isAccountSeller && + !tradeInfo?.destructInfo && + !availability?.exchanged_tokens.every((t) => t === '0') && + (listOfStatus.includes(ITO_Status.expired) || noRemain), [tradeInfo, listOfStatus, isAccountSeller, noRemain], ) diff --git a/packages/maskbook/src/plugins/ITO/UI/ITO_Card.tsx b/packages/maskbook/src/plugins/ITO/UI/ITO_Card.tsx index 281efd24fdd3..ceb9e6539f70 100644 --- a/packages/maskbook/src/plugins/ITO/UI/ITO_Card.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/ITO_Card.tsx @@ -1,5 +1,4 @@ -import { formatBalance } from '@masknet/shared' -import { ERC20TokenDetailed, TransactionStateType } from '@masknet/web3-shared' +import { ERC20TokenDetailed, formatBalance, TransactionStateType } from '@masknet/web3-shared' import { Alert, Box, Skeleton, Typography } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' import { useCallback, useEffect } from 'react' diff --git a/packages/maskbook/src/plugins/ITO/UI/PoolInList.tsx b/packages/maskbook/src/plugins/ITO/UI/PoolInList.tsx index 6235f59e7c1f..e7357c62b5cd 100644 --- a/packages/maskbook/src/plugins/ITO/UI/PoolInList.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/PoolInList.tsx @@ -1,5 +1,14 @@ -import { formatBalance, FormattedBalance, isZero, pow10 } from '@masknet/shared' -import { getChainDetailed, isSameAddress, useAccount, useTokenConstants } from '@masknet/web3-shared' +import { FormattedBalance } from '@masknet/shared' +import { + formatBalance, + isZero, + pow10, + getChainDetailed, + isSameAddress, + useAccount, + useTokenConstants, + TransactionStateType, +} from '@masknet/web3-shared' import { Box, Card, @@ -17,13 +26,15 @@ import { import BigNumber from 'bignumber.js' import formatDateTime from 'date-fns/format' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' -import { TokenIcon } from '../../../extension/options-page/DashboardComponents/TokenIcon' +import { TokenIcon } from '@masknet/shared' import { debugModeSetting } from '../../../settings/settings' import { useI18N } from '../../../utils' import { MSG_DELIMITER } from '../constants' import { useAvailabilityComputed } from '../hooks/useAvailabilityComputed' import { usePoolTradeInfo } from '../hooks/usePoolTradeInfo' -import { ITO_Status, JSON_PayloadInMask } from '../types' +import { ITO_Status, JSON_PayloadInMask, PoolSubgraph } from '../types' +import { useDestructCallback } from '../hooks/useDestructCallback' +import { useTransactionDialog } from '../../../web3/hooks/useTransactionDialog' const useStyles = makeStyles((theme) => ({ top: { @@ -96,19 +107,23 @@ const useStyles = makeStyles((theme) => ({ }, })) -export interface PoolInListProps { - pool: JSON_PayloadInMask - exchange_in_volumes: string[] - exchange_out_volumes: string[] +export interface PoolInListProps extends PoolSubgraph { onSend?: (pool: JSON_PayloadInMask) => void - onWithdraw?: (payload: JSON_PayloadInMask) => void + onRetry: () => void } export function PoolInList(props: PoolInListProps) { const { t } = useI18N() const classes = useStyles() - const { pool, exchange_in_volumes, exchange_out_volumes, onSend, onWithdraw } = props + const { pool, exchange_in_volumes, exchange_out_volumes, onSend, onRetry } = props + //#region withdraw + const [destructState, destructCallback, resetDestructCallback] = useDestructCallback(pool.contract_address) + useTransactionDialog(null, destructState, TransactionStateType.CONFIRMED, () => { + onRetry() + resetDestructCallback() + }) + //#endregion const { NATIVE_TOKEN_ADDRESS } = useTokenConstants() const account = useAccount() const { computed: availabilityComputed, loading: loadingAvailability } = useAvailabilityComputed(pool) @@ -128,7 +143,7 @@ export function PoolInList(props: PoolInListProps) { return ( <> {loadingTradeInfo || loadingAvailability ? null : canWithdraw ? ( - onWithdraw?.(pool)}> + destructCallback(pool.pid)}> {t('plugin_ito_withdraw')} ) : canSend ? ( diff --git a/packages/maskbook/src/plugins/ITO/UI/PoolList.tsx b/packages/maskbook/src/plugins/ITO/UI/PoolList.tsx index c37a84cd8fdd..7702adca4a6e 100644 --- a/packages/maskbook/src/plugins/ITO/UI/PoolList.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/PoolList.tsx @@ -1,10 +1,10 @@ -import { TransactionStateType, useAccount } from '@masknet/web3-shared' +import { useAccount } from '@masknet/web3-shared' import { Box, CircularProgress, makeStyles, Typography } from '@material-ui/core' -import { useTransactionDialog } from '../../../web3/hooks/useTransactionDialog' import { useAllPoolsAsSeller } from '../hooks/useAllPoolsAsSeller' -import { useDestructCallback } from '../hooks/useDestructCallback' +import { useScrollBottomEvent } from '@masknet/shared' import type { JSON_PayloadInMask } from '../types' import { PoolInList } from './PoolInList' +import { useRef, useState, useCallback } from 'react' const useStyles = makeStyles((theme) => ({ root: { @@ -30,19 +30,16 @@ export interface PoolListProps { export function PoolList(props: PoolListProps) { const classes = useStyles() const account = useAccount() - const { value: pools = [], loading, retry } = useAllPoolsAsSeller(account) + const [page, setPage] = useState(0) + const { value: pools = [], loading, retry } = useAllPoolsAsSeller(account, page) - //#region withdraw - const [destructState, destructCallback, resetDestructCallback] = useDestructCallback() - useTransactionDialog(null, destructState, TransactionStateType.CONFIRMED, () => { - retry() - resetDestructCallback() - }) - //#endregion + const containerRef = useRef(null) + const addPage = useCallback(() => setPage(page + 1), [page]) + useScrollBottomEvent(containerRef, addPage) return ( -
- {loading ? ( +
+ {loading && page === 0 ? ( @@ -53,15 +50,9 @@ export function PoolList(props: PoolListProps) { ) : (
{pools.map((x) => ( - { - destructCallback(payload.pid) - }} - /> + ))} + {loading && page > 0 ? : null}
)}
diff --git a/packages/maskbook/src/plugins/ITO/UI/RemindDialog.tsx b/packages/maskbook/src/plugins/ITO/UI/RemindDialog.tsx index 254e63385473..535104b21c39 100644 --- a/packages/maskbook/src/plugins/ITO/UI/RemindDialog.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/RemindDialog.tsx @@ -5,7 +5,7 @@ import { FormattedAddress } from '@masknet/shared' import { useI18N } from '../../../utils' import { useStylesExtends } from '../../../components/custom-ui-helper' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' -import { TokenIcon } from '../../../extension/options-page/DashboardComponents/TokenIcon' +import { TokenIcon } from '@masknet/shared' import { resolveLinkOnExplorer, FungibleTokenDetailed, ChainId } from '@masknet/web3-shared' import { SwapStatus } from './SwapGuide' diff --git a/packages/maskbook/src/plugins/ITO/UI/ShareDialog.tsx b/packages/maskbook/src/plugins/ITO/UI/ShareDialog.tsx index 460c33ae6242..4e1ddea2ce4c 100644 --- a/packages/maskbook/src/plugins/ITO/UI/ShareDialog.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/ShareDialog.tsx @@ -1,9 +1,9 @@ import { useCallback } from 'react' -import { makeStyles, Typography, Box } from '@material-ui/core' -import { formatBalance, isZero } from '@masknet/shared' -import { useI18N, getAssetAsBlobURL } from '../../../utils' +import { Box, makeStyles, Typography } from '@material-ui/core' +import { getAssetAsBlobURL, useI18N } from '../../../utils' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' import type { FungibleTokenDetailed } from '@masknet/web3-shared' +import { formatBalance, isZero } from '@masknet/web3-shared' import { useStylesExtends } from '../../../components/custom-ui-helper' import type { BigNumber } from 'bignumber.js' diff --git a/packages/maskbook/src/plugins/ITO/UI/SwapDialog.tsx b/packages/maskbook/src/plugins/ITO/UI/SwapDialog.tsx index 90c43fcc27b7..82d67c83840d 100644 --- a/packages/maskbook/src/plugins/ITO/UI/SwapDialog.tsx +++ b/packages/maskbook/src/plugins/ITO/UI/SwapDialog.tsx @@ -1,22 +1,24 @@ -import { useState, useMemo, useCallback, useEffect } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import BigNumber from 'bignumber.js' import { v4 as uuid } from 'uuid' -import { makeStyles, Typography, Slider, CircularProgress } from '@material-ui/core' -import { formatBalance, pow10, ZERO } from '@masknet/shared' +import { CircularProgress, makeStyles, Slider, Typography } from '@material-ui/core' -import { useRemoteControlledDialog, useI18N } from '../../../utils' +import { useI18N, useRemoteControlledDialog } from '../../../utils' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' import { - FungibleTokenDetailed, + ChainId, + currySameAddress, ERC20TokenDetailed, EthereumTokenType, - ChainId, - TransactionStateType, - useTokenBalance, + formatBalance, + FungibleTokenDetailed, + isNative, + pow10, resolveTransactionLinkOnExplorer, + TransactionStateType, useChainId, - isNative, - currySameAddress, + useTokenBalance, + ZERO, } from '@masknet/web3-shared' import { SelectTokenDialogEvent, WalletMessages, WalletRPC } from '../../Wallet/messages' import { TokenAmountPanel } from '../../../web3/UI/TokenAmountPanel' @@ -24,7 +26,6 @@ import { useSwapCallback } from '../hooks/useSwapCallback' import { useStylesExtends } from '../../../components/custom-ui-helper' import type { JSON_PayloadInMask } from '../types' import { SwapStatus } from './SwapGuide' -import { useITO_ContractAddress } from '../contracts/useITO_ContractAddress' import { EthereumERC20TokenApprovedBoundary } from '../../../web3/UI/EthereumERC20TokenApprovedBoundary' import { EthereumWalletConnectedBoundary } from '../../../web3/UI/EthereumWalletConnectedBoundary' import { useQualificationVerify } from '../hooks/useQualificationVerify' @@ -115,12 +116,12 @@ export function SwapDialog(props: SwapDialogProps) { const chainId = useChainId() const classes = useStylesExtends(useStyles(), props) - const ITO_CONTRACT_ADDRESS = useITO_ContractAddress() const [ratio, setRatio] = useState( new BigNumber(payload.exchange_amounts[0 * 2]).dividedBy(payload.exchange_amounts[0 * 2 + 1]), ) const [swapToken, setSwapToken] = useState(payload.exchange_tokens[0]) + const [swapAmount, setSwapAmount] = useState(tokenAmount.multipliedBy(ratio)) const [inputAmountForUI, setInputAmountForUI] = useState( swapAmount.isZero() ? '' : formatBalance(swapAmount, swapToken.decimals), @@ -189,6 +190,7 @@ export function SwapDialog(props: SwapDialogProps) { //#region swap const { value: qualificationInfo, loading: loadingQualification } = useQualificationVerify( payload.qualification_address, + payload.contract_address, ) const [swapState, swapCallback, resetSwapCallback] = useSwapCallback( @@ -308,7 +310,7 @@ export function SwapDialog(props: SwapDialogProps) { - + href={resolveAddressLinkOnExplorer(chainId, ITO2_CONTRACT_ADDRESS)}> + {' '} to use your {token.symbol ?? 'Token'} tokens when a new ITO round starts later. - + {(allowance: string) => ( {isMoreThanMillion(allowance, token.decimals) diff --git a/packages/maskbook/src/plugins/ITO/apis/index.ts b/packages/maskbook/src/plugins/ITO/apis/index.ts index 3c5c501e7fc4..b46edeaad0ed 100644 --- a/packages/maskbook/src/plugins/ITO/apis/index.ts +++ b/packages/maskbook/src/plugins/ITO/apis/index.ts @@ -145,14 +145,16 @@ export async function getPool(pid: string) { return payloadIntoMask(data.pool) } -export async function getAllPoolsAsSeller(address: string) { +export async function getAllPoolsAsSeller(address: string, page: number) { const response = await fetch(getITOConstants(currentChainIdSettings.value).SUBGRAPH_URL, { method: 'POST', mode: 'cors', body: stringify({ query: ` { - sellInfos (where: { seller: "${address.toLowerCase()}" }) { + sellInfos ( orderBy: timestamp, orderDirection: desc, first: 50, skip: ${ + page * 50 + }, where: { seller: "${address.toLowerCase()}" }) { pool { ${POOL_FIELDS} exchange_in_volumes @@ -211,12 +213,14 @@ export async function getAllPoolsAsBuyer(address: string) { }[] } } - return data.buyInfos.map((x) => { - const pool = payloadIntoMask(omit(x.pool, ['exchange_in_volumes', 'exchange_out_volumes'])) - return { - pool, - exchange_in_volumes: x.pool.exchange_in_volumes, - exchange_out_volumes: x.pool.exchange_out_volumes, - } - }) + return data + ? data.buyInfos.map((x) => { + const pool = payloadIntoMask(omit(x.pool, ['exchange_in_volumes', 'exchange_out_volumes'])) + return { + pool, + exchange_in_volumes: x.pool.exchange_in_volumes, + exchange_out_volumes: x.pool.exchange_out_volumes, + } + }) + : [] } diff --git a/packages/maskbook/src/plugins/ITO/constants.ts b/packages/maskbook/src/plugins/ITO/constants.ts index 0c325eb191c0..2a02d9dcf496 100644 --- a/packages/maskbook/src/plugins/ITO/constants.ts +++ b/packages/maskbook/src/plugins/ITO/constants.ts @@ -6,6 +6,8 @@ export const ITO_CONTRACT_BASE_TIMESTAMP = new Date('2021-03-29T00:00:00.000Z'). export const TIME_WAIT_BLOCKCHAIN = 30000 // Keccak-256(ifQualified(address)) XOR Keccak-256(logQualified(address,uint256)) export const QUALIFICATION_INTERFACE_ID = '0xfb036a85' +// Keccak-256(ifQualified(address,bytes32[])) XOR Keccak-256(logQualified(address,bytes32[])) +export const QUALIFICATION2_INTERFACE_ID = '0x6762aec5' // Keccak-256(get_start_time()) export const QUALIFICATION_HAS_START_TIME_INTERFACE_ID = '0xdf29dfc4' // Keccak-256(isLucky(address)) diff --git a/packages/maskbook/src/plugins/ITO/contracts/useITO_Contract.ts b/packages/maskbook/src/plugins/ITO/contracts/useITO_Contract.ts index 887c47d5e9da..1bc59e286c1d 100644 --- a/packages/maskbook/src/plugins/ITO/contracts/useITO_Contract.ts +++ b/packages/maskbook/src/plugins/ITO/contracts/useITO_Contract.ts @@ -1,18 +1,16 @@ -import ITO_BSC_POLYGON_ABI from '@masknet/contracts/abis/BscPolygonITO.json' +import type { AbiItem } from 'web3-utils' import ITO_ABI from '@masknet/contracts/abis/ITO.json' -import type { BscPolygonITO } from '@masknet/contracts/types/BscPolygonITO' +import ITO2_ABI from '@masknet/contracts/abis/ITO2.json' import type { ITO } from '@masknet/contracts/types/ITO' -import { NetworkType, useContract, useITOConstants, useNetworkType } from '@masknet/web3-shared' -import type { AbiItem } from 'web3-utils' +import type { ITO2 } from '@masknet/contracts/types/ITO2' +import { useITOConstants, useContract, isSameAddress } from '@masknet/web3-shared' export function useITO_Contract(contractAddress?: string) { - const { ITO_CONTRACT_ADDRESS, ITO_BSC_POLYGON_CONTRACT_ADDRESS } = useITOConstants() - const ITO_CONTRACT = useContract(contractAddress ?? ITO_CONTRACT_ADDRESS, ITO_ABI as AbiItem[]) - const ITO_BSC_POLYGON_CONTRACT = useContract( - contractAddress ?? ITO_BSC_POLYGON_CONTRACT_ADDRESS, - ITO_BSC_POLYGON_ABI as AbiItem[], - ) - const networkType = useNetworkType() + const { ITO_CONTRACT_ADDRESS, ITO2_CONTRACT_ADDRESS } = useITOConstants() + const ITO_CONTRACT = useContract(ITO_CONTRACT_ADDRESS, ITO_ABI as AbiItem[]) + const ITO2_CONTRACT = useContract(ITO2_CONTRACT_ADDRESS, ITO2_ABI as AbiItem[]) - return networkType === NetworkType.Ethereum ? ITO_CONTRACT : ITO_BSC_POLYGON_CONTRACT + return contractAddress && isSameAddress(contractAddress, ITO_CONTRACT_ADDRESS) + ? { contract: ITO_CONTRACT, version: 1 } + : { contract: ITO2_CONTRACT, version: 2 } } diff --git a/packages/maskbook/src/plugins/ITO/contracts/useITO_ContractAddress.ts b/packages/maskbook/src/plugins/ITO/contracts/useITO_ContractAddress.ts deleted file mode 100644 index e348daf036d3..000000000000 --- a/packages/maskbook/src/plugins/ITO/contracts/useITO_ContractAddress.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NetworkType, useITOConstants, useNetworkType } from '@masknet/web3-shared' - -export function useITO_ContractAddress() { - const { ITO_CONTRACT_ADDRESS, ITO_BSC_POLYGON_CONTRACT_ADDRESS } = useITOConstants() - const networkType = useNetworkType() - - return networkType === NetworkType.Ethereum ? ITO_CONTRACT_ADDRESS : ITO_BSC_POLYGON_CONTRACT_ADDRESS -} diff --git a/packages/maskbook/src/plugins/ITO/contracts/useQualificationContract.ts b/packages/maskbook/src/plugins/ITO/contracts/useQualificationContract.ts index 4304eb57d4fc..04e47438087f 100644 --- a/packages/maskbook/src/plugins/ITO/contracts/useQualificationContract.ts +++ b/packages/maskbook/src/plugins/ITO/contracts/useQualificationContract.ts @@ -1,8 +1,22 @@ import type { AbiItem } from 'web3-utils' import type { Qualification } from '@masknet/contracts/types/Qualification' +import type { Qualification2 } from '@masknet/contracts/types/Qualification2' import QualificationABI from '@masknet/contracts/abis/Qualification.json' -import { useContract } from '@masknet/web3-shared' +import Qualification2ABI from '@masknet/contracts/abis/Qualification2.json' +import { useContract, isSameAddress, useITOConstants } from '@masknet/web3-shared' -export function useQualificationContract(address: string) { - return useContract(address, QualificationABI as AbiItem[]) +export function useQualificationContract(address: string, ito_address: string) { + const { ITO_CONTRACT_ADDRESS } = useITOConstants() + const QLF_CONTRACT = useContract(address, QualificationABI as AbiItem[]) + const QLF2_CONTRACT = useContract(address, Qualification2ABI as AbiItem[]) + + return isSameAddress(ito_address, ITO_CONTRACT_ADDRESS) + ? { + version: 1, + contract: QLF_CONTRACT, + } + : { + version: 2, + contract: QLF2_CONTRACT, + } } diff --git a/packages/maskbook/src/plugins/ITO/define.tsx b/packages/maskbook/src/plugins/ITO/define.tsx index d0cc0ab0eb50..e59de714c4f1 100644 --- a/packages/maskbook/src/plugins/ITO/define.tsx +++ b/packages/maskbook/src/plugins/ITO/define.tsx @@ -1,8 +1,8 @@ import { makeStyles } from '@material-ui/core' -import { formatBalance, formatEthereumAddress } from '@masknet/shared' +import { formatBalance, formatEthereumAddress } from '@masknet/web3-shared' import { PostInspector } from './UI/PostInspector' import { PluginConfig, PluginScope, PluginStage } from '../types' -import { ITO_MetaKey, ITO_PluginID } from './constants' +import { ITO_MetaKey, ITO_PluginID, MSG_DELIMITER } from './constants' import type { JSON_PayloadOutMask } from './types' import { ITO_MetadataReader, payloadIntoMask } from './helpers' import MaskbookPluginWrapper from '../MaskbookPluginWrapper' @@ -36,7 +36,7 @@ function LabelWrapper(props: LabelWrapperProps) { } export const [ITO_CompositionEntry, ITO_CompositionUI] = createCompositionDialog( - , + , (props) => , ) @@ -61,7 +61,9 @@ export const ITO_PluginDefine: PluginConfig = { [ ITO_MetaKey, (payload: JSON_PayloadOutMask) => { - const sellerName = payload.seller.name ?? formatEthereumAddress(payload.seller.address, 4) + const sellerName = payload.seller.name + ? payload.seller.name + : payload.message.split(MSG_DELIMITER)[0] ?? formatEthereumAddress(payload.seller.address, 4) return ( ([]) return useAsyncRetry(async () => { - const pools = await PluginITO_RPC.getAllPoolsAsSeller(address) - return pools.reverse() - }, [address]) + const pools = await PluginITO_RPC.getAllPoolsAsSeller(address, page) + allPoolsRef.current = allPoolsRef.current.concat(pools) + return allPoolsRef.current + }, [address, page]) } diff --git a/packages/maskbook/src/plugins/ITO/hooks/useAvailability.ts b/packages/maskbook/src/plugins/ITO/hooks/useAvailability.ts index afa0da2988e9..3d371a9f9d90 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useAvailability.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useAvailability.ts @@ -4,7 +4,7 @@ import { useITO_Contract } from '../contracts/useITO_Contract' export function useAvailability(id?: string, contract_address?: string) { const account = useAccount() - const ITO_Contract = useITO_Contract(contract_address) + const { contract: ITO_Contract } = useITO_Contract(contract_address) return useAsyncRetry(async () => { if (!id) return null diff --git a/packages/maskbook/src/plugins/ITO/hooks/useAvailabilityComputed.ts b/packages/maskbook/src/plugins/ITO/hooks/useAvailabilityComputed.ts index 0c0e255d9561..413a6d11a71f 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useAvailabilityComputed.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useAvailabilityComputed.ts @@ -10,7 +10,10 @@ import { ITO_CONTRACT_BASE_TIMESTAMP } from '../constants' export function useAvailabilityComputed(payload: JSON_PayloadInMask) { const chainId = useChainId() const asyncResult = useAvailability(payload.pid, payload.contract_address) - const { value: qualification_start_time } = useQualification(payload.qualification_address) + const { value: qualification_start_time } = useQualification( + payload.qualification_address, + payload.contract_address, + ) //#region ticker const [_, setTicker] = useState(0) diff --git a/packages/maskbook/src/plugins/ITO/hooks/useClaimAll.ts b/packages/maskbook/src/plugins/ITO/hooks/useClaimAll.ts index e0195586a3ac..36994bbb8188 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useClaimAll.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useClaimAll.ts @@ -1,5 +1,12 @@ import { useAsyncRetry } from 'react-use' -import { getChainDetailed, useAccount, useChainId, FungibleTokenDetailed } from '@masknet/web3-shared' +import { + getChainDetailed, + useAccount, + useChainId, + FungibleTokenDetailed, + useITOConstants, + ChainId, +} from '@masknet/web3-shared' import { useAllPoolsAsBuyer } from './useAllPoolsAsBuyer' import { useITO_Contract } from '../contracts/useITO_Contract' @@ -11,15 +18,18 @@ export interface SwappedToken { unlockTime: Date } -export function useClaimAll() { +export function useClaimAll(isMainnetOld = false) { const account = useAccount() const chainId = useChainId() - const ITO_Contract = useITO_Contract() + const { ITO_CONTRACT_ADDRESS } = useITOConstants() + // Todo: Remove the code after the period that old ITO is being used and continues to be used for a while + const { contract: ITO_Contract } = useITO_Contract(isMainnetOld ? ITO_CONTRACT_ADDRESS : undefined) const { value: pools = [], loading } = useAllPoolsAsBuyer(account) return useAsyncRetry(async () => { const chainDetailed = getChainDetailed(chainId) if (!chainDetailed) return [] + if (isMainnetOld && chainId !== ChainId.Mainnet) return [] if (!ITO_Contract || loading) return undefined if (pools.length === 0) return [] diff --git a/packages/maskbook/src/plugins/ITO/hooks/useClaimCallback.ts b/packages/maskbook/src/plugins/ITO/hooks/useClaimCallback.ts index 8ce8339550e4..7c23bc72d84f 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useClaimCallback.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useClaimCallback.ts @@ -2,23 +2,23 @@ import { useCallback } from 'react' import stringify from 'json-stable-stringify' import type { NonPayableTx } from '@masknet/contracts/types/types' import { + isZero, TransactionEventType, TransactionStateType, useAccount, useChainId, - useTransactionState, useGasPrice, useNonce, + useTransactionState, } from '@masknet/web3-shared' import { useITO_Contract } from '../contracts/useITO_Contract' -import { isZero } from '@masknet/shared' export function useClaimCallback(pids: string[], contractAddress?: string) { const nonce = useNonce() const gasPrice = useGasPrice() const account = useAccount() const chainId = useChainId() - const ITO_Contract = useITO_Contract(contractAddress) + const { contract: ITO_Contract } = useITO_Contract(contractAddress) const [claimState, setClaimState] = useTransactionState() const claimCallback = useCallback(async () => { diff --git a/packages/maskbook/src/plugins/ITO/hooks/useDestructCallback.ts b/packages/maskbook/src/plugins/ITO/hooks/useDestructCallback.ts index ef06380cc7b8..829db605ca5a 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useDestructCallback.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useDestructCallback.ts @@ -11,11 +11,11 @@ import { } from '@masknet/web3-shared' import { useITO_Contract } from '../contracts/useITO_Contract' -export function useDestructCallback() { +export function useDestructCallback(ito_address: string) { const nonce = useNonce() const gasPrice = useGasPrice() const account = useAccount() - const ITO_Contract = useITO_Contract() + const { contract: ITO_Contract } = useITO_Contract(ito_address) const [destructState, setDestructState] = useTransactionState() const destructCallback = useCallback( diff --git a/packages/maskbook/src/plugins/ITO/hooks/useFill.ts b/packages/maskbook/src/plugins/ITO/hooks/useFill.ts index 8d3a09c59fea..eb6d1f9ac277 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useFill.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useFill.ts @@ -3,24 +3,28 @@ import { useAsync } from 'react-use' import { omit } from 'lodash-es' import BigNumber from 'bignumber.js' import Web3Utils from 'web3-utils' -import type { ITO } from '@masknet/contracts/types/ITO' +import type { ITO2 } from '@masknet/contracts/types/ITO2' import type { NonPayableTx } from '@masknet/contracts/types/types' import { + isGreaterThan, + ONE, + pow10, TransactionEventType, TransactionStateType, useAccount, useChainId, - useTransactionState, useGasPrice, useNonce, + useTransactionState, useWeb3, + FungibleTokenDetailed, + ERC20TokenDetailed, + TransactionState, } from '@masknet/web3-shared' import { useITO_Contract } from '../contracts/useITO_Contract' -import type { FungibleTokenDetailed, ERC20TokenDetailed, TransactionState } from '@masknet/web3-shared' import { gcd, sortTokens } from '../helpers' -import { ITO_CONTRACT_BASE_TIMESTAMP, MSG_DELIMITER, FAKE_SIGN_PASSWORD } from '../constants' +import { FAKE_SIGN_PASSWORD, ITO_CONTRACT_BASE_TIMESTAMP, MSG_DELIMITER } from '../constants' import type { AdvanceSettingData } from '../UI/AdvanceSetting' -import { isGreaterThan, ONE, pow10 } from '@masknet/shared' import { useI18N } from '../../../utils/i18n-next-ui' export interface PoolSettings { @@ -66,7 +70,7 @@ export function useFillCallback(poolSettings?: PoolSettings) { const gasPrice = useGasPrice() const account = useAccount() const chainId = useChainId() - const ITO_Contract = useITO_Contract() + const { contract: ITO_Contract } = useITO_Contract() const { t } = useI18N() const [fillState, setFillState] = useTransactionState() const [fillSettings, setFillSettings] = useState(poolSettings) @@ -96,6 +100,7 @@ export function useFillCallback(poolSettings?: PoolSettings) { type: TransactionStateType.FAILED, error: gasError, }) + return } if (!checkParams(paramsObj, setFillState)) return @@ -139,7 +144,7 @@ export function useFillCallback(poolSettings?: PoolSettings) { // send transaction and wait for hash return new Promise(async (resolve, reject) => { - const promiEvent = ITO_Contract.methods.fill_pool(...params).send(config as NonPayableTx) + const promiEvent = (ITO_Contract as ITO2).methods.fill_pool(...params).send(config as NonPayableTx) promiEvent .on(TransactionEventType.TRANSACTION_HASH, (hash) => { @@ -171,7 +176,7 @@ export function useFillCallback(poolSettings?: PoolSettings) { reject(error) }) }) - }, [web3, gasPrice, nonce, account, chainId, ITO_Contract, poolSettings, paramResult]) + }, [web3, gasPrice, nonce, account, chainId, ITO_Contract, poolSettings, paramResult, setFillState]) const resetCallback = useCallback(() => { setFillState({ @@ -183,7 +188,7 @@ export function useFillCallback(poolSettings?: PoolSettings) { } export function useFillParams(poolSettings: PoolSettings | undefined) { - const ITO_Contract = useITO_Contract() + const { contract: ITO_Contract } = useITO_Contract() const account = useAccount() return useAsync(async () => { @@ -266,10 +271,10 @@ export function useFillParams(poolSettings: PoolSettings | undefined) { 'exchangeTokens', 'token', ]), - ) as Parameters + ) as Parameters let gasError = null as Error | null - const gas = (await ITO_Contract.methods + const gas = (await (ITO_Contract as ITO2).methods .fill_pool(...params) .estimateGas({ from: account, diff --git a/packages/maskbook/src/plugins/ITO/hooks/useIfQualified.ts b/packages/maskbook/src/plugins/ITO/hooks/useIfQualified.ts index 96be0574352e..94e65284de68 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useIfQualified.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useIfQualified.ts @@ -1,14 +1,20 @@ import { useAsyncRetry } from 'react-use' import { useAccount } from '@masknet/web3-shared' +import type { Qualification } from '@masknet/contracts/types/Qualification' +import type { Qualification2 } from '@masknet/contracts/types/Qualification2' import { useQualificationContract } from '../contracts/useQualificationContract' -export function useIfQualified(address: string) { +export function useIfQualified(address: string, ito_address: string) { const account = useAccount() - const qualificationContract = useQualificationContract(address) + const { contract: qualificationContract, version } = useQualificationContract(address, ito_address) return useAsyncRetry(async () => { if (!qualificationContract) return false - return qualificationContract.methods.ifQualified(account).call({ + return ( + version === 1 + ? (qualificationContract as Qualification).methods.ifQualified(account) + : (qualificationContract as Qualification2).methods.ifQualified(account, []) + ).call({ from: account, }) }, [account, qualificationContract]) diff --git a/packages/maskbook/src/plugins/ITO/hooks/useQualification.ts b/packages/maskbook/src/plugins/ITO/hooks/useQualification.ts index 86d778f307dd..01a234307fe8 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useQualification.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useQualification.ts @@ -1,12 +1,10 @@ import { useAsyncRetry } from 'react-use' -import type { AbiItem } from 'web3-utils' -import type { Qualification } from '@masknet/contracts/types/Qualification' -import QualificationABI from '@masknet/contracts/abis/Qualification.json' -import { useAccount, useContract } from '@masknet/web3-shared' +import { useAccount } from '@masknet/web3-shared' +import { useQualificationContract } from '../contracts/useQualificationContract' -export function useQualification(qualification_address: string) { +export function useQualification(qualification_address: string, ito_address: string) { const account = useAccount() - const qualificationContract = useContract(qualification_address, QualificationABI as AbiItem[]) + const { contract: qualificationContract } = useQualificationContract(qualification_address, ito_address) return useAsyncRetry(async () => { const startTime = await qualificationContract!.methods.get_start_time().call({ from: account }) diff --git a/packages/maskbook/src/plugins/ITO/hooks/useQualificationVerify.ts b/packages/maskbook/src/plugins/ITO/hooks/useQualificationVerify.ts index 14930d929f71..0bdf26d3d9b7 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useQualificationVerify.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useQualificationVerify.ts @@ -1,33 +1,30 @@ import { useAsyncRetry } from 'react-use' -import type { AbiItem } from 'web3-utils' import type { Qualification } from '@masknet/contracts/types/Qualification' -import QualificationABI from '@masknet/contracts/abis/Qualification.json' +import type { Qualification2 } from '@masknet/contracts/types/Qualification2' import { QUALIFICATION_INTERFACE_ID, + QUALIFICATION2_INTERFACE_ID, QUALIFICATION_HAS_START_TIME_INTERFACE_ID, QUALIFICATION_HAS_LUCKY_INTERFACE_ID, } from '../constants' -import { useAccount, useContract, useERC165 } from '@masknet/web3-shared' +import { useAccount, useERC165 } from '@masknet/web3-shared' +import { useQualificationContract } from '../contracts/useQualificationContract' -export function useQualificationVerify(address: string) { +export function useQualificationVerify(address: string, ito_address: string) { const account = useAccount() - const qualificationContract = useContract(address, QualificationABI as AbiItem[]) - const { value: isQualificationHasLucky, loading: loadingQualificationHasLucky } = useERC165( + const { contract: qualificationContract, version } = useQualificationContract(address, ito_address) + const { value: isQualificationHasLucky, loading: loadingQualificationHasLucky } = useERC165< + Qualification | Qualification2 + >(qualificationContract, address, QUALIFICATION_HAS_LUCKY_INTERFACE_ID) + const { value: isQualification, loading: loadingQualification } = useERC165( qualificationContract, address, - QUALIFICATION_HAS_LUCKY_INTERFACE_ID, - ) - const { value: isQualification, loading: loadingQualification } = useERC165( - qualificationContract, - address, - QUALIFICATION_INTERFACE_ID, + version === 1 ? QUALIFICATION_INTERFACE_ID : QUALIFICATION2_INTERFACE_ID, ) - const { value: qualificationHasStartTime, loading: loadingQualificationHasStartTime } = useERC165( - qualificationContract, - address, - QUALIFICATION_HAS_START_TIME_INTERFACE_ID, - ) + const { value: qualificationHasStartTime, loading: loadingQualificationHasStartTime } = useERC165< + Qualification | Qualification2 + >(qualificationContract, address, QUALIFICATION_HAS_START_TIME_INTERFACE_ID) return useAsyncRetry(async () => { let startTime diff --git a/packages/maskbook/src/plugins/ITO/hooks/useSwapCallback.ts b/packages/maskbook/src/plugins/ITO/hooks/useSwapCallback.ts index 9ce77a8caf30..6babbef6599f 100644 --- a/packages/maskbook/src/plugins/ITO/hooks/useSwapCallback.ts +++ b/packages/maskbook/src/plugins/ITO/hooks/useSwapCallback.ts @@ -1,10 +1,13 @@ import type { ITO } from '@masknet/contracts/types/ITO' +import type { ITO2 } from '@masknet/contracts/types/ITO2' +import type { Qualification } from '@masknet/contracts/types/Qualification' +import type { Qualification2 } from '@masknet/contracts/types/Qualification2' import type { PayableTx } from '@masknet/contracts/types/types' -import { isZero } from '@masknet/shared' import { currySameAddress, EthereumTokenType, FungibleTokenDetailed, + isZero, TransactionEventType, TransactionStateType, useAccount, @@ -32,9 +35,12 @@ export function useSwapCallback( const nonce = useNonce() const gasPrice = useGasPrice() const account = useAccount() - const ITO_Contract = useITO_Contract() + const { contract: ITO_Contract, version } = useITO_Contract(payload.contract_address) const [swapState, setSwapState] = useTransactionState() - const qualificationContract = useQualificationContract(payload.qualification_address) + const { contract: qualificationContract } = useQualificationContract( + payload.qualification_address, + payload.contract_address, + ) const swapCallback = useCallback(async () => { if (!ITO_Contract || !qualificationContract || !payload) { @@ -85,7 +91,10 @@ export function useSwapCallback( // error: not qualified try { - const ifQualified = await qualificationContract.methods.ifQualified(account).call({ + const ifQualified = await (version === 1 + ? (qualificationContract as Qualification).methods.ifQualified(account) + : (qualificationContract as Qualification2).methods.ifQualified(account, []) + ).call({ from: account, }) if (!ifQualified) { @@ -128,7 +137,7 @@ export function useSwapCallback( return } - const swapParams = [ + const swapParamsV1 = [ pid, Web3Utils.soliditySha3( Web3Utils.hexToNumber(`0x${buf2hex(hex2buf(Web3Utils.sha3(password) ?? '').slice(0, 5))}`), @@ -139,14 +148,27 @@ export function useSwapCallback( total, ] as Parameters + const swapParamsV2 = [ + pid, + Web3Utils.soliditySha3( + Web3Utils.hexToNumber(`0x${buf2hex(hex2buf(Web3Utils.sha3(password) ?? '').slice(0, 5))}`), + account, + )!, + swapTokenAt, + total, + [], + ] as Parameters + // estimate gas and compose transaction const value = new BigNumber(token.type === EthereumTokenType.Native ? total : '0').toFixed() const config = { from: account, gas: isQualificationHasLucky ? 200000 - : await ITO_Contract.methods - .swap(...swapParams) + : await (version === 1 + ? (ITO_Contract as ITO).methods.swap(...swapParamsV1) + : (ITO_Contract as ITO2).methods.swap(...swapParamsV2) + ) .estimateGas({ from: account, value, @@ -188,7 +210,11 @@ export function useSwapCallback( }) resolve() } - const promiEvent = ITO_Contract.methods.swap(...swapParams).send(config as PayableTx) + const promiEvent = ( + version === 1 + ? (ITO_Contract as ITO).methods.swap(...swapParamsV1) + : (ITO_Contract as ITO2).methods.swap(...swapParamsV2) + ).send(config as PayableTx) promiEvent .on(TransactionEventType.TRANSACTION_HASH, onHash) diff --git a/packages/maskbook/src/plugins/ITO/services.ts b/packages/maskbook/src/plugins/ITO/services.ts index af77432d49cd..22aedd364f25 100644 --- a/packages/maskbook/src/plugins/ITO/services.ts +++ b/packages/maskbook/src/plugins/ITO/services.ts @@ -17,9 +17,9 @@ export async function getPool(pid: string) { return poolFromChain } -export async function getAllPoolsAsSeller(address: string) { +export async function getAllPoolsAsSeller(address: string, page: number) { const chainId = currentChainIdSettings.value - const poolsFromChain = await subgraph.getAllPoolsAsSeller(address) + const poolsFromChain = await subgraph.getAllPoolsAsSeller(address, page) const poolsFromDB = await database.getPoolsFromDB(poolsFromChain.map((x) => x.pool.pid)) return poolsFromChain .map((x) => { diff --git a/packages/maskbook/src/plugins/ITO/types.ts b/packages/maskbook/src/plugins/ITO/types.ts index 6a4eb58bb96e..2ee8a62d211a 100644 --- a/packages/maskbook/src/plugins/ITO/types.ts +++ b/packages/maskbook/src/plugins/ITO/types.ts @@ -32,6 +32,12 @@ export interface JSON_PayloadInMask { test_nums?: number[] } +export interface PoolSubgraph { + pool: JSON_PayloadInMask + exchange_in_volumes: string[] + exchange_out_volumes: string[] +} + //#region TokenOutMask export type TokenOutMask = Omit & { chain_id: ChainId diff --git a/packages/maskbook/src/plugins/PluginSerivce.ts b/packages/maskbook/src/plugins/PluginSerivce.ts index 914a621d8757..de997f7ef123 100644 --- a/packages/maskbook/src/plugins/PluginSerivce.ts +++ b/packages/maskbook/src/plugins/PluginSerivce.ts @@ -8,14 +8,7 @@ */ // Please make sure you have registered your plugin UI at ./PluginUI -import './Wallet/messages' -import './RedPacket/messages' -import './Gitcoin/messages' -import './FileService/utils' -import './Polls/utils' import './Transak/messages' import './Trader/messages' -import './Polls/utils' import './ITO/messages' -import './Airdrop/messages' import './dHEDGE/messages' diff --git a/packages/maskbook/src/plugins/PluginUI.ts b/packages/maskbook/src/plugins/PluginUI.ts index 4131c69a7a27..f735e4eb09e8 100644 --- a/packages/maskbook/src/plugins/PluginUI.ts +++ b/packages/maskbook/src/plugins/PluginUI.ts @@ -7,23 +7,15 @@ const plugins = new Set() export const PluginUI: ReadonlySet = plugins import { Flags } from '../utils/flags' -import { PollsPluginDefine } from './Polls/define' import { StorybookPluginDefine } from './Storybook/define' -import { FileServicePluginDefine } from './FileService/UI-define' import { TraderPluginDefine } from './Trader/define' -import { TransakPluginDefine } from './Transak/define' import { ITO_PluginDefine } from './ITO/define' import { sideEffect } from '../utils/side-effects' -import { VCentPluginDefine } from './VCent/define' import { DHedgePluginDefine } from './dHEDGE/define' sideEffect.then(() => { - plugins.add(FileServicePluginDefine) if (Flags.ito_enabled) plugins.add(ITO_PluginDefine) - if (Flags.vcent_enabled) plugins.add(VCentPluginDefine) - if (Flags.poll_enabled) plugins.add(PollsPluginDefine) if (Flags.trader_enabled) plugins.add(TraderPluginDefine) - if (Flags.transak_enabled) plugins.add(TransakPluginDefine) if (Flags.dhedge_enabled) plugins.add(DHedgePluginDefine) if (process.env.STORYBOOK) plugins.add(StorybookPluginDefine) }) diff --git a/packages/maskbook/src/plugins/Polls/UI/Polls.tsx b/packages/maskbook/src/plugins/Polls/SNSAdaptor/Polls.tsx similarity index 100% rename from packages/maskbook/src/plugins/Polls/UI/Polls.tsx rename to packages/maskbook/src/plugins/Polls/SNSAdaptor/Polls.tsx diff --git a/packages/maskbook/src/plugins/Polls/UI/PollsDialog.tsx b/packages/maskbook/src/plugins/Polls/SNSAdaptor/PollsDialog.tsx similarity index 95% rename from packages/maskbook/src/plugins/Polls/UI/PollsDialog.tsx rename to packages/maskbook/src/plugins/Polls/SNSAdaptor/PollsDialog.tsx index 6f9599631f9b..47d2a9c507c3 100644 --- a/packages/maskbook/src/plugins/Polls/UI/PollsDialog.tsx +++ b/packages/maskbook/src/plugins/Polls/SNSAdaptor/PollsDialog.tsx @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react' import { makeStyles, DialogContent, - DialogProps, Typography, IconButton, Button, @@ -27,7 +26,7 @@ import { PollCardUI } from './Polls' import type { PollMetaData } from '../types' import { POLL_META_KEY_1 } from '../constants' import { InjectedDialog } from '../../../components/shared/InjectedDialog' -import { PluginPollRPC } from '../utils' +import { PluginPollRPC } from '../messages' const useNewPollStyles = makeStyles((theme) => ({ line: { @@ -121,7 +120,7 @@ function NewPollUI(props: PollsDialogProps & NewPollProps) { return usePortalShadowRoot((container) => (