From fdce79ad3d167fd079af7c528ff54a87d255d134 Mon Sep 17 00:00:00 2001 From: septs Date: Tue, 17 May 2022 12:25:33 +0800 Subject: [PATCH 1/9] fix: close #6269 (#6270) --- .../src/pages/Personas/components/ContactTableRow/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard/src/pages/Personas/components/ContactTableRow/index.tsx b/packages/dashboard/src/pages/Personas/components/ContactTableRow/index.tsx index a31944b549ee..48ba5fda28c4 100644 --- a/packages/dashboard/src/pages/Personas/components/ContactTableRow/index.tsx +++ b/packages/dashboard/src/pages/Personas/components/ContactTableRow/index.tsx @@ -137,7 +137,7 @@ export const ContactTableRowUI = memo( {/* To support emoji */} {String.fromCodePoint( first.codePointAt(0) ?? SPACE_POINT, - last.codePointAt(0) ?? SPACE_POINT, + last?.codePointAt(0) ?? SPACE_POINT, )} {contact.fingerprint ? : null} From 9b8c8713a38640b8f25e8dd89c3d39aa0713e8a0 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Tue, 17 May 2022 13:37:22 +0800 Subject: [PATCH 2/9] docs(i18n): sync i18n files from Crowdin (#6271) * New translations en-US.json (Quenya) docs(i18n): sync translation en-US.json for Quenya * New translations en-US.json (Quenya) docs(i18n): sync translation en-US.json for Quenya --- packages/dashboard/src/locales/qya-AA.json | 1 + packages/mask/shared-ui/locales/qya-AA.json | 22 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/dashboard/src/locales/qya-AA.json b/packages/dashboard/src/locales/qya-AA.json index bd02ffc4a6ae..dfab6f0d573f 100644 --- a/packages/dashboard/src/locales/qya-AA.json +++ b/packages/dashboard/src/locales/qya-AA.json @@ -187,6 +187,7 @@ "wallets_empty_tokens_tip": "crwdns1789:0crwdne1789:0", "wallets_empty_collectible_tip": "crwdns1791:0crwdne1791:0", "wallets_address_copied": "crwdns1793:0crwdne1793:0", + "public_key_copied": "crwdns16574:0crwdne16574:0", "wallets_address_copy": "crwdns1795:0crwdne1795:0", "wallets_history_types": "crwdns1797:0crwdne1797:0", "wallets_history_value": "crwdns1799:0crwdne1799:0", diff --git a/packages/mask/shared-ui/locales/qya-AA.json b/packages/mask/shared-ui/locales/qya-AA.json index 624be4a5c13d..dd17275ea04a 100644 --- a/packages/mask/shared-ui/locales/qya-AA.json +++ b/packages/mask/shared-ui/locales/qya-AA.json @@ -7,6 +7,8 @@ "debug_metadata_put_metadata": "crwdns10061:0crwdne10061:0", "edit": "crwdns10063:0crwdne10063:0", "clear": "crwdns10065:0crwdne10065:0", + "connect": "crwdns16576:0crwdne16576:0", + "back": "crwdns16578:0crwdne16578:0", "more": "crwdns10067:0crwdne10067:0", "approve": "crwdns10069:0crwdne10069:0", "address": "crwdns10071:0crwdne10071:0", @@ -22,6 +24,8 @@ "tip": "crwdns10105:0crwdne10105:0", "tags": "crwdns10107:0crwdne10107:0", "contract": "crwdns10109:0crwdne10109:0", + "plugins": "crwdns16580:0crwdne16580:0", + "persona_required": "crwdns16582:0crwdne16582:0", "initializing": "crwdns10111:0crwdne10111:0", "redirect_alert": "crwdns10113:0crwdne10113:0", "typed_message_text_alert": "crwdns10117:0crwdne10117:0", @@ -51,6 +55,20 @@ "auto_paste_failed_snackbar": "crwdns4005:0crwdne4005:0", "auto_paste_failed_snackbar_action": "crwdns4007:0crwdne4007:0", "auto_paste_failed_snackbar_action_close": "crwdns9363:0crwdne9363:0", + "compose_encrypt_method_text": "crwdns16584:0crwdne16584:0", + "compose_encrypt_method_text_sub_title": "crwdns16586:0crwdne16586:0", + "compose_encrypt_method_image": "crwdns16588:0crwdne16588:0", + "compose_encrypt_method_image_sub_title": "crwdns16590:0crwdne16590:0", + "compose_no_local_key": "crwdns16592:0crwdne16592:0", + "compose_encrypt_visible_to_all": "crwdns16594:0crwdne16594:0", + "compose_encrypt_visible_to_all_sub": "crwdns16596:0crwdne16596:0", + "compose_encrypt_visible_to_private": "crwdns16598:0crwdne16598:0", + "compose_encrypt_visible_to_private_sub": "crwdns16600:0crwdne16600:0", + "compose_shared_friends": "crwdns16602:0crwdne16602:0", + "compose_shared_friends_other": "crwdns16604:0{{count}}crwdne16604:0", + "compose_encrypt_visible_to_share": "crwdns16606:0crwdne16606:0", + "compose_encrypt_visible_to_share_sub": "crwdns16608:0crwdne16608:0", + "compose_encrypt_share_dialog_empty": "crwdns16610:0crwdne16610:0", "automation_request_click_post_button": "crwdns4009:0crwdne4009:0", "try_again": "crwdns8125:0crwdne8125:0", "ok": "crwdns12997:0crwdne12997:0", @@ -139,7 +157,10 @@ "post_dialog__button": "crwdns4257:0crwdne4257:0", "post_dialog__placeholder": "crwdns4265:0crwdne4265:0", "post_dialog__title": "crwdns4275:0crwdne4275:0", + "post_dialog_visible_to": "crwdns16612:0crwdne16612:0", + "post_dialog_encryption_method": "crwdns16614:0crwdne16614:0", "post_dialog_enable_paste_auto": "crwdns10129:0crwdne10129:0", + "post_dialog_share_with_input_placeholder": "crwdns16616:0crwdne16616:0", "post_modal_hint__button": "crwdns4277:0crwdne4277:0", "hide": "crwdns4293:0crwdne4293:0", "reset": "crwdns4301:0crwdne4301:0", @@ -152,6 +173,7 @@ "select_none": "crwdns4335:0crwdne4335:0", "all_friends": "crwdns4337:0crwdne4337:0", "select_specific_friends_dialog__title": "crwdns4341:0crwdne4341:0", + "select_friends_dialog_persona_connect": "crwdns16618:0crwdne16618:0", "service_decryption_failed": "crwdns4343:0crwdne4343:0", "service_username_invalid": "crwdns4359:0crwdne4359:0", "speed_up": "crwdns9393:0crwdne9393:0", From 2d942c604781c8a6594c592c361a896594380a4b Mon Sep 17 00:00:00 2001 From: septs Date: Tue, 17 May 2022 13:39:31 +0800 Subject: [PATCH 3/9] chore: no-for-in (#6262) * chore: disallow no-for-in * fix: build failed * chore: accpet review * chore: accpet review --- package.json | 2 +- packages/.eslintrc.json | 2 +- .../mask/background/database/persona/web.ts | 6 +- .../Jobs/SettingListeners.ts | 8 +- .../mask/src/extension/mask-sdk/hmr-bridge.ts | 4 +- .../twitter.com/customization/i18n.ts | 8 +- packages/mask/src/social-network/ui.ts | 6 +- packages/mask/src/utils/native-rpc/Web.ts | 14 +-- packages/shared-base/src/i18n/register-ns.ts | 8 +- .../src/utils/getLocalImplementation.tsx | 4 +- packages/theme/src/CSSVariables/applyToDOM.ts | 6 +- packages/theme/src/CSSVariables/createVars.ts | 2 +- .../theme/src/UIHelper/custom-ui-helper.tsx | 2 +- packages/theme/stories/utils/Material-UI.ts | 4 +- .../base/binary-encode/decode.ts | 14 ++- .../base/binary-encode/encode.ts | 3 +- pnpm-lock.yaml | 110 +++++++++++++++--- 17 files changed, 142 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index 2c521581f49c..f3673747e6e7 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "devDependencies": { "@commitlint/cli": "^16.2.4", "@commitlint/config-conventional": "^16.2.4", - "@dimensiondev/eslint-plugin": "^0.0.2-20220414093950-7d54c58", + "@dimensiondev/eslint-plugin": "0.0.2-20220516081411-2649814", "@dimensiondev/patch-package": "^6.5.0", "@jest/globals": "^28.1.0", "@magic-works/i18n-codegen": "^0.1.0", diff --git a/packages/.eslintrc.json b/packages/.eslintrc.json index 329c14763de5..2b91bf5350be 100644 --- a/packages/.eslintrc.json +++ b/packages/.eslintrc.json @@ -70,6 +70,7 @@ "@dimensiondev/browser/prefer-location-assign": "error", "@dimensiondev/jsx/no-class-component": "error", "@dimensiondev/jsx/no-template-literal": "error", + "@dimensiondev/no-for-in": "error", "@dimensiondev/no-number-constructor": "off", "@dimensiondev/prefer-early-return": "error", "@dimensiondev/string/no-interpolation": "off", @@ -81,7 +82,6 @@ "@dimensiondev/unicode/specific-set": "error", "@typescript-eslint/await-thenable": "error", "@typescript-eslint/no-base-to-string": "off", - "@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-implied-eval": "error", "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-invalid-this": "error", diff --git a/packages/mask/background/database/persona/web.ts b/packages/mask/background/database/persona/web.ts index 32446804934f..43da926be902 100644 --- a/packages/mask/background/database/persona/web.ts +++ b/packages/mask/background/database/persona/web.ts @@ -299,10 +299,10 @@ export async function updatePersonaDB( else nextLinkedProfiles = nextRecord.linkedProfiles } if (howToMerge.explicitUndefinedField === 'ignore') { - for (const _key in nextRecord) { - const key = _key as keyof typeof nextRecord + const keys = Object.keys(nextRecord) as Array + for (const key of keys) { if (nextRecord[key] === undefined) { - delete nextRecord[key as keyof typeof nextRecord] + delete nextRecord[key] } } } diff --git a/packages/mask/src/extension/background-script/Jobs/SettingListeners.ts b/packages/mask/src/extension/background-script/Jobs/SettingListeners.ts index b9c7573c7720..56860c55572a 100644 --- a/packages/mask/src/extension/background-script/Jobs/SettingListeners.ts +++ b/packages/mask/src/extension/background-script/Jobs/SettingListeners.ts @@ -5,12 +5,12 @@ import { MaskMessages } from '../../../utils' export default function (signal: AbortSignal) { if (!isEnvironment(Environment.ManifestBackground)) return - const obj = ToBeListened() - for (const _key in obj) { - const key = _key as keyof MaskSettingsEvents + const listeners = ToBeListened() + const keys = Object.keys(listeners) as Array + for (const key of keys) { signal.addEventListener( 'abort', - obj[key].addListener((data: any) => MaskMessages.events[key].sendToAll(data as never)), + listeners[key].addListener((data) => MaskMessages.events[key].sendToAll(data as never)), ) } } diff --git a/packages/mask/src/extension/mask-sdk/hmr-bridge.ts b/packages/mask/src/extension/mask-sdk/hmr-bridge.ts index cf4907f75154..9d5545e99dc3 100644 --- a/packages/mask/src/extension/mask-sdk/hmr-bridge.ts +++ b/packages/mask/src/extension/mask-sdk/hmr-bridge.ts @@ -4,10 +4,10 @@ export const hmr_sdkServer = { ...maskSDKServer } if (import.meta.webpackHot) { import.meta.webpackHot.accept('./bridge', () => { - for (const key in hmr_sdkServer) { + for (const key of Object.keys(hmr_sdkServer)) { if (!(key in maskSDKServer)) Reflect.deleteProperty(hmr_sdkServer, key) } - for (const key in maskSDKServer) { + for (const key of Object.keys(maskSDKServer)) { // @ts-expect-error hmr_sdkServer[key] = maskSDKServer[key] } diff --git a/packages/mask/src/social-network-adaptor/twitter.com/customization/i18n.ts b/packages/mask/src/social-network-adaptor/twitter.com/customization/i18n.ts index ae63b2ae5708..60eced5cfe66 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/customization/i18n.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/customization/i18n.ts @@ -4,10 +4,10 @@ import { languages } from '../locales/languages' export const i18NOverwriteTwitter: SocialNetworkUI.Customization.I18NOverwrite = { mask: {}, } -const resource: any = languages -for (const lng in resource) { - for (const key in resource[lng]) { +const resource = languages +for (const language of Object.keys(resource) as Array) { + for (const key of Object.keys(resource[language]) as Array) { i18NOverwriteTwitter.mask[key] ??= {} - i18NOverwriteTwitter.mask[key][lng] = resource[lng][key] + i18NOverwriteTwitter.mask[key][language] = resource[language][key] } } diff --git a/packages/mask/src/social-network/ui.ts b/packages/mask/src/social-network/ui.ts index 8a20ee5c16d0..83763e94d3ad 100644 --- a/packages/mask/src/social-network/ui.ts +++ b/packages/mask/src/social-network/ui.ts @@ -153,11 +153,11 @@ export async function activateSocialNetworkUIInner(ui_deferred: SocialNetworkUI. function i18nOverwrite() { const i18n = ui.customization.i18nOverwrite || {} - for (const namespace in i18n) { + for (const namespace of Object.keys(i18n)) { const ns = i18n[namespace] - for (const i18nKey in ns) { + for (const i18nKey of Object.keys(ns)) { const pair = i18n[namespace][i18nKey] - for (const language in pair) { + for (const language of Object.keys(pair)) { const value = pair[language] i18NextInstance.addResource(language, namespace, i18nKey, value) } diff --git a/packages/mask/src/utils/native-rpc/Web.ts b/packages/mask/src/utils/native-rpc/Web.ts index 62de2b778e79..4e4fd3bcfbde 100644 --- a/packages/mask/src/utils/native-rpc/Web.ts +++ b/packages/mask/src/utils/native-rpc/Web.ts @@ -232,14 +232,14 @@ function wrapWithAssert(env: Environment, f: Function) { } try { - for (const _key in MaskNetworkAPI) { - const key = _key as keyof MaskNetworkAPIs - const f: Function = MaskNetworkAPI[key] - + for (const key of Object.keys(MaskNetworkAPI) as Array) { + const fn: Function = MaskNetworkAPI[key] if (key.startsWith('SNSAdaptor_')) { - MaskNetworkAPI[key] = wrapWithAssert(Environment.ContentScript, f) + MaskNetworkAPI[key] = wrapWithAssert(Environment.ContentScript, fn) } else { - MaskNetworkAPI[key] = wrapWithAssert(Environment.ManifestBackground, f) + MaskNetworkAPI[key] = wrapWithAssert(Environment.ManifestBackground, fn) } } -} catch {} +} catch { + // ignore +} diff --git a/packages/shared-base/src/i18n/register-ns.ts b/packages/shared-base/src/i18n/register-ns.ts index ae7239c88012..bc9a744f17be 100644 --- a/packages/shared-base/src/i18n/register-ns.ts +++ b/packages/shared-base/src/i18n/register-ns.ts @@ -9,13 +9,15 @@ function addI18NBundle(instance: i18n, namespace: string, langs: Record( RPCCache.set(ref, localImpl) const result: any = await impl() - for (const key in localImpl) { + for (const key of Object.keys(localImpl) as Array) { if (!Reflect.has(result, key)) { delete localImpl[key] isUpdate && console.log(`[HMR] ${name}.${key} removed.`) @@ -30,7 +30,7 @@ export async function getLocalImplementation( isUpdate && console.log(`[HMR] ${name}.${key} updated.`) } } - for (const key in result) { + for (const key of Object.keys(result)) { if (!Reflect.has(localImpl, key)) isUpdate && console.log(`[HMR] ${name}.${key} added.`) Object.defineProperty(localImpl, key, { configurable: true, enumerable: true, value: result[key] }) } diff --git a/packages/theme/src/CSSVariables/applyToDOM.ts b/packages/theme/src/CSSVariables/applyToDOM.ts index b1887eeab3ea..62b463e74ac2 100644 --- a/packages/theme/src/CSSVariables/applyToDOM.ts +++ b/packages/theme/src/CSSVariables/applyToDOM.ts @@ -12,7 +12,7 @@ function getRGBFragment(x: Record, key: string) { export function CSSVariableInjectorCSS(scheme: PaletteMode) { const ns: Record = scheme === 'light' ? LightColor : DarkColor const result: Record = {} - for (const key in ns) { + for (const key of Object.keys(ns)) { // --mask-name: val; result[`--mask-${kebabCase(key)}`] = ns[key] result[`--mask-${kebabCase(key)}-fragment`] = getRGBFragment(ns, key) @@ -33,14 +33,14 @@ export function applyMaskColorVars(node: HTMLElement, scheme: PaletteMode) { return } else if (node instanceof HTMLStyleElement) { let rule = ':root, :host {\n' - for (const key in ns) { + for (const key of Object.keys(ns)) { // --mask-name: val; rule += ` --mask-${kebabCase(key)}: ${ns[key]};\n` rule += ` --mask-${kebabCase(key)}-fragment: ${getRGBFragment(ns, key)};\n` } node.textContent = rule + '}' } else { - for (const key in ns) { + for (const key of Object.keys(ns)) { node.style.setProperty('--mask-' + kebabCase(key), ns[key]) node.style.setProperty('--mask-' + kebabCase(key) + '-fragment', getRGBFragment(ns, key)) } diff --git a/packages/theme/src/CSSVariables/createVars.ts b/packages/theme/src/CSSVariables/createVars.ts index 00f17e4be0aa..503b9d311ba7 100644 --- a/packages/theme/src/CSSVariables/createVars.ts +++ b/packages/theme/src/CSSVariables/createVars.ts @@ -3,7 +3,7 @@ export function css_var>( unique_name: string, keys: T, ): { [key in keyof T]: string & ((defaultValue?: string) => string) } { - for (const k in keys) keys[k] = createVar(k) as any + for (const k of Object.keys(keys) as Array) keys[k] = createVar(k as string) as any return keys as any function createVar(name: string) { const val = '--' + unique_name + '-' + name diff --git a/packages/theme/src/UIHelper/custom-ui-helper.tsx b/packages/theme/src/UIHelper/custom-ui-helper.tsx index a7b6b10555e7..db8ed7aba8cd 100644 --- a/packages/theme/src/UIHelper/custom-ui-helper.tsx +++ b/packages/theme/src/UIHelper/custom-ui-helper.tsx @@ -17,7 +17,7 @@ export function mergeClasses(...args: (Partial> | undefined const result = {} as Partial> for (const current of args) { if (!current) continue - for (const key in current) { + for (const key of Object.keys(current)) { if (key === '__proto__') continue if (key in result) result[key] = result[key] + ' ' + current[key] else result[key] = current[key] diff --git a/packages/theme/stories/utils/Material-UI.ts b/packages/theme/stories/utils/Material-UI.ts index 5d888daff774..94ef7291de68 100644 --- a/packages/theme/stories/utils/Material-UI.ts +++ b/packages/theme/stories/utils/Material-UI.ts @@ -4,7 +4,9 @@ import { argsOfArr, ControlType } from './args' function enumIn(enums: { [Prop in keyof T]?: (argsFromEnum: (enumString: NonNullable[], type?: ControlType) => ArgType) => ArgType }): ArgTypes { - for (const key in enums) enums[key] = (enums[key] as any)(argsOfArr) + for (const key of Object.keys(enums) as Array) { + enums[key] = (enums[key] as any)(argsOfArr) + } return enums as ArgTypes } export const MuiArgs = { diff --git a/packages/typed-message/base/binary-encode/decode.ts b/packages/typed-message/base/binary-encode/decode.ts index 6e342faa4613..e11b4032a41c 100644 --- a/packages/typed-message/base/binary-encode/decode.ts +++ b/packages/typed-message/base/binary-encode/decode.ts @@ -49,13 +49,15 @@ function assertString(x: unknown): asserts x is string { if (typeof x !== 'string') throw new TypeError(`${HEAD}Invalid TypedMessage`) } // Detach Uint8Array from it's underlying buffer -function fixU8Array(obj: unknown) { +function fixU8Array(input: unknown) { // for Array and object - if (typeof obj === 'object' && obj !== null) { - for (const key in obj) { - const val = (obj as any)[key] - if (val instanceof Uint8Array) (obj as any)[key] = val.slice() - else fixU8Array(val) + if (typeof input !== 'object' || input === undefined || input === null) return + for (const key of Object.keys(input)) { + const value = Reflect.get(input, key) + if (value instanceof Uint8Array) { + Reflect.set(input, key, value.slice()) + } else { + fixU8Array(value) } } } diff --git a/packages/typed-message/base/binary-encode/encode.ts b/packages/typed-message/base/binary-encode/encode.ts index c4ea1beb6530..58e694bea244 100644 --- a/packages/typed-message/base/binary-encode/encode.ts +++ b/packages/typed-message/base/binary-encode/encode.ts @@ -71,8 +71,7 @@ function collectValue(val: any): any { } const result: Record = {} - for (const key in val) { - if (typeof key !== 'string') throw new TypeError(`${HEAD}Unsupported type symbol.`) + for (const key of Object.keys(val)) { const v = val[key] result[key] = collectValue(v) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa9db6a7ad7b..3a34fa9ce938 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: specifiers: '@commitlint/cli': ^16.2.4 '@commitlint/config-conventional': ^16.2.4 - '@dimensiondev/eslint-plugin': ^0.0.2-20220414093950-7d54c58 + '@dimensiondev/eslint-plugin': 0.0.2-20220516081411-2649814 '@dimensiondev/kit': 0.0.0-20220228054820-f2378be '@dimensiondev/patch-package': ^6.5.0 '@emotion/cache': ^11.7.1 @@ -98,7 +98,7 @@ importers: devDependencies: '@commitlint/cli': 16.2.4_@swc+core@1.2.177 '@commitlint/config-conventional': 16.2.4 - '@dimensiondev/eslint-plugin': 0.0.2-20220414093950-7d54c58_eslint@8.15.0 + '@dimensiondev/eslint-plugin': 0.0.2-20220516081411-2649814_eslint@8.15.0 '@dimensiondev/patch-package': 6.5.0 '@jest/globals': 28.1.0 '@magic-works/i18n-codegen': 0.1.0_typescript@4.7.0-beta @@ -112,7 +112,7 @@ importers: '@typescript-eslint/parser': 5.22.0_dx5yzralznart3ybdl432c3i44 cspell: 5.20.0 eslint: 8.15.0 - eslint-plugin-import: 2.26.0_eslint@8.15.0 + eslint-plugin-import: 2.26.0_6nacgdzqm4zbhelsxkmd2vkvxy eslint-plugin-react: 7.29.4_eslint@8.15.0 eslint-plugin-react-hooks: 4.5.0_eslint@8.15.0 eslint-plugin-unicorn: 42.0.0_eslint@8.15.0 @@ -2209,17 +2209,23 @@ packages: resolution: {integrity: sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==} engines: {node: '>=6.0.0'} hasBin: true + dependencies: + '@babel/types': 7.17.10 dev: true /@babel/parser/7.17.3: resolution: {integrity: sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==} engines: {node: '>=6.0.0'} hasBin: true + dependencies: + '@babel/types': 7.17.10 /@babel/parser/7.17.9: resolution: {integrity: sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==} engines: {node: '>=6.0.0'} hasBin: true + dependencies: + '@babel/types': 7.17.10 dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.17.10: @@ -5681,9 +5687,8 @@ packages: '@msgpack/msgpack': 1.12.2 dev: false - /@dimensiondev/eslint-plugin/0.0.2-20220414093950-7d54c58_eslint@8.15.0: - resolution: {integrity: sha512-H6ZmwT+mhplwYU0j8bvNmBNp0y5pT6fMfb3OjWiWkhF5W7LKxUy9YZLc6XfsCHC56hPTPq5u/pCjRBtE4Y1qxQ==, tarball: download/@dimensiondev/eslint-plugin/0.0.2-20220414093950-7d54c58/515fb9cbdd7dba3b6da5e0686027b2ec170872dc10618b545a9035dea7a12633} - engines: {node: '>= 16'} + /@dimensiondev/eslint-plugin/0.0.2-20220516081411-2649814_eslint@8.15.0: + resolution: {integrity: sha512-cEEKTD1ku7ScTuifqrZHAXpc8a1hwew12MLee/jvFEdOkoQSDxYiqAh7V35wQLGappUUyqJiLc6vgk6qlpzQeA==, tarball: download/@dimensiondev/eslint-plugin/0.0.2-20220516081411-2649814/f8750f35c321553cee686b564cea6d4c5dffe62eaab4af3ab64a6392d8e4743b} peerDependencies: eslint: '>= 8' dependencies: @@ -12093,6 +12098,8 @@ packages: dependencies: micromatch: 3.1.10 normalize-path: 2.1.1 + transitivePeerDependencies: + - supports-color /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} @@ -13775,6 +13782,8 @@ packages: snapdragon-node: 2.1.1 split-string: 3.1.0 to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color /braces/3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} @@ -14271,6 +14280,8 @@ packages: upath: 1.2.0 optionalDependencies: fsevents: 1.2.13 + transitivePeerDependencies: + - supports-color /chokidar/3.5.2: resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} @@ -15634,6 +15645,11 @@ packages: /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.0.0 @@ -15645,6 +15661,11 @@ packages: /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.1.3 @@ -16764,29 +16785,54 @@ packages: dependencies: debug: 3.2.7 resolve: 1.22.0 + transitivePeerDependencies: + - supports-color dev: true - /eslint-module-utils/2.7.3: + /eslint-module-utils/2.7.3_wex3ustmkv4ospy3s77r6ihlwq: resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true dependencies: + '@typescript-eslint/parser': 5.22.0_dx5yzralznart3ybdl432c3i44 debug: 3.2.7 + eslint-import-resolver-node: 0.3.6 find-up: 2.1.0 + transitivePeerDependencies: + - supports-color dev: true - /eslint-plugin-import/2.26.0_eslint@8.15.0: + /eslint-plugin-import/2.26.0_6nacgdzqm4zbhelsxkmd2vkvxy: resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} engines: {node: '>=4'} peerDependencies: + '@typescript-eslint/parser': '*' eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true dependencies: + '@typescript-eslint/parser': 5.22.0_dx5yzralznart3ybdl432c3i44 array-includes: 3.1.4 array.prototype.flat: 1.2.5 debug: 2.6.9 doctrine: 2.1.0 eslint: 8.15.0 eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.3 + eslint-module-utils: 2.7.3_wex3ustmkv4ospy3s77r6ihlwq has: 1.0.3 is-core-module: 2.8.1 is-glob: 4.0.3 @@ -16794,6 +16840,10 @@ packages: object.values: 1.1.5 resolve: 1.22.0 tsconfig-paths: 3.14.1 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color dev: true /eslint-plugin-react-hooks/4.5.0_eslint@8.15.0: @@ -17505,6 +17555,8 @@ packages: regex-not: 1.0.2 snapdragon: 0.8.2 to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color /expand-tilde/2.0.2: resolution: {integrity: sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=} @@ -17606,6 +17658,8 @@ packages: regex-not: 1.0.2 snapdragon: 0.8.2 to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color /extract-files/9.0.0: resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==} @@ -17921,6 +17975,8 @@ packages: is-glob: 3.1.0 micromatch: 3.1.10 resolve-dir: 1.0.1 + transitivePeerDependencies: + - supports-color dev: true /findup-sync/3.0.0: @@ -17931,6 +17987,8 @@ packages: is-glob: 4.0.3 micromatch: 3.1.10 resolve-dir: 1.0.1 + transitivePeerDependencies: + - supports-color dev: true /fined/1.2.0: @@ -18496,6 +18554,8 @@ packages: just-debounce: 1.1.0 normalize-path: 3.0.0 object.defaults: 1.1.0 + transitivePeerDependencies: + - supports-color dev: true /glob/7.1.6: @@ -18750,6 +18810,8 @@ packages: semver-greatest-satisfied-range: 1.1.0 v8flags: 3.2.0 yargs: 7.1.2 + transitivePeerDependencies: + - supports-color dev: true /gulp-zip/5.1.0: @@ -18777,6 +18839,8 @@ packages: gulp-cli: 2.3.0 undertaker: 1.3.0 vinyl-fs: 3.0.3 + transitivePeerDependencies: + - supports-color dev: true /gulplog/1.0.0: @@ -21514,6 +21578,8 @@ packages: object.map: 1.0.1 rechoir: 0.6.2 resolve: 1.22.0 + transitivePeerDependencies: + - supports-color dev: true /lilconfig/2.0.4: @@ -21909,6 +21975,8 @@ packages: micromatch: 3.1.10 resolve: 1.22.0 stack-trace: 0.0.10 + transitivePeerDependencies: + - supports-color dev: true /md5.js/1.3.5: @@ -22115,6 +22183,8 @@ packages: regex-not: 1.0.2 snapdragon: 0.8.2 to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color /micromatch/4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} @@ -22583,6 +22653,8 @@ packages: regex-not: 1.0.2 snapdragon: 0.8.2 to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color /native-abort-controller/1.0.4_abort-controller@3.0.0: resolution: {integrity: sha512-zp8yev7nxczDJMoP6pDxyD20IU0T22eX8VwN2ztDccKvSZhRaV33yP1BGwKSZfXuqWUzsXopVFjBdau9OOAwMQ==} @@ -24840,6 +24912,8 @@ packages: graceful-fs: 4.2.10 micromatch: 3.1.10 readable-stream: 2.3.7 + transitivePeerDependencies: + - supports-color /readdirp/3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -26004,6 +26078,8 @@ packages: source-map: 0.5.7 source-map-resolve: 0.5.3 use: 3.1.1 + transitivePeerDependencies: + - supports-color /socket.io-client/2.4.0: resolution: {integrity: sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==} @@ -28183,14 +28259,6 @@ packages: optional: true dev: false - /use-subscription/1.6.0_react@packages+empty: - resolution: {integrity: sha512-0Y/cTLlZfw547tJhJMoRA16OUbVqRm6DmvGpiGbmLST6BIA5KU5cKlvlz8DVMrACnWpyEjCkgmhLatthP4jUbA==} - peerDependencies: - react: ^18.0.0 - dependencies: - react: link:packages/empty - dev: false - /use/3.1.1: resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} engines: {node: '>=0.10.0'} @@ -28560,6 +28628,8 @@ packages: web3-providers-http: 1.7.3 web3-providers-ipc: 1.7.3 web3-providers-ws: 1.7.3 + transitivePeerDependencies: + - supports-color /web3-core-subscriptions/1.7.3: resolution: {integrity: sha512-/i1ZCLW3SDxEs5mu7HW8KL4Vq7x4/fDXY+yf/vPoDljlpvcLEOnI8y9r7om+0kYwvuTlM6DUHHafvW0221TyRQ==} @@ -28579,6 +28649,8 @@ packages: web3-core-method: 1.7.3 web3-core-requestmanager: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color /web3-eth-abi/1.7.3: resolution: {integrity: sha512-ZlD8DrJro0ocnbZViZpAoMX44x5aYAb73u2tMq557rMmpiluZNnhcCYF/NnVMy6UIkn7SF/qEA45GXA1ne6Tnw==} @@ -28722,6 +28794,8 @@ packages: eventemitter3: 4.0.4 web3-core-helpers: 1.7.3 websocket: 1.0.34 + transitivePeerDependencies: + - supports-color /web3-shh/1.7.3: resolution: {integrity: sha512-bQTSKkyG7GkuULdZInJ0osHjnmkHij9tAySibpev1XjYdjLiQnd0J9YGF4HjvxoG3glNROpuCyTaRLrsLwaZuw==} @@ -29266,6 +29340,8 @@ packages: typedarray-to-buffer: 3.1.5 utf-8-validate: 5.0.9 yaeti: 0.0.6 + transitivePeerDependencies: + - supports-color /whatwg-encoding/2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} From f5c2684dfe13353afc020e1c1718004da14b494e Mon Sep 17 00:00:00 2001 From: septs Date: Tue, 17 May 2022 13:52:08 +0800 Subject: [PATCH 4/9] chore: no-array-reduce (#6268) --- packages/.eslintrc.json | 1 + .../backup-format/src/utils/backupPreview.ts | 3 +- .../backup-format/src/utils/hex2buffer.ts | 4 +- packages/gun-utils/src/utils.ts | 1 + .../services/identity/profile/update.ts | 6 +- packages/mask/src/UIRoot.tsx | 1 + .../components/shared/ApplicationBoard.tsx | 44 +++---- .../shared/ApplicationSettingPluginList.tsx | 34 ++---- .../shared/ApplicationSettingPluginSwitch.tsx | 16 +-- .../FindTruman/SNSAdaptor/OptionsCard.tsx | 7 +- .../FindTruman/SNSAdaptor/ResultCard.tsx | 8 +- .../plugins/ITO/SNSAdaptor/NftAirdropCard.tsx | 7 +- .../mask/src/plugins/ITO/Worker/apis/chain.ts | 115 +++++++++--------- .../src/plugins/Polls/SNSAdaptor/Polls.tsx | 5 +- .../src/plugins/PoolTogether/UI/Account.tsx | 19 ++- .../plugins/PoolTogether/UI/DepositDialog.tsx | 2 +- .../hooks/useAvailabilityNftRedPacket.ts | 5 +- .../plugins/RedPacket/Worker/apis/chain.ts | 85 +++++++------ .../Savings/SNSAdaptor/SavingsDialog.tsx | 18 +-- .../Snapshot/SNSAdaptor/ResultCard.tsx | 14 ++- .../plugins/Snapshot/SNSAdaptor/VotesCard.tsx | 15 ++- .../Snapshot/SNSAdaptor/hooks/usePower.ts | 21 ++-- .../Snapshot/SNSAdaptor/hooks/useResults.ts | 21 ++-- .../Snapshot/SNSAdaptor/hooks/useVotes.ts | 7 +- .../plugins/Tips/hooks/useTipsWalletsList.ts | 7 +- .../src/plugins/Trader/apis/balancer/index.ts | 3 +- .../src/plugins/Trader/apis/trending/index.ts | 14 ++- .../src/plugins/Trader/apis/uniswap/index.ts | 10 +- .../trader/uniswap/useAllCommonPairs.ts | 29 ++--- .../trader/uniswap/useTradeBreakdown.ts | 2 + .../Trader/trader/uniswap/useV3BestTrade.ts | 2 + .../Trader/trader/uniswap/useV3SwapPools.ts | 12 +- packages/mask/src/utils/getTextUILength.ts | 5 +- .../src/hooks/useAllPluginsWeb3State.ts | 15 +-- .../plugin-infra/src/manager/sns-adaptor.ts | 15 +-- packages/shared-base/src/color/avatar.ts | 1 + packages/theme/src/Theme/Provider.tsx | 1 + .../typed-message/base/transformer/Flatten.ts | 1 + .../base/transformer/composed.ts | 1 + packages/web3-providers/src/debank/format.ts | 58 ++++----- packages/web3-shared/evm/utils/token.ts | 26 ++-- 41 files changed, 302 insertions(+), 359 deletions(-) diff --git a/packages/.eslintrc.json b/packages/.eslintrc.json index 2b91bf5350be..df53e8dd126b 100644 --- a/packages/.eslintrc.json +++ b/packages/.eslintrc.json @@ -59,6 +59,7 @@ "unicorn/no-new-buffer": "error", "unicorn/no-thenable": "error", "unicorn/no-useless-promise-resolve-reject": "error", + "unicorn/no-array-reduce": ["error", { "allowSimpleOperations": false }], "unicorn/prefer-add-event-listener": "error", "unicorn/prefer-date-now": "error", "unicorn/prefer-dom-node-dataset": "error", diff --git a/packages/backup-format/src/utils/backupPreview.ts b/packages/backup-format/src/utils/backupPreview.ts index eb1be97c3095..baeb83c4c208 100644 --- a/packages/backup-format/src/utils/backupPreview.ts +++ b/packages/backup-format/src/utils/backupPreview.ts @@ -1,4 +1,5 @@ import type { NormalizedBackup } from '@masknet/backup-format' +import { sumBy } from 'lodash-unified' export interface BackupPreview { personas: number @@ -20,7 +21,7 @@ export function getBackupPreviewInfo(json: NormalizedBackup.Data): BackupPreview return { personas: json.personas.size, - accounts: [...json.personas.values()].reduce((a, b) => a + b.linkedProfiles.size, 0), + accounts: sumBy([...json.personas.values()], (persona) => persona.linkedProfiles.size), posts: json.posts.size, contacts: json.profiles.size, relations: json.relations.length, diff --git a/packages/backup-format/src/utils/hex2buffer.ts b/packages/backup-format/src/utils/hex2buffer.ts index 7204339f8dd7..4b8f76f2e0c2 100644 --- a/packages/backup-format/src/utils/hex2buffer.ts +++ b/packages/backup-format/src/utils/hex2buffer.ts @@ -1,3 +1,5 @@ +import { sum } from 'lodash-unified' + /** @internal */ export function hex2buffer(hexString: string, padded?: boolean) { if (hexString.length % 2) { @@ -21,7 +23,7 @@ export function hex2buffer(hexString: string, padded?: boolean) { /** @internal */ function concat(...buf: (Uint8Array | number[])[]) { - const res = new Uint8Array(buf.map((item) => item.length).reduce((prev, cur) => prev + cur)) + const res = new Uint8Array(sum(buf.map((item) => item.length))) let offset = 0 buf.forEach((item) => { for (let i = 0; i < item.length; i += 1) { diff --git a/packages/gun-utils/src/utils.ts b/packages/gun-utils/src/utils.ts index ca0357ddc92d..4ca9392d60c8 100644 --- a/packages/gun-utils/src/utils.ts +++ b/packages/gun-utils/src/utils.ts @@ -2,6 +2,7 @@ import { EventIterator } from 'event-iterator' import { getGunInstance, OnCloseEvent } from './instance' function getGunNodeFromPath(path: string[]) { + // eslint-disable-next-line unicorn/no-array-reduce const resultNode = path.reduce((gun, path) => gun.get(path as never), getGunInstance()) return resultNode } diff --git a/packages/mask/background/services/identity/profile/update.ts b/packages/mask/background/services/identity/profile/update.ts index c82f7a8f5792..2a6189457780 100644 --- a/packages/mask/background/services/identity/profile/update.ts +++ b/packages/mask/background/services/identity/profile/update.ts @@ -58,10 +58,10 @@ export async function resolveUnknownLegacyIdentity(identifier: ProfileIdentifier const unknown = ProfileIdentifier.of(identifier.network, '$unknown').unwrap() const self = ProfileIdentifier.of(identifier.network, '$self').unwrap() - const r = await queryProfilesDB({ identifiers: [unknown, self] }) - if (!r.length) return + const records = await queryProfilesDB({ identifiers: [unknown, self] }) + if (!records.length) return const final = { - ...r.reduce((p, c) => ({ ...p, ...c })), + ...Object.assign({}, ...records), identifier, } try { diff --git a/packages/mask/src/UIRoot.tsx b/packages/mask/src/UIRoot.tsx index 7e0dabf1b201..9cae87e10383 100644 --- a/packages/mask/src/UIRoot.tsx +++ b/packages/mask/src/UIRoot.tsx @@ -17,6 +17,7 @@ import { MaskThemeProvider } from '@masknet/theme' const identity = (jsx: React.ReactNode) => jsx as JSX.Element function compose(init: React.ReactNode, ...f: ((children: React.ReactNode) => JSX.Element)[]) { + // eslint-disable-next-line unicorn/no-array-reduce return f.reduceRight((prev, curr) => curr(prev), <>{init}) } diff --git a/packages/mask/src/components/shared/ApplicationBoard.tsx b/packages/mask/src/components/shared/ApplicationBoard.tsx index ad043a459618..9f8b3016c9ae 100644 --- a/packages/mask/src/components/shared/ApplicationBoard.tsx +++ b/packages/mask/src/components/shared/ApplicationBoard.tsx @@ -4,7 +4,7 @@ import { Typography } from '@mui/material' import { useChainId } from '@masknet/web3-shared-evm' import { useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra/content-script' import { useCurrentWeb3NetworkPluginID, useAccount, NetworkPluginID } from '@masknet/plugin-infra/web3' -import { EMPTY_LIST, CrossIsolationMessages, formatPersonaPublicKey } from '@masknet/shared-base' +import { CrossIsolationMessages, formatPersonaPublicKey } from '@masknet/shared-base' import { getCurrentSNSNetwork } from '../../social-network-adaptor/utils' import { activatedSocialNetworkUI } from '../../social-network' import { useI18N } from '../../utils' @@ -122,33 +122,25 @@ function ApplicationBoardContent(props: Props) { const applicationList = useMemo( () => snsAdaptorPlugins - .reduce((acc, cur) => { - if (!cur.ApplicationEntries) return acc - const currentWeb3NetworkSupportedChainIds = cur.enableRequirement.web3?.[currentWeb3Network] + .flatMap(({ ID, ApplicationEntries, enableRequirement }) => { + if (!ApplicationEntries) return [] + const currentWeb3NetworkSupportedChainIds = enableRequirement.web3?.[currentWeb3Network] const isWalletConnectedRequired = currentWeb3NetworkSupportedChainIds !== undefined - const currentSNSIsSupportedNetwork = cur.enableRequirement.networks.networks[currentSNSNetwork] + const currentSNSIsSupportedNetwork = enableRequirement.networks.networks[currentSNSNetwork] const isSNSEnabled = currentSNSIsSupportedNetwork === undefined || currentSNSIsSupportedNetwork - - return acc.concat( - cur.ApplicationEntries.map((x) => { - return { - entry: x, - enabled: isSNSEnabled, - pluginId: cur.ID, - isWalletConnectedRequired: !account && isWalletConnectedRequired, - isWalletConnectedEVMRequired: Boolean( - account && - currentWeb3Network !== NetworkPluginID.PLUGIN_EVM && - isWalletConnectedRequired, - ), - } - }) ?? EMPTY_LIST, - ) - }, EMPTY_LIST) - .sort( - (a, b) => - (a.entry.appBoardSortingDefaultPriority ?? 0) - (b.entry.appBoardSortingDefaultPriority ?? 0), - ) + return ApplicationEntries.map((entry) => ({ + entry, + enabled: isSNSEnabled, + pluginId: ID, + isWalletConnectedRequired: !account && isWalletConnectedRequired, + isWalletConnectedEVMRequired: Boolean( + account && currentWeb3Network !== NetworkPluginID.PLUGIN_EVM && isWalletConnectedRequired, + ), + })) + }) + .sort((a, b) => { + return (a.entry.appBoardSortingDefaultPriority ?? 0) - (b.entry.appBoardSortingDefaultPriority ?? 0) + }) .filter((x) => Boolean(x.entry.RenderEntryComponent)), [snsAdaptorPlugins, currentWeb3Network, chainId, account], ) diff --git a/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx b/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx index 60cce9311e2c..5e5d47c7e912 100644 --- a/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx +++ b/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx @@ -2,7 +2,6 @@ import { useActivatedPluginsSNSAdaptor, Plugin } from '@masknet/plugin-infra/con import { useMemo, useState, useCallback } from 'react' import { List, ListItem, Typography } from '@mui/material' import { makeStyles, getMaskColor } from '@masknet/theme' -import { EMPTY_LIST } from '@masknet/shared-base' import { useI18N } from '../../utils' import { PersistentStorages } from '../../../shared' @@ -81,28 +80,17 @@ export function ApplicationSettingPluginList() { const { classes } = useStyles() const { t } = useI18N() const snsAdaptorPlugins = useActivatedPluginsSNSAdaptor('any') - const applicationList = useMemo( - () => - snsAdaptorPlugins - .reduce((acc, cur) => { - if (!cur.ApplicationEntries) return acc - return acc.concat( - cur.ApplicationEntries.filter( - (x) => x.appBoardSortingDefaultPriority && !x.recommendFeature, - ).map((x) => { - return { - entry: x, - pluginId: cur.ID, - } - }) ?? EMPTY_LIST, - ) - }, EMPTY_LIST) - .sort( - (a, b) => - (a.entry.appBoardSortingDefaultPriority ?? 0) - (b.entry.appBoardSortingDefaultPriority ?? 0), - ), - [snsAdaptorPlugins], - ) + const applicationList = useMemo(() => { + return snsAdaptorPlugins + .flatMap(({ ID, ApplicationEntries: entries }) => + (entries ?? []) + .filter((entry) => entry.appBoardSortingDefaultPriority && !entry.recommendFeature) + .map((entry) => ({ entry, pluginId: ID })), + ) + .sort((a, b) => { + return (a.entry.appBoardSortingDefaultPriority ?? 0) - (b.entry.appBoardSortingDefaultPriority ?? 0) + }) + }, [snsAdaptorPlugins]) const [listedAppList, setListedAppList] = useState(applicationList.filter((x) => !getUnlistedApp(x))) const [unlistedAppList, setUnListedAppList] = useState(applicationList.filter((x) => getUnlistedApp(x))) diff --git a/packages/mask/src/components/shared/ApplicationSettingPluginSwitch.tsx b/packages/mask/src/components/shared/ApplicationSettingPluginSwitch.tsx index e11d80d28614..b8f5de60eed8 100644 --- a/packages/mask/src/components/shared/ApplicationSettingPluginSwitch.tsx +++ b/packages/mask/src/components/shared/ApplicationSettingPluginSwitch.tsx @@ -1,7 +1,7 @@ import { List, ListItem, ListItemAvatar, Avatar, Typography, Box } from '@mui/material' import { openWindow } from '@masknet/shared-base-ui' import { TutorialIcon } from '@masknet/icons' -import { useActivatedPluginsSNSAdaptor, Plugin, PluginI18NFieldRender } from '@masknet/plugin-infra/content-script' +import { useActivatedPluginsSNSAdaptor, PluginI18NFieldRender } from '@masknet/plugin-infra/content-script' import { SettingSwitch } from '@masknet/shared' import { makeStyles, MaskColorVar } from '@masknet/theme' import { Services } from '../../extension/service' @@ -72,17 +72,9 @@ export function ApplicationSettingPluginSwitch(props: Props) { return ( {snsAdaptorPlugins - .reduce<{ entry: Plugin.SNSAdaptor.ApplicationEntry; pluginId: string }[]>((acc, cur) => { - if (!cur.ApplicationEntries) return acc - return acc.concat( - cur.ApplicationEntries.map((x) => { - return { - entry: x, - pluginId: cur.ID, - } - }) ?? [], - ) - }, []) + .flatMap(({ ID, ApplicationEntries: entries }) => + (entries ?? []).map((entry) => ({ entry, pluginId: ID })), + ) .filter((x) => x.entry.category === 'dapp') .sort((a, b) => (a.entry.marketListSortingPriority ?? 0) - (b.entry.marketListSortingPriority ?? 0)) .map((x) => ( diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx index ce66e9674eb6..46a36cc3aa8e 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx @@ -7,6 +7,7 @@ import NoNftCard from './NoNftCard' import { FindTrumanContext } from '../context' import { BorderLinearProgress } from './ResultCard' import { ActionButtonPromise } from '../../../extension/options-page/DashboardComponents/ActionButton' +import { sumBy } from 'lodash-unified' const useOptionsStyles = makeStyles()((theme) => { return { @@ -92,11 +93,7 @@ export default function OptionsCard(props: OptionsViewProps) { const renderOptions = (userStatus: UserPollStatus) => { const showCount = !!userStatus.count - const total = userStatus.count - ? userStatus.count.reduce((total, e) => { - return { choice: -1, value: total.value + e.value } - }).value - : 0 + const total = sumBy(userStatus.count ?? [], (status) => status.value) return userStatus.options.map((option, index) => { const count = userStatus.count ? userStatus.count.find((e) => e.choice === index)?.value || 0 : 0 const percent = (total > 0 ? (count * 100) / total : 0).toFixed(2) diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/ResultCard.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/ResultCard.tsx index 03d293bf378b..519ae4a753d8 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/ResultCard.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/ResultCard.tsx @@ -16,6 +16,7 @@ import { PostType } from '../types' import { useContext, useState } from 'react' import { FindTrumanContext } from '../context' import { makeStyles } from '@masknet/theme' +import { sumBy } from 'lodash-unified' export const BorderLinearProgress: any = styled(LinearProgress)(({ theme }) => ({ height: 10, @@ -49,12 +50,7 @@ export default function ResultCard(props: ResultViewProps) { const { t } = useContext(FindTrumanContext) - const total = - result?.count && result.count.length > 0 - ? result.count.reduce((total, e) => { - return { choice: -1, value: total.value + e.value } - }).value - : 1 + const total = result?.count ? sumBy(result.count, (status) => status.value) : 1 const answer = result ? type === PostType.PuzzleResult diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/NftAirdropCard.tsx b/packages/mask/src/plugins/ITO/SNSAdaptor/NftAirdropCard.tsx index 1ecf7565186f..7190867404a9 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/NftAirdropCard.tsx +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/NftAirdropCard.tsx @@ -186,12 +186,7 @@ export function NftAirdropCard(props: NftAirdropCardProps) { const currentChainId = useChainId() const { classes } = useStyles() - const claimableCount = campaignInfos - ? campaignInfos.reduce((acc, cur) => { - if (cur.claimableInfo.claimable) return acc + 1 - return acc - }, 0) - : 0 + const claimableCount = campaignInfos?.filter((info) => info.claimableInfo.claimable).length ?? 0 useEffect(() => { setCheckAddress('') diff --git a/packages/mask/src/plugins/ITO/Worker/apis/chain.ts b/packages/mask/src/plugins/ITO/Worker/apis/chain.ts index d856374686aa..302bbc539fed 100644 --- a/packages/mask/src/plugins/ITO/Worker/apis/chain.ts +++ b/packages/mask/src/plugins/ITO/Worker/apis/chain.ts @@ -69,56 +69,58 @@ export async function getAllPoolsAsSeller( _unlock_time: BigNumber } - const payloadList: { payload: JSON_PayloadFromChain; hash: string }[] = (await response.json()).result?.reduce( - (acc: { payload: JSON_PayloadFromChain; hash: string }[], cur: TxType) => { - if (!isSameAddress(cur.from, sellerAddress)) return acc - try { - const decodedInputParam = interFace.decodeFunctionData( - 'fill_pool', - cur.input, - ) as unknown as FillPoolInputParam - - const [sellerName = '', message = '', regions = '-'] = decodedInputParam._message.split(MSG_DELIMITER) - - const payload: JSON_PayloadFromChain = { - end_time: (decodedInputParam._end.toNumber() + ITO_CONTRACT_BASE_TIMESTAMP / 1000) * 1000, - exchange_token_addresses: decodedInputParam._exchange_addrs, - limit: decodedInputParam._limit.toString(), - message, - qualification_address: decodedInputParam._qualification, - exchange_amounts: decodedInputParam._ratios.map((v) => v.toString()), - start_time: (decodedInputParam._start.toNumber() + ITO_CONTRACT_BASE_TIMESTAMP / 1000) * 1000, - token_address: decodedInputParam._token_addr, - total: decodedInputParam._total_tokens.toString(), - unlock_time: - (decodedInputParam._unlock_time.toNumber() + ITO_CONTRACT_BASE_TIMESTAMP / 1000) * 1000, - seller: { - address: cur.from, - name: sellerName, - }, - contract_address: cur.to, - chain_id: chainId, - regions, - block_number: Number(cur.blockNumber), - // #region Retrieve at step 3 - pid: '', - creation_time: 0, - // #endregion - // #region Retrieve at step 4 - total_remaining: '', - // #endregion - // #region Retrieve from database - password: '', - // #endregion - } + interface Payload { + result?: TxType[] + } + + const payload: Payload = await response.json() - return acc.concat({ payload, hash: cur.hash }) - } catch { - return acc + const payloadList = (payload.result ?? []).flatMap((txType: TxType) => { + if (!isSameAddress(txType.from, sellerAddress)) return [] + try { + const decodedInputParam = interFace.decodeFunctionData( + 'fill_pool', + txType.input, + ) as unknown as FillPoolInputParam + + const [sellerName = '', message = '', regions = '-'] = decodedInputParam._message.split(MSG_DELIMITER) + + const payload: JSON_PayloadFromChain = { + end_time: (decodedInputParam._end.toNumber() + ITO_CONTRACT_BASE_TIMESTAMP / 1000) * 1000, + exchange_token_addresses: decodedInputParam._exchange_addrs, + limit: decodedInputParam._limit.toString(), + message, + qualification_address: decodedInputParam._qualification, + exchange_amounts: decodedInputParam._ratios.map((v) => v.toString()), + start_time: (decodedInputParam._start.toNumber() + ITO_CONTRACT_BASE_TIMESTAMP / 1000) * 1000, + token_address: decodedInputParam._token_addr, + total: decodedInputParam._total_tokens.toString(), + unlock_time: (decodedInputParam._unlock_time.toNumber() + ITO_CONTRACT_BASE_TIMESTAMP / 1000) * 1000, + seller: { + address: txType.from, + name: sellerName, + }, + contract_address: txType.to, + chain_id: chainId, + regions, + block_number: Number(txType.blockNumber), + // #region Retrieve at step 3 + pid: '', + creation_time: 0, + // #endregion + // #region Retrieve at step 4 + total_remaining: '', + // #endregion + // #region Retrieve from database + password: '', + // #endregion } - }, - [], - ) + + return { payload, hash: txType.hash } + } catch { + return [] + } + }) // #endregion // #region @@ -212,18 +214,18 @@ export async function getClaimAllPools(chainId: ChainId, endBlock: number, swapp if (!Array.isArray(result)) return [] - const swapRawData: SwapRawType[] = result.reduce((acc: SwapRawType[], cur: TxType) => { - if (!isSameAddress(cur.from, swapperAddress)) return acc + const swapRawData: SwapRawType[] = result.flatMap((txType: TxType) => { + if (!isSameAddress(txType.from, swapperAddress)) return [] try { - const decodedInputParam = interFace.decodeFunctionData('swap', cur.input) as unknown as SwapInputParam - return acc.concat({ - txHash: cur.hash, + const decodedInputParam = interFace.decodeFunctionData('swap', txType.input) as unknown as SwapInputParam + return { + txHash: txType.hash, pid: decodedInputParam.id, - }) + } } catch { - return acc + return [] } - }, []) + }) // 3. filter out pools that have unlock_time. const swapRawFilteredData = ( @@ -273,6 +275,7 @@ export async function getClaimAllPools(chainId: ChainId, endBlock: number, swapp .filter((v) => Boolean(v)) as SwappedTokenType[] // 5. merge same swap token pools into one + // eslint-disable-next-line unicorn/no-array-reduce const swappedTokenList = swappedTokenUnmergedList.reduce((acc: SwappedTokenType[], cur) => { if (acc.some(checkClaimable(cur)) && cur.isClaimable) { // merge same claimable tokens to one diff --git a/packages/mask/src/plugins/Polls/SNSAdaptor/Polls.tsx b/packages/mask/src/plugins/Polls/SNSAdaptor/Polls.tsx index 3167f68adc78..2fedf1d570ad 100644 --- a/packages/mask/src/plugins/Polls/SNSAdaptor/Polls.tsx +++ b/packages/mask/src/plugins/Polls/SNSAdaptor/Polls.tsx @@ -8,6 +8,7 @@ import type { PollGunDB } from '../Services' import { PollStatus } from '../types' import { SupportedLanguages } from '@masknet/public-api' import { safeUnreachable } from '@dimensiondev/kit' +import { sum } from 'lodash-unified' const useStyles = makeStyles()((theme) => ({ card: { @@ -71,9 +72,7 @@ export function PollCardUI(props: PollCardProps) { const { t } = useI18N() const lang = useLanguage() - const totalVotes = poll.results.reduce( - (accumulator: number, currentValue: number): number => accumulator + currentValue, - ) + const totalVotes = sum(poll.results) const getDeadline = (date: number) => { const deadline = new Date(date) diff --git a/packages/mask/src/plugins/PoolTogether/UI/Account.tsx b/packages/mask/src/plugins/PoolTogether/UI/Account.tsx index e6fdde3a26fa..013cdc5be9e5 100644 --- a/packages/mask/src/plugins/PoolTogether/UI/Account.tsx +++ b/packages/mask/src/plugins/PoolTogether/UI/Account.tsx @@ -8,6 +8,7 @@ import { COMMUNITY_URL } from '../constants' import { useAccountBalance } from '../hooks/useAccountBalances' import type { Pool } from '../types' import { AccountPool } from './AccountPool' +import { sumBy } from 'lodash-unified' const useStyles = makeStyles()((theme) => ({ root: { @@ -76,17 +77,13 @@ export function Account(props: AccountProps) { } const noZeroBalances = balances.filter((balance) => Number.parseInt(balance.account.ticketBalance, 10) !== 0) - const totalUsdBalance = noZeroBalances - .map((balance) => { - const ticketBalance = Number.parseFloat( - formatBalance(balance.account.ticketBalance, Number.parseInt(balance.pool.tokens.ticket.decimals, 10)), - ) - const ticketUsdRate = balance.pool.tokens.ticket.usd - if (!ticketUsdRate) return 0 - return ticketBalance * ticketUsdRate - }) - .reduce((x, y) => x + y, 0) - .toLocaleString() + const totalUsdBalance = sumBy(noZeroBalances, (balance) => { + const decimals = Number.parseInt(balance.pool.tokens.ticket.decimals, 10) + const ticketBalance = Number.parseFloat(formatBalance(balance.account.ticketBalance, decimals)) + const ticketUsdRate = balance.pool.tokens.ticket.usd + if (!ticketUsdRate) return 0 + return ticketBalance * ticketUsdRate + }) return ( diff --git a/packages/mask/src/plugins/PoolTogether/UI/DepositDialog.tsx b/packages/mask/src/plugins/PoolTogether/UI/DepositDialog.tsx index ced220768201..68b1561e6db4 100644 --- a/packages/mask/src/plugins/PoolTogether/UI/DepositDialog.tsx +++ b/packages/mask/src/plugins/PoolTogether/UI/DepositDialog.tsx @@ -295,7 +295,7 @@ export function DepositDialog() { {t('plugin_pooltogether_odds_value', { - value: odds.toLocaleString(), + value: odds, period: getPrizePeriod(t, prizePeriodSeconds), })} diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailabilityNftRedPacket.ts b/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailabilityNftRedPacket.ts index 95a9b460db6d..1537455aa3d1 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailabilityNftRedPacket.ts +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailabilityNftRedPacket.ts @@ -19,10 +19,7 @@ export function useAvailabilityNftRedPacket(id: string, from: string) { const isClaimed = availability.claimed_id !== '0' const totalAmount = result.erc721_token_ids.length const bits = new BigNumber(result.bit_status).toString(2).split('') - const claimedAmount = bits.reduce((acc, cur) => { - if (cur === '1') return acc + 1 - return acc - }, 0) + const claimedAmount = bits.filter((bit) => bit === '1').length const isClaimedAll = totalAmount === claimedAmount const isCompleted = isClaimedAll && !isClaimed const isEnd = isCompleted || availability.expired diff --git a/packages/mask/src/plugins/RedPacket/Worker/apis/chain.ts b/packages/mask/src/plugins/RedPacket/Worker/apis/chain.ts index 6fda5d4d7125..66029ca049c1 100644 --- a/packages/mask/src/plugins/RedPacket/Worker/apis/chain.ts +++ b/packages/mask/src/plugins/RedPacket/Worker/apis/chain.ts @@ -64,53 +64,50 @@ export async function getRedPacketHistory( _total_tokens: BigNumber } - const { result } = await response.json() + const { result }: { result: TxType[] } = await response.json() if (!result.length) return [] - const payloadList: RedPacketJSONPayloadFromChain[] = result.reduce( - (acc: RedPacketJSONPayloadFromChain[], cur: TxType) => { - if (!isSameAddress(cur.from, senderAddress)) return acc - try { - const decodedInputParam = interFace.decodeFunctionData( - 'create_red_packet', - cur.input, - ) as unknown as CreateRedpacketParam - - const redpacketPayload: RedPacketJSONPayloadFromChain = { - contract_address: cur.to, - txid: cur.hash, - shares: decodedInputParam._number.toNumber(), - is_random: decodedInputParam._ifrandom, - total: decodedInputParam._total_tokens.toString(), - duration: decodedInputParam._duration.toNumber() * 1000, - block_number: Number(cur.blockNumber), - contract_version: 4, - network: getChainName(chainId), - token_address: decodedInputParam._token_addr, - sender: { - address: senderAddress, - name: decodedInputParam._name, - message: decodedInputParam._message, - }, - // #region Retrieve at step 3 - rpid: '', - creation_time: 0, - // #endregion - // #region Retrieve at step 4 - total_remaining: '', - claimers: [], - // #endregion - // #region Retrieve from database - password: '', - // #endregion - } - return acc.concat(redpacketPayload) - } catch { - return acc + const payloadList: RedPacketJSONPayloadFromChain[] = result.flatMap((txType: TxType) => { + if (!isSameAddress(txType.from, senderAddress)) return [] + try { + const decodedInputParam = interFace.decodeFunctionData( + 'create_red_packet', + txType.input, + ) as unknown as CreateRedpacketParam + + const redpacketPayload: RedPacketJSONPayloadFromChain = { + contract_address: txType.to, + txid: txType.hash, + shares: decodedInputParam._number.toNumber(), + is_random: decodedInputParam._ifrandom, + total: decodedInputParam._total_tokens.toString(), + duration: decodedInputParam._duration.toNumber() * 1000, + block_number: Number(txType.blockNumber), + contract_version: 4, + network: getChainName(chainId), + token_address: decodedInputParam._token_addr, + sender: { + address: senderAddress, + name: decodedInputParam._name, + message: decodedInputParam._message, + }, + // #region Retrieve at step 3 + rpid: '', + creation_time: 0, + // #endregion + // #region Retrieve at step 4 + total_remaining: '', + claimers: [], + // #endregion + // #region Retrieve from database + password: '', + // #endregion } - }, - [], - ) + return redpacketPayload + } catch { + return [] + } + }) // #endregion // #region diff --git a/packages/mask/src/plugins/Savings/SNSAdaptor/SavingsDialog.tsx b/packages/mask/src/plugins/Savings/SNSAdaptor/SavingsDialog.tsx index 797928a50a45..86eadc23d02e 100644 --- a/packages/mask/src/plugins/Savings/SNSAdaptor/SavingsDialog.tsx +++ b/packages/mask/src/plugins/Savings/SNSAdaptor/SavingsDialog.tsx @@ -32,19 +32,7 @@ import { LidoProtocol } from '../protocols/LDOProtocol' import { AAVEProtocol } from '../protocols/AAVEProtocol' import { LDO_PAIRS } from '../constants' import type { AbiItem } from 'web3-utils' -import { flatten, compact } from 'lodash-unified' - -function splitToPair(a: FungibleTokenDetailed[] | undefined) { - if (!a) { - return [] - } - return a.reduce(function (result: any, value, index, array) { - if (index % 2 === 0) { - result.push(array.slice(index, index + 2)) - } - return result - }, []) -} +import { flatten, compact, chunk } from 'lodash-unified' export interface SavingsDialogProps { open: boolean @@ -100,7 +88,9 @@ export function SavingsDialog({ open, onClose }: SavingsDialogProps) { const protocols = useMemo( () => [ ...LDO_PAIRS.filter((x) => x[0].chainId === chainId).map((pair) => new LidoProtocol(pair)), - ...splitToPair(detailedAaveTokens).map((pair: any) => new AAVEProtocol(pair)), + ...chunk(detailedAaveTokens, 2).map( + (pair) => new AAVEProtocol(pair as [FungibleTokenDetailed, FungibleTokenDetailed]), + ), ], [chainId, detailedAaveTokens, tab], ) diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/ResultCard.tsx b/packages/mask/src/plugins/Snapshot/SNSAdaptor/ResultCard.tsx index efe8cc1910b9..83351e1e31f0 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/ResultCard.tsx +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/ResultCard.tsx @@ -125,11 +125,15 @@ function Content() { }} title={ - {result.powerDetail.reduce((sum, cur, i) => { - const name = - millify(cur.power, { precision: 2, lowercase: true }) + ' ' + cur.name - return `${sum} ${i === 0 ? '' : '+'} ${name}` - }, '')} + {result.powerDetail + .flatMap((detail, index) => { + const name = millify(detail.power, { + precision: 2, + lowercase: true, + }) + return [index === 0 ? '' : '+', name, detail.name] + }) + .join(' ')} } placement="top" diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/VotesCard.tsx b/packages/mask/src/plugins/Snapshot/SNSAdaptor/VotesCard.tsx index decf384a4212..b473f4db44aa 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/VotesCard.tsx +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/VotesCard.tsx @@ -95,14 +95,13 @@ function Content() { const isAverageWeight = v.choices?.every((c) => c.weight === 1) const fullChoiceText = v.totalWeight && v.choices - ? v.choices.reduce((acc, choice, i) => { - return ( - acc + - (i === 0 ? '' : ', ') + - (!isAverageWeight ? formatPercentage(choice.weight / v.totalWeight!) + ' ' : '') + - choice.name - ) - }, '') + ? v.choices + .flatMap((choice, index) => [ + index === 0 ? '' : ', ', + !isAverageWeight ? formatPercentage(choice.weight / v.totalWeight!) + ' ' : '', + choice.name, + ]) + .join('') : null return ( diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/usePower.ts b/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/usePower.ts index 9c6699ebfc59..664a656d01fa 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/usePower.ts +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/usePower.ts @@ -3,7 +3,7 @@ import { useAccount } from '@masknet/web3-shared-evm' import { PluginSnapshotRPC } from '../../messages' import type { ProposalIdentifier } from '../../types' import { useProposal } from './useProposal' -import { mapKeys } from 'lodash-unified' +import { find, sumBy } from 'lodash-unified' export function usePower(identifier: ProposalIdentifier) { const { payload: proposal } = useProposal(identifier.id) @@ -11,18 +11,13 @@ export function usePower(identifier: ProposalIdentifier) { const account = useAccount() return useAsyncRetry(async () => { if (!account) return 0 - return ( - await PluginSnapshotRPC.getScores( - proposal.snapshot, - [account], - proposal.network, - identifier.space, - proposal.strategies, - ) + const scores = await PluginSnapshotRPC.getScores( + proposal.snapshot, + [account], + proposal.network, + identifier.space, + proposal.strategies, ) - .map((v) => mapKeys(v, (_value, key) => key.toLowerCase()) as { [x: string]: number }) - .reduce((acc, cur) => { - return acc + (cur[account.toLowerCase()] ?? 0) - }, 0) + return sumBy(scores, (score) => find(score, (_, key) => key.toLowerCase() === account.toLowerCase()) ?? 0) }, [account]) } diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useResults.ts b/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useResults.ts index 203516d92f52..fdadf07e37e9 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useResults.ts +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useResults.ts @@ -2,6 +2,7 @@ import type { ProposalIdentifier, ProposalResult, VoteItem } from '../../types' import { useSuspense } from '../../../../utils/hooks/useSuspense' import { useProposal } from './useProposal' import { useVotes } from './useVotes' +import { sumBy } from 'lodash-unified' const cache = new Map< string, @@ -25,20 +26,18 @@ async function Suspender(identifier: ProposalIdentifier) { const { payload: proposal } = useProposal(identifier.id) const { payload: votes } = useVotes(identifier) const strategies = proposal.strategies - const powerOfChoices = proposal.choices.map((_choice, i) => - voteForChoice(votes, i).reduce((a, b) => { - if (b.choiceIndex) { - return a + b.balance - } else { - const totalWeight = b.choices!.reduce((_totalWeight, inner_b) => _totalWeight + inner_b.weight, 0) - return a + (b.balance * (b.choices!.find((v) => v.index === i + 1)?.weight ?? 0)) / totalWeight - } - }, 0), + const powerOfChoices = proposal.choices.map((_choice, index) => + sumBy(voteForChoice(votes, index), (choice) => { + if (choice.choiceIndex) return choice.balance + const totalWeight = sumBy(choice.choices, (choice) => choice.weight) + const weight = choice.choices!.find((v) => v.index === index + 1)?.weight ?? 0 + return (choice.balance * weight) / totalWeight + }), ) const powerDetailOfChoices = proposal.choices.map((_choice, i) => - strategies.map((_strategy, sI) => voteForChoice(votes, i).reduce((a, b) => a + b.scores[sI], 0)), + strategies.map((_strategy, index) => sumBy(voteForChoice(votes, i), (vote) => vote.scores[index])), ) - const totalPower = votes.reduce((a, b) => a + b.balance, 0) + const totalPower = sumBy(votes, (vote) => vote.balance) const results: ProposalResult[] = powerOfChoices.map((p, i) => ({ choice: proposal.choices[i], diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useVotes.ts b/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useVotes.ts index fd8c2f5e2e6c..498e1f244f74 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useVotes.ts +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/hooks/useVotes.ts @@ -2,6 +2,7 @@ import { PluginSnapshotRPC } from '../../messages' import type { VoteItem, ProposalIdentifier } from '../../types' import { useSuspense } from '../../../../utils/hooks/useSuspense' import { useProposal } from './useProposal' +import { sumBy } from 'lodash-unified' const cache = new Map] | [1, VoteItem[]] | [2, Error]>() export function votesRetry() { @@ -50,13 +51,11 @@ async function Suspender(identifier: ProposalIdentifier) { totalWeight: choices ? Array.isArray(v.choice) ? v.choice.length - : choices.reduce((acc, choice) => { - return acc + choice.weight - }, 0) + : sumBy(choices, (choice) => choice.weight) : undefined, address: v.voter, authorIpfsHash: v.id, - balance: scores.reduce((a, b) => a + (b[v.voter.toLowerCase()] ? b[v.voter.toLowerCase()] : 0), 0), + balance: sumBy(scores, (score) => score[v.voter.toLowerCase()] ?? 0), scores: strategies.map((_strategy, i) => scores[i][v.voter] || 0), strategySymbol: proposal.space.symbol ?? strategies[0].params.symbol, authorName: profileEntries[v.voter.toLowerCase()]?.name, diff --git a/packages/mask/src/plugins/Tips/hooks/useTipsWalletsList.ts b/packages/mask/src/plugins/Tips/hooks/useTipsWalletsList.ts index eb60dcb8551e..606b72c064d5 100644 --- a/packages/mask/src/plugins/Tips/hooks/useTipsWalletsList.ts +++ b/packages/mask/src/plugins/Tips/hooks/useTipsWalletsList.ts @@ -18,7 +18,7 @@ export function useTipsWalletsList( if (kv && kv.proofs.length > 0 && proofs.length > 0) { const kvCache = kv.proofs.find((x) => x.identity === identity) if (!kvCache) return EMPTY_LIST - const result = proofs.reduce((res, x) => { + const result = proofs.map((x) => { x.isDefault = 0 x.isPublic = 1 const matched = kvCache?.content[PluginId.Tips]?.find((proof) => isSameAddress(x.identity, proof.identity)) @@ -26,9 +26,8 @@ export function useTipsWalletsList( x.isDefault = matched.isDefault x.isPublic = matched.isPublic } - res.push(x) - return res - }, []) + return x + }) const idx = result.findIndex((i) => i.isDefault) if (idx !== -1) { result.unshift(result.splice(idx, 1)[0]) diff --git a/packages/mask/src/plugins/Trader/apis/balancer/index.ts b/packages/mask/src/plugins/Trader/apis/balancer/index.ts index 2777f93fe34d..011191a2ab43 100644 --- a/packages/mask/src/plugins/Trader/apis/balancer/index.ts +++ b/packages/mask/src/plugins/Trader/apis/balancer/index.ts @@ -1,7 +1,6 @@ import { SOR } from '@balancer-labs/sor' import { JsonRpcProvider } from '@ethersproject/providers' import { ChainId, getRPCConstants, getTraderConstants, isSameAddress } from '@masknet/web3-shared-evm' -import { ZERO } from '@masknet/web3-shared-base' import BigNumber from 'bignumber.js' import { first, memoize } from 'lodash-unified' import { currentChainIdSettings } from '../../../Wallet/settings' @@ -73,7 +72,7 @@ export async function getSwaps( // compose routes // learn more: https://github.com/balancer-labs/balancer-frontend/blob/develop/src/components/swap/Routing.vue - const totalSwapAmount = swaps.reduce((total, rawHops) => total.plus(first(rawHops)?.swapAmount || '0'), ZERO) + const totalSwapAmount = BigNumber.sum(...swaps.map((rawHops) => first(rawHops)?.swapAmount || '0')) const pools = sor.onChainCache.pools const routes = swaps.map((rawHops) => { diff --git a/packages/mask/src/plugins/Trader/apis/trending/index.ts b/packages/mask/src/plugins/Trader/apis/trending/index.ts index 70a8db6d683c..a8fa0cd65138 100644 --- a/packages/mask/src/plugins/Trader/apis/trending/index.ts +++ b/packages/mask/src/plugins/Trader/apis/trending/index.ts @@ -224,11 +224,15 @@ async function getCoinTrending(id: string, currency: Currency, dataProvider: Dat ) ?? '' ], }, - market: Object.entries(info.market_data).reduce((accumulated, [key, value]) => { - if (value && typeof value === 'object') accumulated[key] = value[currency.id] ?? 0 - else accumulated[key] = value - return accumulated - }, {}), + market: (() => { + const entries = Object.entries(info.market_data).map(([key, value]) => { + if (value && typeof value === 'object') { + return [key, value[currency.id] ?? 0] + } + return [key, value] + }) + return Object.fromEntries(entries) + })(), tickers: info.tickers.slice(0, 30).map((x) => ({ logo_url: x.market.logo, trade_url: x.trade_url, diff --git a/packages/mask/src/plugins/Trader/apis/uniswap/index.ts b/packages/mask/src/plugins/Trader/apis/uniswap/index.ts index ea5dcce00b7a..dfc6a152cf90 100644 --- a/packages/mask/src/plugins/Trader/apis/uniswap/index.ts +++ b/packages/mask/src/plugins/Trader/apis/uniswap/index.ts @@ -310,7 +310,7 @@ export async function getBulkPairData(pairList: string[]) { const oneDayResult = await fetchPairsHistoricalBulk(pairList, oneDayBlock) - const oneDayData = oneDayResult.reduce>((obj, cur) => ({ ...obj, [cur.id]: cur }), {}) + const oneDayData = Object.fromEntries(oneDayResult.map((pair): [string, Data] => [pair.id, pair])) const pairsData = await Promise.all( current?.map(async (pair) => { @@ -340,9 +340,11 @@ export async function getBulkPairData(pairList: string[]) { }), ) - return pairsData.reduce>( - (obj, cur) => ({ ...obj, [cur.id]: cur }), - {}, + return Object.fromEntries( + pairsData.map((pair): [string, Data & { oneDayVolumeUSD: number; oneDayVolumeUntracked: number }] => [ + pair.id, + pair, + ]), ) } diff --git a/packages/mask/src/plugins/Trader/trader/uniswap/useAllCommonPairs.ts b/packages/mask/src/plugins/Trader/trader/uniswap/useAllCommonPairs.ts index 204f8e3f5829..04220f26f898 100644 --- a/packages/mask/src/plugins/Trader/trader/uniswap/useAllCommonPairs.ts +++ b/packages/mask/src/plugins/Trader/trader/uniswap/useAllCommonPairs.ts @@ -71,22 +71,19 @@ export function useAllCommonPairs(tradeProvider: TradeProvider, currencyA?: Curr const { value: allPairs, ...asyncResult } = usePairs(tradeProvider, allCurrencyCombinations) // only pass along valid pairs, non-duplicated pairs - const allPairs_ = useMemo( - () => - Object.values( - allPairs - // filter out invalid pairs - .filter((result): result is [PairState.EXISTS, Pair] => - Boolean(result[0] === PairState.EXISTS && result[1]), - ) - // filter out duplicated pairs - .reduce>((memo, [, current]) => { - memo[current.liquidityToken.address] = memo[current.liquidityToken.address] ?? current - return memo - }, {}), - ), - [allPairs], - ) + const allPairs_ = useMemo(() => { + const filtered = new Map() + for (const [state, pair] of allPairs as [PairState.EXISTS, Pair][]) { + // filter out invalid pairs + if (state !== PairState.EXISTS) continue + if (!pair) continue + // filter out duplicated pairs + const { address } = pair.liquidityToken + if (filtered.has(address)) continue + filtered.set(pair.liquidityToken.address, pair) + } + return [...filtered.values()] + }, [allPairs]) return { ...asyncResult, diff --git a/packages/mask/src/plugins/Trader/trader/uniswap/useTradeBreakdown.ts b/packages/mask/src/plugins/Trader/trader/uniswap/useTradeBreakdown.ts index 783b57907efb..0c492b38499d 100644 --- a/packages/mask/src/plugins/Trader/trader/uniswap/useTradeBreakdown.ts +++ b/packages/mask/src/plugins/Trader/trader/uniswap/useTradeBreakdown.ts @@ -14,6 +14,7 @@ function computeRealizedLPFeePercent(trade: Trade): Percent { // for each hop in our trade, take away the x*y=k price impact from 0.3% fees // e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03)) const percent = ONE_HUNDRED_PERCENT.subtract( + // eslint-disable-next-line unicorn/no-array-reduce trade.route.pairs.reduce( (currentFee: Percent): Percent => currentFee.multiply(INPUT_FRACTION_AFTER_FEE), ONE_HUNDRED_PERCENT, @@ -22,6 +23,7 @@ function computeRealizedLPFeePercent(trade: Trade): Percent { return new Percent(percent.numerator, percent.denominator) } else { const percent = ONE_HUNDRED_PERCENT.subtract( + // eslint-disable-next-line unicorn/no-array-reduce trade.route.pools.reduce( (currentFee: Percent, pool): Percent => currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(pool.fee, 1_000_000))), diff --git a/packages/mask/src/plugins/Trader/trader/uniswap/useV3BestTrade.ts b/packages/mask/src/plugins/Trader/trader/uniswap/useV3BestTrade.ts index 8b7b50d09439..d4b44d4dc3af 100644 --- a/packages/mask/src/plugins/Trader/trader/uniswap/useV3BestTrade.ts +++ b/packages/mask/src/plugins/Trader/trader/uniswap/useV3BestTrade.ts @@ -78,6 +78,7 @@ export function useV3BestTradeExactIn( } const { bestRoute, amountOut } = quotesResults .filter((x) => x.succeed) + // eslint-disable-next-line unicorn/no-array-reduce .reduce( ( currentBest: { bestRoute: Route | null; amountOut: string | null }, @@ -198,6 +199,7 @@ export function useV3BestTradeExactOut( } const { bestRoute, amountIn } = quotesResults .filter((x) => x.succeed) + // eslint-disable-next-line unicorn/no-array-reduce .reduce( ( currentBest: { bestRoute: Route | null; amountIn: string | null }, diff --git a/packages/mask/src/plugins/Trader/trader/uniswap/useV3SwapPools.ts b/packages/mask/src/plugins/Trader/trader/uniswap/useV3SwapPools.ts index 1c4350cd890a..4e8d6591b71a 100644 --- a/packages/mask/src/plugins/Trader/trader/uniswap/useV3SwapPools.ts +++ b/packages/mask/src/plugins/Trader/trader/uniswap/useV3SwapPools.ts @@ -21,13 +21,11 @@ export function useV3SwapPools( const allCurrencyCombinationsWithAllFees: [Token, Token, FeeAmount][] = useMemo( () => - allCurrencyCombinations.reduce<[Token, Token, FeeAmount][]>((list, [tokenA, tokenB]) => { - return list.concat([ - [tokenA, tokenB, FeeAmount.LOW], - [tokenA, tokenB, FeeAmount.MEDIUM], - [tokenA, tokenB, FeeAmount.HIGH], - ]) - }, []), + allCurrencyCombinations.flatMap<[Token, Token, FeeAmount]>(([tokenA, tokenB]) => [ + [tokenA, tokenB, FeeAmount.LOW], + [tokenA, tokenB, FeeAmount.MEDIUM], + [tokenA, tokenB, FeeAmount.HIGH], + ]), [allCurrencyCombinations], ) const pools = usePools(TradeProvider.UNISWAP_V3, allCurrencyCombinationsWithAllFees) diff --git a/packages/mask/src/utils/getTextUILength.ts b/packages/mask/src/utils/getTextUILength.ts index 21263dbf1884..a4a255501ae3 100644 --- a/packages/mask/src/utils/getTextUILength.ts +++ b/packages/mask/src/utils/getTextUILength.ts @@ -1,6 +1,9 @@ +import { sum } from 'lodash-unified' + /* eslint @dimensiondev/unicode/specific-set: ["error", { "only": "code" }] */ + export function getTextUILength(text: string) { - return Array.from(text).reduce((acc, char) => acc + getCharUILength(char), 0) + return sum(Array.from(text).map(getCharUILength)) } export function sliceTextByUILength(text: string, len: number) { diff --git a/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts b/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts index bd86889f7cef..812584b89b59 100644 --- a/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts +++ b/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts @@ -2,16 +2,13 @@ import { useActivatedPluginsDashboard } from '../manager/dashboard' import { useActivatedPluginsSNSAdaptor } from '../manager/sns-adaptor' import type { Web3Plugin } from '../web3-types' +type Capabilities = Web3Plugin.ObjectCapabilities.Capabilities + export function useAllPluginsWeb3State() { const pluginsSNSAdaptor = useActivatedPluginsSNSAdaptor('any') const pluginsDashboard = useActivatedPluginsDashboard() - - return [...pluginsSNSAdaptor, ...pluginsDashboard].reduce< - Record - >((accumulator, current) => { - if (current.Web3State) { - accumulator[current.ID] = current.Web3State - } - return accumulator - }, {}) + const entries = [...pluginsSNSAdaptor, ...pluginsDashboard] + .filter((definition) => definition.Web3State) + .map((definition): [string, Capabilities] => [definition.ID, definition.Web3State!]) + return Object.fromEntries(entries) as Record } diff --git a/packages/plugin-infra/src/manager/sns-adaptor.ts b/packages/plugin-infra/src/manager/sns-adaptor.ts index 202666e5acc7..9635844ca9b7 100644 --- a/packages/plugin-infra/src/manager/sns-adaptor.ts +++ b/packages/plugin-infra/src/manager/sns-adaptor.ts @@ -57,15 +57,12 @@ export function useActivatedPluginSNSAdaptor(pluginID: string, minimalModeEquals export function useActivatedPluginSNSAdaptor_Web3Supported(chainId: number, pluginID: string) { const plugins = useActivatedPluginsSNSAdaptor('any') - return plugins.reduce>((acc, cur) => { - if (!cur.enableRequirement.web3) { - acc[cur.ID] = true - return acc - } - const supportedChainIds = cur.enableRequirement.web3?.[pluginID as NetworkPluginID]?.supportedChainIds - acc[cur.ID] = supportedChainIds?.includes(chainId) ?? false - return acc - }, {}) + const entries = plugins.map((plugin): [string, boolean] => { + if (!plugin.enableRequirement.web3) return [plugin.ID, true] + const supportedChainIds = plugin.enableRequirement.web3?.[pluginID as NetworkPluginID]?.supportedChainIds + return [plugin.ID, supportedChainIds?.includes(chainId) ?? false] + }) + return Object.fromEntries(entries) as Record } export function startPluginSNSAdaptor( diff --git a/packages/shared-base/src/color/avatar.ts b/packages/shared-base/src/color/avatar.ts index 2b32d55b143a..43b5b6d33ea5 100644 --- a/packages/shared-base/src/color/avatar.ts +++ b/packages/shared-base/src/color/avatar.ts @@ -1,4 +1,5 @@ export function generateContactAvatarColor(input: string, theme: 'light' | 'dark') { + // eslint-disable-next-line unicorn/no-array-reduce const hash = [...input].reduce((prev, current) => { // eslint-disable-next-line no-bitwise const next = current.charCodeAt(0) + (prev << 5) - prev diff --git a/packages/theme/src/Theme/Provider.tsx b/packages/theme/src/Theme/Provider.tsx index 226dedd32885..2260bdc1a4d2 100644 --- a/packages/theme/src/Theme/Provider.tsx +++ b/packages/theme/src/Theme/Provider.tsx @@ -3,6 +3,7 @@ import { MaskIconPalette, MaskIconPaletteContext } from '@masknet/icons' import { CustomSnackbarProvider } from '../Components' function compose(init: React.ReactNode, ...f: ((children: React.ReactNode) => JSX.Element)[]) { + // eslint-disable-next-line unicorn/no-array-reduce return f.reduceRight((prev, curr) => curr(prev), <>{init}) } diff --git a/packages/typed-message/base/transformer/Flatten.ts b/packages/typed-message/base/transformer/Flatten.ts index ba5f32c2a154..8ce7cc6b2789 100644 --- a/packages/typed-message/base/transformer/Flatten.ts +++ b/packages/typed-message/base/transformer/Flatten.ts @@ -20,6 +20,7 @@ export function FlattenTypedMessage(message: TypedMessage, context: Transformati .map((x) => FlattenTypedMessage(x, context)) .flatMap((x) => (isTypedMessageTuple(x) ? (x.meta ? x : x.items) : x)) .filter((x) => !isTypedMessageEmpty(x)) + // eslint-disable-next-line unicorn/no-array-reduce .reduce((result, current) => { const lastItem = result.at(-1) if (!lastItem || lastItem.meta || current.meta) return result.concat(current) diff --git a/packages/typed-message/base/transformer/composed.ts b/packages/typed-message/base/transformer/composed.ts index 1fbea4d71607..8f0c0cc73382 100644 --- a/packages/typed-message/base/transformer/composed.ts +++ b/packages/typed-message/base/transformer/composed.ts @@ -18,6 +18,7 @@ export function composeTransformers(): ComposedTransformers { const transformers = new Set() function composed(message: TypedMessage, context: TransformationContext) { + // eslint-disable-next-line unicorn/no-array-reduce return [...transformers].sort((a, b) => b[1] - a[1]).reduce((p, [c]) => c(p, context), message) } diff --git a/packages/web3-providers/src/debank/format.ts b/packages/web3-providers/src/debank/format.ts index a834097eefa7..22493411061b 100644 --- a/packages/web3-providers/src/debank/format.ts +++ b/packages/web3-providers/src/debank/format.ts @@ -6,40 +6,34 @@ import DeBank from '@masknet/web3-constants/evm/debank.json' type Asset = Web3Plugin.Asset -export function formatAssets(data: WalletTokenRecord[]): Asset[] { +export function formatAssets(records: WalletTokenRecord[]): Asset[] { const supportedChains = Object.values(DeBank.CHAIN_ID).filter(Boolean) - - const result: Asset[] = data.reduce((list: Asset[], y) => { - if (!y.is_verified) return list - const chainIdFromChain = getChainIdFromName(y.chain) - if (!chainIdFromChain) return list - const address = supportedChains.includes(y.id) ? createNativeToken(chainIdFromChain).address : y.id - - return [ - ...list, - { + return records.flatMap((asset) => { + if (!asset.is_verified) return [] + const chainIdFromChain = getChainIdFromName(asset.chain) + if (!chainIdFromChain) return [] + const address = supportedChains.includes(asset.id) ? createNativeToken(chainIdFromChain).address : asset.id + return { + id: address, + chainId: chainIdFromChain, + token: { id: address, + address, chainId: chainIdFromChain, - token: { - id: address, - address, - chainId: chainIdFromChain, - type: TokenType.Fungible, - decimals: y.decimals, - name: y.name, - symbol: y.symbol, - logoURI: y.logo_url, - }, - balance: rightShift(y.amount, y.decimals).toFixed(), - price: { - [CurrencyType.USD]: toFixed(y.price), - }, - value: { - [CurrencyType.USD]: multipliedBy(y.price ?? 0, y.amount).toFixed(), - }, - logoURI: y.logo_url, + type: TokenType.Fungible, + decimals: asset.decimals, + name: asset.name, + symbol: asset.symbol, + logoURI: asset.logo_url, + }, + balance: rightShift(asset.amount, asset.decimals).toFixed(), + price: { + [CurrencyType.USD]: toFixed(asset.price), + }, + value: { + [CurrencyType.USD]: multipliedBy(asset.price ?? 0, asset.amount).toFixed(), }, - ] - }, []) - return result + logoURI: asset.logo_url, + } + }) } diff --git a/packages/web3-shared/evm/utils/token.ts b/packages/web3-shared/evm/utils/token.ts index 863bce1ad8fc..d7cf9024203c 100644 --- a/packages/web3-shared/evm/utils/token.ts +++ b/packages/web3-shared/evm/utils/token.ts @@ -123,22 +123,22 @@ export function createERC20Tokens( symbol: string | ((chainId: ChainId) => string), decimals: number | ((chainId: ChainId) => number), ) { - type Table = ChainIdRecord - const base = {} as Table - return getEnumAsArray(ChainId).reduce((accumulator, { value: chainId }) => { + const entries = getEnumAsArray(ChainId).map(({ value: chainId }): [ChainId, ERC20TokenDetailed] => { const evaluator: (f: T | ((chainId: ChainId) => T)) => T = (f) => typeof f === 'function' ? (f as any)(chainId) : f - - accumulator[chainId] = { - type: EthereumTokenType.ERC20, + return [ chainId, - address: getTokenConstants(chainId)[key] ?? '', - name: evaluator(name), - symbol: evaluator(symbol), - decimals: evaluator(decimals), - } - return accumulator - }, base) + { + type: EthereumTokenType.ERC20, + chainId, + address: getTokenConstants(chainId)[key] ?? '', + name: evaluator(name), + symbol: evaluator(symbol), + decimals: evaluator(decimals), + }, + ] + }) + return Object.fromEntries(entries) as ChainIdRecord } export function addGasMargin(value: BigNumber.Value, scale = 3000) { From 2d48cea4506c2b18e57a33e456b42da69b852342 Mon Sep 17 00:00:00 2001 From: septs Date: Tue, 17 May 2022 16:56:52 +0800 Subject: [PATCH 5/9] chore: improve object-assign using (#6272) --- .../mask/background/services/identity/profile/update.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/mask/background/services/identity/profile/update.ts b/packages/mask/background/services/identity/profile/update.ts index 2a6189457780..b3dc946d59a0 100644 --- a/packages/mask/background/services/identity/profile/update.ts +++ b/packages/mask/background/services/identity/profile/update.ts @@ -60,13 +60,10 @@ export async function resolveUnknownLegacyIdentity(identifier: ProfileIdentifier const records = await queryProfilesDB({ identifiers: [unknown, self] }) if (!records.length) return - const final = { - ...Object.assign({}, ...records), - identifier, - } + const finalRecord: ProfileRecord = Object.assign({}, ...records, { identifier }) try { await consistentPersonaDBWriteAccess(async (t) => { - await createProfileDB(final, t) + await createProfileDB(finalRecord, t) await deleteProfileDB(unknown, t).catch(() => {}) await deleteProfileDB(self, t).catch(() => {}) }) From b16f895e3a470d36dae8dbc2f613be0a510bf1ab Mon Sep 17 00:00:00 2001 From: septs Date: Tue, 17 May 2022 20:47:57 +0800 Subject: [PATCH 6/9] chore: no-useless-{catch,rename} (#6274) * chore: no-useless-{catch,rename} * chore: no-useless-{catch,rename} --- packages/.eslintrc.json | 2 ++ .../src/components/Restore/RestoreFromCloud.tsx | 2 +- packages/encryption/src/encryption/Encryption.ts | 2 +- packages/mask/shared-ui/locales/en-US.json | 1 - packages/mask/shared-ui/locales/qya-AA.json | 1 - packages/mask/src/plugins/Avatar/Services/index.ts | 10 +++------- .../plugins/FindTruman/SNSAdaptor/CompletionCard.tsx | 2 -- .../src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx | 2 -- .../src/plugins/PoolTogether/UI/PoolTogetherView.tsx | 2 +- 9 files changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/.eslintrc.json b/packages/.eslintrc.json index df53e8dd126b..a06fafd88039 100644 --- a/packages/.eslintrc.json +++ b/packages/.eslintrc.json @@ -40,6 +40,8 @@ "no-unmodified-loop-condition": "error", "no-unneeded-ternary": "error", "no-useless-concat": "error", + "no-useless-rename": "error", + "no-useless-catch": "error", "no-loss-of-precision": "error", "prefer-regex-literals": "error", "react/jsx-boolean-value": "error", diff --git a/packages/dashboard/src/components/Restore/RestoreFromCloud.tsx b/packages/dashboard/src/components/Restore/RestoreFromCloud.tsx index f810606257b4..808d9f29f6cd 100644 --- a/packages/dashboard/src/components/Restore/RestoreFromCloud.tsx +++ b/packages/dashboard/src/components/Restore/RestoreFromCloud.tsx @@ -159,7 +159,7 @@ export const RestoreFromCloud = memo(() => { )} - {(_, { backupJson: backupBasicInfoJson, handleRestore: handleRestore }) => ( + {(_, { backupJson: backupBasicInfoJson, handleRestore }) => ( <> diff --git a/packages/encryption/src/encryption/Encryption.ts b/packages/encryption/src/encryption/Encryption.ts index 1e297d84c30d..f05b9132f092 100644 --- a/packages/encryption/src/encryption/Encryption.ts +++ b/packages/encryption/src/encryption/Encryption.ts @@ -94,7 +94,7 @@ async function e2e_v37( target: EncryptTargetE2E, io: EncryptIO, ): Promise<[PayloadWellFormed.EndToEndEncryption, EncryptResult['e2e']]> { - const { authorPublic, postIV: postIV, postKeyEncoded } = context + const { authorPublic, postIV, postKeyEncoded } = context const authorPublicKey = await authorPublic if (!authorPublicKey.some) throw new EncryptError(EncryptErrorReasons.PublicKeyNotFound) diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index c97bf81ed945..7331c936d720 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -65,7 +65,6 @@ "compose_encrypt_visible_to_private": "Private", "compose_encrypt_visible_to_private_sub": "Just Me", "compose_shared_friends": "1 friend", - "compose_shared_friends_other": "{{count}} friends", "compose_encrypt_visible_to_share": "Share with", "compose_encrypt_visible_to_share_sub": "Just Selected Contacts", "compose_encrypt_share_dialog_empty": "No encrypted friends, you can try searching.", diff --git a/packages/mask/shared-ui/locales/qya-AA.json b/packages/mask/shared-ui/locales/qya-AA.json index dd17275ea04a..6f6aaf8e7002 100644 --- a/packages/mask/shared-ui/locales/qya-AA.json +++ b/packages/mask/shared-ui/locales/qya-AA.json @@ -65,7 +65,6 @@ "compose_encrypt_visible_to_private": "crwdns16598:0crwdne16598:0", "compose_encrypt_visible_to_private_sub": "crwdns16600:0crwdne16600:0", "compose_shared_friends": "crwdns16602:0crwdne16602:0", - "compose_shared_friends_other": "crwdns16604:0{{count}}crwdne16604:0", "compose_encrypt_visible_to_share": "crwdns16606:0crwdne16606:0", "compose_encrypt_visible_to_share_sub": "crwdns16608:0crwdne16608:0", "compose_encrypt_share_dialog_empty": "crwdns16610:0crwdne16610:0", diff --git a/packages/mask/src/plugins/Avatar/Services/index.ts b/packages/mask/src/plugins/Avatar/Services/index.ts index 2f25a164f0f5..c59479fc0d79 100644 --- a/packages/mask/src/plugins/Avatar/Services/index.ts +++ b/packages/mask/src/plugins/Avatar/Services/index.ts @@ -42,13 +42,9 @@ export async function saveNFTAvatar( networkPluginId?: NetworkPluginID, chainId?: number, ) { - try { - const avatar = await saveNFTAvatarToRSS(address, nft, '', snsKey) - await setUserAddress(nft.userId, address, network, networkPluginId, chainId) - return avatar - } catch (error) { - throw error - } + const avatar = await saveNFTAvatarToRSS(address, nft, '', snsKey) + await setUserAddress(nft.userId, address, network, networkPluginId, chainId) + return avatar } export async function getAddress(userId: string, network: string, networkPluginId?: NetworkPluginID, chainId?: number) { diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/CompletionCard.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/CompletionCard.tsx index 7105ba2da5a0..67789590560a 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/CompletionCard.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/CompletionCard.tsx @@ -63,8 +63,6 @@ export default function CompletionCard(props: CompletionCardProps) { answer: e.answer || '', })), ) - } catch (error) { - throw error } finally { setSubmitting(false) } diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx index 46a36cc3aa8e..6429f1f4c46d 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/OptionsCard.tsx @@ -196,8 +196,6 @@ export default function OptionsCard(props: OptionsViewProps) { setSubmitting(true) try { await onSubmit(choice) - } catch (error) { - throw error } finally { setSubmitting(false) } diff --git a/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx b/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx index 192076f9db5d..bcc6a144941b 100644 --- a/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx +++ b/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx @@ -73,7 +73,7 @@ export function PoolTogetherView(props: PoolTogetherViewProps) { const [pools, setPools] = useState([]) // #region pools - const { value: _pools = [], error: error, loading: loading, retry: retry } = usePools() + const { value: _pools = [], error, loading, retry } = usePools() _pools.sort((x, y) => Number(y.prize.weeklyTotalValueUsd) - Number(x.prize.weeklyTotalValueUsd)) // #endregion From 0d2c239ba700ed43eac24ea00aff4c9cbb51c28d Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Wed, 18 May 2022 01:20:32 +0800 Subject: [PATCH 7/9] feat: timeline plugin rendering optimization (#6134) * feat: timeline plugin rendering optimization * feat: enable plugin * refactor: reply review * fix: plugin configuration * refactor: reply review * fix: css style * fix: fileserve plugin * fix: css style * fix: parse plugin when on wallet * fix: css style * fix: css style * fix: css style * fix: ito icon * fix: ito icon * refactor: remove console.log * fix: file service name * fix: rename switch network * fix: css style * fix: cyberconnect style * fix: ito style * fix: ito style * fix: css style * fix: css style * fix: css style * fix: css style * fix: ito title * fix: fungible token detailed hook * fix: css style * chore: update red packet * fix: ito connect wallet * fix: css style * fix: css style * fix: maskbox css style * fix: persona verified * fix: remove unused code * fix: show connect wallet * fix: css style * fix: open connect wallet * fix: css style * fix: enabled plugin * fix: remove unused code * fix: css style * fix: build error * fix: build error * fix: reply review * fix: css style * fix: css style * fix: css style * fix: css style * fix: chainnet name * fix: revert code * fix: css style * fix: check wallet chainnet * fix: remove settings * fix: wallet connect * fix: css style * fix: css style * fix: show token * fix: dependency * fix: typo * chore: remove locale key * fix: token * fix: connect wallet * fix: opensea * fix: remove debug * fix: opensea * fix: revert code * fix: remove unused code * fix: reply review * fix: css style * fix: css style * fix: reply review * fix: reply review * fix: reply review * fix: reply review * fix: reply review * fix: typo * fix: reply review * fix: reply review * fix: revert code Co-authored-by: zhouhanseng --- packages/icons/general/Plugin.tsx | 12 + packages/icons/general/Provider.tsx | 14 ++ packages/icons/general/index.ts | 2 + packages/icons/plugins/CyberConnect.tsx | 2 +- packages/icons/plugins/MarketsClaim.tsx | 3 +- packages/icons/plugins/connect.tsx | 31 +++ packages/icons/plugins/index.ts | 2 + packages/icons/plugins/shared.tsx | 20 ++ packages/mask/shared-ui/locales/en-US.json | 30 +-- packages/mask/shared-ui/locales/ja-JP.json | 3 - packages/mask/shared-ui/locales/ko-KR.json | 6 - packages/mask/shared-ui/locales/qya-AA.json | 5 - packages/mask/shared-ui/locales/zh-CN.json | 5 - packages/mask/shared-ui/locales/zh-TW.json | 4 - .../DisabledPluginSuggestion.tsx | 67 +++++- .../InjectedComponents/SearchResultBox.tsx | 2 +- .../ArtBlocks/SNSAdaptor/ActionBar.tsx | 7 +- .../ArtBlocks/SNSAdaptor/Collectible.tsx | 12 +- .../plugins/ArtBlocks/SNSAdaptor/index.tsx | 7 +- .../Collectible/SNSAdaptor/ActionBar.tsx | 106 +++++---- .../Collectible/SNSAdaptor/Collectible.tsx | 34 ++- .../SNSAdaptor/MakeOfferDialog.tsx | 16 +- .../Collectible/SNSAdaptor/PostInspector.tsx | 19 +- .../Collectible/hooks/useCollectibleState.ts | 1 - .../CryptoartAI/SNSAdaptor/ActionBar.tsx | 13 +- .../CryptoartAI/SNSAdaptor/Collectible.tsx | 9 +- .../CryptoartAI/SNSAdaptor/PostInspector.tsx | 21 +- .../CryptoartAI/hooks/useCollectibleState.ts | 1 + .../mask/src/plugins/EVM/hooks/useAsset.ts | 15 +- .../FindTruman/SNSAdaptor/FindTruman.tsx | 154 +++++++------ .../plugins/FindTruman/SNSAdaptor/index.tsx | 9 + packages/mask/src/plugins/FindTruman/base.ts | 20 -- .../plugins/Furucombo/SNSAdaptor/index.tsx | 7 +- .../plugins/Furucombo/UI/FurucomboView.tsx | 87 +++++--- .../src/plugins/Furucombo/UI/PoolView.tsx | 21 +- .../Gitcoin/SNSAdaptor/PreviewCard.tsx | 139 ++++++++---- .../src/plugins/Gitcoin/SNSAdaptor/index.tsx | 7 +- packages/mask/src/plugins/Gitcoin/base.ts | 9 - .../mask/src/plugins/ITO/SNSAdaptor/ITO.tsx | 211 ++++++++++-------- .../plugins/ITO/SNSAdaptor/PostInspector.tsx | 12 +- .../ITO/SNSAdaptor/hooks/useAvailability.ts | 11 +- .../hooks/useAvailabilityComputed.ts | 7 +- .../ITO/SNSAdaptor/hooks/useIfQualified.ts | 5 +- .../mask/src/plugins/ITO/SNSAdaptor/index.tsx | 12 +- packages/mask/src/plugins/ITO/base.ts | 19 -- .../SNSAdaptor/components/ArticlesTab.tsx | 5 +- .../components/DrawResultDialog.tsx | 11 +- .../SNSAdaptor/components/PreviewCard.tsx | 141 +++++++----- .../src/plugins/MaskBox/SNSAdaptor/index.tsx | 9 +- .../mask/src/plugins/MaskPluginWrapper.tsx | 137 +++++++----- .../plugins/PoolTogether/SNSAdaptor/index.tsx | 19 +- .../PoolTogether/UI/PoolTogetherView.tsx | 66 +++--- .../src/plugins/PoolTogether/UI/PoolView.tsx | 18 +- .../mask/src/plugins/PoolTogether/base.tsx | 2 +- .../SNSAdaptor/RedPacket/OperationFooter.tsx | 67 ++++-- .../RedPacket/SNSAdaptor/RedPacket/index.tsx | 41 ++-- .../SNSAdaptor/RedPacket/useStyles.ts | 2 +- .../RedPacket/SNSAdaptor/RedPacketNft.tsx | 41 ++-- .../SNSAdaptor/RedPacketNftInPost.tsx | 7 +- .../SNSAdaptor/RedpacketNftConfirmDialog.tsx | 2 +- .../SNSAdaptor/hooks/useAvailability.ts | 9 +- .../SNSAdaptor/hooks/useRedPacketContract.ts | 14 +- .../plugins/RedPacket/SNSAdaptor/index.tsx | 9 + packages/mask/src/plugins/RedPacket/base.ts | 22 +- .../Snapshot/SNSAdaptor/LoadingFailCard.tsx | 25 ++- .../plugins/Snapshot/SNSAdaptor/Snapshot.tsx | 111 +++++---- .../Snapshot/SNSAdaptor/SnapshotCard.tsx | 2 + .../Snapshot/SNSAdaptor/VotingCard.tsx | 53 +++-- .../src/plugins/Snapshot/SNSAdaptor/index.tsx | 9 + .../src/plugins/Trader/SNSAdaptor/index.tsx | 9 + .../src/plugins/dHEDGE/SNSAdaptor/index.tsx | 9 + .../mask/src/plugins/dHEDGE/UI/PoolView.tsx | 15 +- .../src/plugins/dHEDGE/UI/PoolViewDeck.tsx | 11 +- .../src/utils/hooks/useSettingSwitcher.tsx | 16 +- .../src/web3/UI/EthereumChainBoundary.tsx | 174 ++++++++++----- .../UI/EthereumWalletConnectedBoundary.tsx | 97 ++++---- packages/plugin-infra/src/types.ts | 8 + packages/plugins/CrossChainBridge/src/base.ts | 2 +- .../CyberConnect/src/SNSAdaptor/FollowTab.tsx | 14 +- .../CyberConnect/src/SNSAdaptor/Profile.tsx | 4 +- .../CyberConnect/src/SNSAdaptor/index.tsx | 9 + packages/plugins/CyberConnect/src/base.tsx | 13 -- .../FileService/src/SNSAdaptor/index.tsx | 9 + packages/theme/src/CSSVariables/constants.ts | 8 + packages/web3-providers/src/opensea/index.ts | 2 +- .../evm/contracts/useBalanceChecker.ts | 2 +- .../evm/contracts/useMulticallContract.ts | 2 +- .../evm/contracts/useWrappedEtherContract.ts | 2 +- .../evm/hooks/useFungibleTokenDetailed.ts | 4 +- 89 files changed, 1465 insertions(+), 966 deletions(-) create mode 100644 packages/icons/general/Plugin.tsx create mode 100644 packages/icons/general/Provider.tsx create mode 100644 packages/icons/plugins/connect.tsx create mode 100644 packages/icons/plugins/shared.tsx diff --git a/packages/icons/general/Plugin.tsx b/packages/icons/general/Plugin.tsx new file mode 100644 index 000000000000..98c5b861bc0e --- /dev/null +++ b/packages/icons/general/Plugin.tsx @@ -0,0 +1,12 @@ +import { createIcon } from '../utils' + +export const PluginIcon = createIcon( + 'PluginIcon', + + + , + '0 0 19 18', +) diff --git a/packages/icons/general/Provider.tsx b/packages/icons/general/Provider.tsx new file mode 100644 index 000000000000..3524f1decfe2 --- /dev/null +++ b/packages/icons/general/Provider.tsx @@ -0,0 +1,14 @@ +import { createIcon } from '../utils' + +export const ProviderByIcon = createIcon( + 'ProviderByIcon', + + + , + '0 0 17 16', +) diff --git a/packages/icons/general/index.ts b/packages/icons/general/index.ts index d30eda75b638..24df574b958f 100644 --- a/packages/icons/general/index.ts +++ b/packages/icons/general/index.ts @@ -116,6 +116,8 @@ export * from './MindsRound' export * from './CircleLoading' export * from './AddUser' export * from './PopupRestore' +export * from './Provider' +export * from './Plugin' export * from './Direct' export * from './SearchEmpty' export * from './WarningTriangle' diff --git a/packages/icons/plugins/CyberConnect.tsx b/packages/icons/plugins/CyberConnect.tsx index d2dada033e36..6aafbe3351fe 100644 --- a/packages/icons/plugins/CyberConnect.tsx +++ b/packages/icons/plugins/CyberConnect.tsx @@ -15,7 +15,7 @@ export const CyberConnectIcon: typeof SvgIcon = createPaletteAwareIcon( fillRule="evenodd" clipRule="evenodd" d="M20.8194 14.1385L29.6618 23.2918C29.768 23.4001 29.8525 23.529 29.9105 23.6712C29.9685 23.8133 29.9989 23.9659 30 24.1202C30.001 24.2745 29.9727 24.4275 29.9165 24.5705C29.8604 24.7135 29.7777 24.8436 29.673 24.9535L29.0242 25.6228C28.8418 25.8206 28.601 25.9497 28.3397 25.9897C28.1672 26.0136 27.9917 25.9958 27.8269 25.9377C27.6621 25.8797 27.5126 25.7829 27.3899 25.6551L16.5922 14.4778C16.4045 14.2838 16.2556 14.0534 16.1539 13.7997C16.0523 13.5461 16 13.2742 16 12.9996C16 12.725 16.0523 12.4531 16.1539 12.1994C16.2556 11.9458 16.4045 11.7153 16.5922 11.5213L27.3899 0.344062C27.4951 0.234991 27.62 0.148459 27.7576 0.0894208C27.8951 0.0303825 28.0425 0 28.1914 0C28.3403 0 28.4877 0.0303825 28.6253 0.0894208C28.7628 0.148459 28.8878 0.234991 28.993 0.344062L29.6618 1.04798C29.7672 1.15687 29.8508 1.2862 29.9078 1.42856C29.9648 1.57093 29.9942 1.72354 29.9942 1.87767C29.9942 2.03179 29.9648 2.1844 29.9078 2.32677C29.8508 2.46914 29.7672 2.59848 29.6618 2.70738L20.8194 11.8629C20.5294 12.1655 20.3667 12.5745 20.3667 13.0007C20.3667 13.427 20.5294 13.8359 20.8194 14.1385ZM9.18017 11.8726L0.341223 2.71698C0.233969 2.60853 0.148579 2.47911 0.0900066 2.33622C0.0314345 2.19333 0.000846678 2.03982 1.73677e-05 1.88459C-0.000811943 1.72936 0.0281358 1.5755 0.0851776 1.43194C0.142219 1.28839 0.226225 1.158 0.332313 1.04833L0.978629 0.376712C1.16268 0.180155 1.40373 0.0512975 1.66506 0.00975571C1.83749 -0.0133774 2.01275 0.00476068 2.17734 0.0627778C2.34194 0.120795 2.49149 0.217133 2.61448 0.344398L13.408 11.5218C13.5957 11.7158 13.7445 11.9463 13.8461 12.1999C13.9477 12.4536 14 12.7255 14 13.0001C14 13.2747 13.9477 13.5466 13.8461 13.8002C13.7445 14.0539 13.5957 14.2843 13.408 14.4783L2.61448 25.6557C2.50913 25.7649 2.38405 25.8515 2.24639 25.9105C2.10872 25.9696 1.96117 26 1.81215 26C1.66314 26 1.51558 25.9696 1.37792 25.9105C1.24025 25.8515 1.11517 25.7649 1.00983 25.6557L0.341223 24.9634C0.235829 24.8543 0.152224 24.7247 0.0951825 24.5822C0.038141 24.4396 0.00878436 24.2868 0.00878436 24.1325C0.00878436 23.9782 0.038141 23.8254 0.0951825 23.6828C0.152224 23.5402 0.235829 23.4107 0.341223 23.3016L9.18017 14.1483C9.47006 13.8457 9.63272 13.4367 9.63272 13.0104C9.63272 12.5842 9.47006 12.1752 9.18017 11.8726Z" - fill="white" + fill="black" />, undefined, '-8 -10 44 44', diff --git a/packages/icons/plugins/MarketsClaim.tsx b/packages/icons/plugins/MarketsClaim.tsx index f94a2736ade3..1e82b939ee43 100644 --- a/packages/icons/plugins/MarketsClaim.tsx +++ b/packages/icons/plugins/MarketsClaim.tsx @@ -1,7 +1,6 @@ import { createIcon } from '../utils' -import type { SvgIcon } from '@mui/material' -export const MarketsClaimIcon: typeof SvgIcon = createIcon( +export const MarketsClaimIcon = createIcon( 'Markets', <> diff --git a/packages/icons/plugins/connect.tsx b/packages/icons/plugins/connect.tsx new file mode 100644 index 000000000000..291662e4980f --- /dev/null +++ b/packages/icons/plugins/connect.tsx @@ -0,0 +1,31 @@ +import { createIcon } from '@masknet/icons' +export const PluginWalletConnectIcon = createIcon( + 'PluginWalletConnectIcon', + + + + + + , + '0 0 17 16', +) diff --git a/packages/icons/plugins/index.ts b/packages/icons/plugins/index.ts index 996563638215..042cbb8b08a1 100644 --- a/packages/icons/plugins/index.ts +++ b/packages/icons/plugins/index.ts @@ -24,3 +24,5 @@ export * from './DHEDGEIcon' export * from './PoolTogetherIcon' export * from './SecurityChecker' export * from './ArtBlocks' +export * from './connect' +export * from './shared' diff --git a/packages/icons/plugins/shared.tsx b/packages/icons/plugins/shared.tsx new file mode 100644 index 000000000000..fa880e3d3136 --- /dev/null +++ b/packages/icons/plugins/shared.tsx @@ -0,0 +1,20 @@ +import { createIcon } from '@masknet/icons' +export const SharedIcon = createIcon( + 'SharedIcon', + + + + + + + + + + , + '0 0 19 18', +) diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index 7331c936d720..5fee71e29b8f 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -132,10 +132,6 @@ "user_guide_tip_2": "Connect and switch your wallet.", "user_guide_tip_3": "Browse the Web 3 footprints of your Twitter friends, enjoy the freedom of Web 3.", "user_guide_tip_4": "Click here to have a quick start.", - "create_persona": "Create persona", - "connect_persona": "Connect persona", - "please_create_persona": "Please create persona", - "please_connect_persona": "Please connect persona", "mask_network": "Mask Network", "import": "Import", "no_search_result": "No result", @@ -196,7 +192,6 @@ "wallet_search_no_result": "No results.", "wallet_confirm_with_password": "Confirm with password", "wallet_airdrop_nft_unclaimed_title": "NFT Airdrop Unclaimed:", - "plugin_not_enabled": "{{plugin}} (Not Enabled)", "plugin_external_unknown_plugin": "New unknown Mask plugins found. Do you want to load them?", "plugin_external_loader_search_holder": "Search for an external plugin", "plugin_external_loader_search_button": "Search for plugin", @@ -297,7 +292,7 @@ "plugin_wallet_nft_approving_all": "Unlocking {{symbol}}...", "plugin_wallet_approve_all_nft": "Unlock {{symbol}}", "plugin_wallet_approve_all_nft_successfully": "Unlock {{symbol}} successfully", - "plugin_wallet_connect_a_wallet": "Connect a Wallet", + "plugin_wallet_connect_a_wallet": "Connect wallet", "plugin_wallet_confirm_risk_warning": "Confirm Risk Warning", "plugin_wallet_no_gas_fee": "No Gas Fee", "plugin_wallet_update_gas_fee": "Updating Gas Fee…", @@ -331,11 +326,13 @@ "plugin_wallet_on_connect_in_firefox": "Connect", "plugin_wallet_return_mobile_wallet_options": "Return to Mobile Wallet Options", "plugin_wallet_view_qr_code": "View QR Code", - "plugin_wallet_switch_network": "Switch to {{network}} Network", - "plugin_wallet_switch_network_under_going": "Switching to {{network}} Network…", + "plugin_wallet_switch_network": "Switch to {{network}}", + "plugin_wallet_switch_network_under_going": "Switching to {{network}}", + "plugin_wallet_connect_tips": "You’re connected to a walletConnect\nwallet. Please switch network in that wallet, \nor switch to another wallet.", + "plugin_wallet_connect_network": "Connect {{network}} wallet", + "plugin_wallet_connect_network_under_going": "Connect {{network}} wallet", "plugin_wallet_not_available_on": "Not available on {{network}} Network.", - "plugin_wallet_connect_wallet": "Connect Wallet", - "plugin_wallet_connect_wallet_tip": "Please connect to a wallet.", + "plugin_wallet_connect_wallet": "Connect wallet", "plugin_wallet_name_placeholder": "Enter 1-12 characters", "plugin_wallet_fail_to_sign": "Failed to sign password.", "plugin_wallet_cancel_sign": "Signature canceled.", @@ -607,14 +604,14 @@ "plugin_ito_list_table_got": "Balance", "plugin_ito_list_button_send": "Send", "plugin_ito_withdraw": "Withdraw", - "plugin_ito_qualification_loading": "Verify qualification…", - "plugin_ito_qualification_failed": "The wallet address isn't on the list.", "plugin_ito_withdrawn": "Withdrawn", "plugin_ito_your_swapped_amount": "You swapped {{amount}} {{symbol}}", "plugin_ito_your_claimed_amount": "You claimed {{amount}} {{symbol}}", "plugin_ito_your_refund_amount": "return {{amount}} {{symbol}}.", "plugin_ito_unlock_in_advance": "Unlock in Advance", "plugin_ito_swapped_status": "{{remain}} / {{total}} {{token}} Swapped", + "plugin_ito_qualification_loading": "Verify qualification…", + "plugin_ito_qualification_failed": "The wallet address isn't on the list.", "plugin_ito_congratulations": "Congratulations!", "plugin_ito_out_of_stock_hit": "Better luck next time", "plugin_ito_claim_success_share": "I just attended @{{user}}'s #ITO with @{{account}} to swap ${{symbol}}. Install mask.io and start your own Initial Twitter Offering! \n {{link}}", @@ -816,7 +813,6 @@ "plugin_dhedge_buy_token": "GET {{symbol}}", "plugin_dhedge_enter_an_amount": "Enter an amount", "plugin_dhedge_insufficient_balance": "Insufficient {{symbol}} balance", - "plugin_dhedge_loading": "Loading...", "plugin_dhedge_pool_not_found": "Invalid pool address.", "plugin_dhedge_smt_wrong": "Something went wrong!", "plugin_pooltogether_tab_pools": "Pools", @@ -915,7 +911,8 @@ "plugin_furucombo_rewards": "Rewards", "plugin_furucombo_invest": "Invest", "plugin_furucombo_pool_not_found": "Invalid pool address.", - "plugin_furucombo_smt_wrong": "Something went wrong!", + "plugin_furucombo_load_failed": "Load failed", + "plugin_furucombo_reload": "Reload", "plugin_furucombo_head_pools": "Pools", "plugin_furucombo_head_action": "Action", "plugin_pets_dialog_title": "Non-Fungible Friends", @@ -1123,5 +1120,8 @@ "plugin_transak_name": "Fiat On-Ramp", "plugin_transak_description": "Fiat On-Ramp Aggregator on Twitter. Buy crypto in 60+ countries with Transak support.", "plugin_valuables_name": "Valuables", - "plugin_valuables_description": "Buy & sell tweets autographed by their original creators." + "plugin_valuables_description": "Buy & sell tweets autographed by their original creators.", + "plugin_default_title": "Default", + "plugin_provider_by": "Provided by", + "plugin_enables": "Enable plugins" } diff --git a/packages/mask/shared-ui/locales/ja-JP.json b/packages/mask/shared-ui/locales/ja-JP.json index e66fd9af6238..22e985b3dab6 100644 --- a/packages/mask/shared-ui/locales/ja-JP.json +++ b/packages/mask/shared-ui/locales/ja-JP.json @@ -246,8 +246,6 @@ "plugin_ito_list_table_got": "バランス", "plugin_ito_list_button_send": "送る", "plugin_ito_withdraw": "取り消す", - "plugin_ito_qualification_loading": "資格認証中…", - "plugin_ito_qualification_failed": "ウォレットアドレスがリストにありません。", "plugin_ito_withdrawn": "取り消しました", "plugin_ito_your_swapped_amount": "あなたは {{amount}} {{symbol}} を獲得しました", "plugin_ito_your_claimed_amount": "あなたは {{amount}} {{symbol}} を請求しました", @@ -384,7 +382,6 @@ "plugin_dhedge_buy_token": "{{symbol}} を得る", "plugin_dhedge_enter_an_amount": "量を入力", "plugin_dhedge_insufficient_balance": "{{symbol}} の残高が不十分です", - "plugin_dhedge_loading": "ロード中…", "plugin_dhedge_pool_not_found": "無効なプールアドレスです!", "plugin_dhedge_smt_wrong": "何か間違いが発生しました!" } diff --git a/packages/mask/shared-ui/locales/ko-KR.json b/packages/mask/shared-ui/locales/ko-KR.json index 39b48625493f..309f9b81d1b8 100644 --- a/packages/mask/shared-ui/locales/ko-KR.json +++ b/packages/mask/shared-ui/locales/ko-KR.json @@ -80,8 +80,6 @@ "user_guide_tip_connected": "해당 계정에 성공적으로 연결되었습니다.", "user_guide_tip_1": "클릭하여 메인 기능을 확인하세요.", "user_guide_tip_2": "여기서 월렛을 연결하세요. 여기서 네트워크나 월렛을 바꿀 수 있습니다.", - "create_persona": "페르소나 만들기", - "connect_persona": "페로소나 연결하기", "mask_network": "Mask Network", "import": "불러오기", "no_search_result": "결과 없음", @@ -219,7 +217,6 @@ "plugin_wallet_switch_network_under_going": "{{network}} 네트워크로 바꾸는 중...", "plugin_wallet_not_available_on": "{{network}} 에서는 사용할 수 없습니다.", "plugin_wallet_connect_wallet": "월렛 연결", - "plugin_wallet_connect_wallet_tip": "월렛을 연결하세요.", "plugin_wallet_name_placeholder": "1-12 자 입력하세요", "plugin_wallet_fail_to_sign": "비밀번호 사인 실패합니다.", "plugin_wallet_cancel_sign": "서명이 실패되었습니다.", @@ -437,8 +434,6 @@ "plugin_ito_list_table_got": "잔액", "plugin_ito_list_button_send": "발송", "plugin_ito_withdraw": "철회", - "plugin_ito_qualification_loading": "자격 인증...", - "plugin_ito_qualification_failed": "이 월렛 주소는 리스트에 없습니다.", "plugin_ito_withdrawn": "철회됨", "plugin_ito_your_swapped_amount": "{{amount}} {{symbol}} 스왑되었습니다.", "plugin_ito_your_claimed_amount": "{{amount}} {{symbol}} 수령되었습니다.", @@ -597,7 +592,6 @@ "plugin_dhedge_buy_token": "{{symbol}} 획득", "plugin_dhedge_enter_an_amount": "수액 입력", "plugin_dhedge_insufficient_balance": "{{symbol}} 잔액 부족", - "plugin_dhedge_loading": "로딩 중", "plugin_dhedge_pool_not_found": "무효한 풀 주소!", "plugin_dhedge_smt_wrong": "오류가 발생합니다.", "plugin_pooltogether_tab_pools": "풀(Pools)", diff --git a/packages/mask/shared-ui/locales/qya-AA.json b/packages/mask/shared-ui/locales/qya-AA.json index 6f6aaf8e7002..fa190e5951ae 100644 --- a/packages/mask/shared-ui/locales/qya-AA.json +++ b/packages/mask/shared-ui/locales/qya-AA.json @@ -196,7 +196,6 @@ "wallet_search_no_result": "crwdns8139:0crwdne8139:0", "wallet_confirm_with_password": "crwdns10141:0crwdne10141:0", "wallet_airdrop_nft_unclaimed_title": "crwdns8093:0crwdne8093:0", - "plugin_not_enabled": "crwdns10811:0{{plugin}}crwdne10811:0", "plugin_external_unknown_plugin": "crwdns10143:0crwdne10143:0", "plugin_external_loader_search_holder": "crwdns10145:0crwdne10145:0", "plugin_external_loader_search_button": "crwdns10147:0crwdne10147:0", @@ -335,7 +334,6 @@ "plugin_wallet_switch_network_under_going": "crwdns4689:0{{network}}crwdne4689:0", "plugin_wallet_not_available_on": "crwdns7913:0{{network}}crwdne7913:0", "plugin_wallet_connect_wallet": "crwdns4693:0crwdne4693:0", - "plugin_wallet_connect_wallet_tip": "crwdns4695:0crwdne4695:0", "plugin_wallet_name_placeholder": "crwdns4705:0crwdne4705:0", "plugin_wallet_fail_to_sign": "crwdns4707:0crwdne4707:0", "plugin_wallet_cancel_sign": "crwdns4709:0crwdne4709:0", @@ -607,8 +605,6 @@ "plugin_ito_list_table_got": "crwdns5131:0crwdne5131:0", "plugin_ito_list_button_send": "crwdns5133:0crwdne5133:0", "plugin_ito_withdraw": "crwdns5135:0crwdne5135:0", - "plugin_ito_qualification_loading": "crwdns5137:0crwdne5137:0", - "plugin_ito_qualification_failed": "crwdns5139:0crwdne5139:0", "plugin_ito_withdrawn": "crwdns5141:0crwdne5141:0", "plugin_ito_your_swapped_amount": "crwdns5143:0{{amount}}crwdnd5143:0{{symbol}}crwdne5143:0", "plugin_ito_your_claimed_amount": "crwdns5145:0{{amount}}crwdnd5145:0{{symbol}}crwdne5145:0", @@ -816,7 +812,6 @@ "plugin_dhedge_buy_token": "crwdns5423:0{{symbol}}crwdne5423:0", "plugin_dhedge_enter_an_amount": "crwdns5425:0crwdne5425:0", "plugin_dhedge_insufficient_balance": "crwdns5427:0{{symbol}}crwdne5427:0", - "plugin_dhedge_loading": "crwdns5429:0crwdne5429:0", "plugin_dhedge_pool_not_found": "crwdns5431:0crwdne5431:0", "plugin_dhedge_smt_wrong": "crwdns5433:0crwdne5433:0", "plugin_pooltogether_tab_pools": "crwdns5435:0crwdne5435:0", diff --git a/packages/mask/shared-ui/locales/zh-CN.json b/packages/mask/shared-ui/locales/zh-CN.json index 2e983f733945..8794b0935615 100644 --- a/packages/mask/shared-ui/locales/zh-CN.json +++ b/packages/mask/shared-ui/locales/zh-CN.json @@ -168,7 +168,6 @@ "wallet_search_no_result": "没有任何结果。", "wallet_confirm_with_password": "使用密码确认", "wallet_airdrop_nft_unclaimed_title": "未认领的NFT Airdrop:", - "plugin_not_enabled": "{{plugin}} (未启用)", "plugin_external_unknown_plugin": "发现新的未知Mask插件,您想要加载它们吗?", "plugin_external_loader_search_holder": "查找外部插件", "plugin_external_loader_search_button": "查找插件", @@ -299,7 +298,6 @@ "plugin_wallet_switch_network_under_going": "正在切换到 {{network}} 网络…", "plugin_wallet_not_available_on": "在 {{network}} 网络上不可用。", "plugin_wallet_connect_wallet": "连接钱包", - "plugin_wallet_connect_wallet_tip": "请连接钱包", "plugin_wallet_name_placeholder": "输入1-12 个字符", "plugin_wallet_fail_to_sign": "无法签名密码。", "plugin_wallet_cancel_sign": "签名已取消。", @@ -552,8 +550,6 @@ "plugin_ito_list_table_got": "余额", "plugin_ito_list_button_send": "发送", "plugin_ito_withdraw": "提取", - "plugin_ito_qualification_loading": "资格认证中…", - "plugin_ito_qualification_failed": "钱包地址不在列表内。", "plugin_ito_withdrawn": "已提取", "plugin_ito_your_swapped_amount": "你兑换了 {{amount}} {{symbol}}", "plugin_ito_your_claimed_amount": "你认领了 {{amount}} {{symbol}}", @@ -740,7 +736,6 @@ "plugin_dhedge_buy_token": "获得 {{symbol}}", "plugin_dhedge_enter_an_amount": "输入数额", "plugin_dhedge_insufficient_balance": "{{symbol}} 余额不足", - "plugin_dhedge_loading": "加载中...", "plugin_dhedge_pool_not_found": "无效的池子地址。", "plugin_dhedge_smt_wrong": "发生了一些错误!", "plugin_pooltogether_tab_pools": "池子", diff --git a/packages/mask/shared-ui/locales/zh-TW.json b/packages/mask/shared-ui/locales/zh-TW.json index fa3f8544fd20..5377ab10b6a7 100644 --- a/packages/mask/shared-ui/locales/zh-TW.json +++ b/packages/mask/shared-ui/locales/zh-TW.json @@ -203,7 +203,6 @@ "plugin_wallet_switch_network_under_going": "切換至 {{network}} 中", "plugin_wallet_not_available_on": "{{network}} 不可用", "plugin_wallet_connect_wallet": "連接錢包", - "plugin_wallet_connect_wallet_tip": "請連接你的錢包", "plugin_red_packet_display_name": "插件:紅包", "plugin_red_packet_claimed": "已認領", "plugin_red_packet_erc20_tab_title": "代幣", @@ -382,8 +381,6 @@ "plugin_ito_list_table_got": "餘額", "plugin_ito_list_button_send": "送出", "plugin_ito_withdraw": "提取", - "plugin_ito_qualification_loading": "驗證資格…", - "plugin_ito_qualification_failed": "錢包地址不在清單上。", "plugin_ito_withdrawn": "已提取", "plugin_ito_your_swapped_amount": "你交換了 {{amount}} {{symbol}}", "plugin_ito_your_claimed_amount": "你認領了 {{amount}} {{symbol}}", @@ -536,7 +533,6 @@ "plugin_dhedge_buy_token": "取得 {{symbol}}", "plugin_dhedge_enter_an_amount": "輸入一個金額", "plugin_dhedge_insufficient_balance": "{{symbol}} 餘額不足", - "plugin_dhedge_loading": "讀取中…", "plugin_dhedge_pool_not_found": "錯誤的池地址!", "plugin_dhedge_smt_wrong": "出錯了!" } diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index a018a42e6b65..68a9c33a14b4 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -4,12 +4,15 @@ import { registeredPlugins, usePostInfoDetails, Plugin, - usePluginI18NField, + PluginI18NFieldRender, } from '@masknet/plugin-infra/content-script' import { extractTextFromTypedMessage } from '@masknet/typed-message' -import { Switch } from '@mui/material' import Services from '../../extension/service' import MaskPostExtraInfoWrapper from '../../plugins/MaskPluginWrapper' +import { HTMLProps, useCallback } from 'react' +import { Button, Skeleton, useTheme } from '@mui/material' +import { PluginIcon } from '@masknet/icons' +import { makeStyles } from '@masknet/theme' import { useI18N } from '../../utils' function useDisabledPlugins() { @@ -52,25 +55,71 @@ export function PossiblePluginSuggestionPostInspector() { return } export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefinition[] }) { - const { t } = useI18N() - const t2 = usePluginI18NField() const { plugins } = props + const { t } = useI18N() + const theme = useTheme() + const onClick = useCallback((x: Plugin.DeferredDefinition) => { + Services.Settings.setPluginMinimalModeEnabled(x.ID, false) + }, []) + const _plugins = useActivatedPluginsSNSAdaptor('any') if (!plugins.length) return null + return ( <> {plugins.map((x) => ( } + publisher={ + x.publisher ? : undefined + } + publisherLink={x.publisher?.link} + wrapperProps={_plugins.find((y) => y.ID === x.ID)?.wrapperProps} action={ - Services.Settings.setPluginMinimalModeEnabled(x.ID, false)} - /> + } + content={} /> ))} ) } + +const useRectangleStyles = makeStyles()(() => ({ + rectangle: { + background: 'rgba(255, 255, 255, 0.5)', + }, +})) +interface RectangleProps extends HTMLProps {} + +export function Rectangle(props: RectangleProps) { + const { classes } = useRectangleStyles() + return ( +
+ + + +
+ ) +} diff --git a/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx b/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx index c917be2bf891..5d09af03a749 100644 --- a/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx +++ b/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx @@ -1,7 +1,7 @@ import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra/content-script' const PluginRenderer = createInjectHooksRenderer( - useActivatedPluginsSNSAdaptor.visibility.useNotMinimalMode, + useActivatedPluginsSNSAdaptor.visibility.useAnyMode, (x) => x.SearchResultBox, ) diff --git a/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/ActionBar.tsx b/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/ActionBar.tsx index c0a8bd58ef41..7a227a1f65d2 100644 --- a/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/ActionBar.tsx +++ b/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/ActionBar.tsx @@ -7,17 +7,12 @@ import type { Project } from '../types' const useStyles = makeStyles()((theme) => { return { - root: { - marginLeft: theme.spacing(-0.5), - marginRight: theme.spacing(-0.5), - marginTop: theme.spacing(1), - }, + root: {}, content: { padding: theme.spacing(0), }, button: { flex: 1, - margin: `${theme.spacing(0)} ${theme.spacing(0.5)}`, }, } }) diff --git a/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/Collectible.tsx b/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/Collectible.tsx index 581c3601a1bb..b1fe65404fac 100644 --- a/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/Collectible.tsx +++ b/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/Collectible.tsx @@ -1,14 +1,15 @@ import { useI18N } from '../../../utils' -import { Tab, Tabs, Paper, Card, CardHeader, CardContent, Link, Typography, Avatar } from '@mui/material' +import { Tab, Tabs, Paper, Card, CardHeader, CardContent, Link, Typography, Avatar, Box } from '@mui/material' import { useState } from 'react' import { makeStyles } from '@masknet/theme' import { CollectionView } from './CollectionView' import { DetailsView } from './DetailsView' -import { formatWeiToEther, useChainId } from '@masknet/web3-shared-evm' +import { ChainId, formatWeiToEther, useChainId } from '@masknet/web3-shared-evm' import { useFetchProject } from '../hooks/useProject' import { ActionBar } from './ActionBar' import { resolveProjectLinkOnArtBlocks, resolveUserLinkOnArtBlocks } from '../pipes' import { ArtBlocksLogoUrl } from '../constants' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const useStyles = makeStyles()((theme) => { return { @@ -53,6 +54,7 @@ const useStyles = makeStyles()((theme) => { interface CollectibleProps { projectId: string + chainId?: ChainId } export function Collectible(props: CollectibleProps) { @@ -129,7 +131,11 @@ export function Collectible(props: CollectibleProps) { {pages[tabIndex]} - + + + + + ) } diff --git a/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/index.tsx b/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/index.tsx index d86872021181..a55e7c7bea67 100644 --- a/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/ArtBlocks/SNSAdaptor/index.tsx @@ -7,7 +7,6 @@ import { base } from '../base' import { extractTextFromTypedMessage } from '@masknet/typed-message' import { Collectible } from './Collectible' import type { ChainId } from '@masknet/web3-shared-evm' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { ArtBlocksIcon } from '@masknet/icons' const sns: Plugin.SNSAdaptor.Definition = { @@ -39,11 +38,7 @@ const sns: Plugin.SNSAdaptor.Definition = { function Renderer(props: React.PropsWithChildren<{ chainId: ChainId; projectId: string }>) { usePluginWrapper(true) - return ( - - - - ) + return } export default sns diff --git a/packages/mask/src/plugins/Collectible/SNSAdaptor/ActionBar.tsx b/packages/mask/src/plugins/Collectible/SNSAdaptor/ActionBar.tsx index a51866d7b24a..d17cb3043318 100644 --- a/packages/mask/src/plugins/Collectible/SNSAdaptor/ActionBar.tsx +++ b/packages/mask/src/plugins/Collectible/SNSAdaptor/ActionBar.tsx @@ -7,16 +7,21 @@ import { useControlledDialog } from '../../../utils/hooks/useControlledDialog' import { MakeOfferDialog } from './MakeOfferDialog' import { PostListingDialog } from './PostListingDialog' import { CheckoutDialog } from './CheckoutDialog' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' +import { useChainId } from '@masknet/web3-shared-evm' const useStyles = makeStyles()((theme) => { return { root: { - marginLeft: theme.spacing(-0.5), - marginRight: theme.spacing(-0.5), + width: 'calc(100% - 24px)', }, button: { flex: 1, - margin: `0 ${theme.spacing(0.5)}`, + backgroundColor: theme.palette.maskColor.dark, + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, + color: 'white', }, } }) @@ -28,6 +33,7 @@ export function ActionBar(props: ActionBarProps) { const { classes } = useStyles() const { asset, assetOrder } = CollectibleState.useContainer() const assets = asset.value + const chainId = useChainId() const { open: openCheckoutDialog, @@ -43,53 +49,55 @@ export function ActionBar(props: ActionBarProps) { if (!asset.value) return null return ( - - {!asset.value.isOwner && asset.value.is_auction && assetOrder.value ? ( - - {t('plugin_collectible_buy_now')} - - ) : null} - {!asset.value.isOwner && asset.value.is_auction ? ( - - {t('plugin_collectible_place_bid')} - - ) : null} + + + {!asset.value.isOwner && asset.value.is_auction && assetOrder.value ? ( + + {t('plugin_collectible_buy_now')} + + ) : null} + {!asset.value.isOwner && asset.value.is_auction ? ( + + {t('plugin_collectible_place_bid')} + + ) : null} - {!asset.value.isOwner && !asset.value.is_auction ? ( - - {t('plugin_collectible_make_offer')} - - ) : null} - {assets?.isOwner ? ( - - {t('plugin_collectible_sell')} - - ) : null} - - - + {!asset.value.isOwner && !asset.value.is_auction ? ( + + {t('plugin_collectible_make_offer')} + + ) : null} + {assets?.isOwner ? ( + + {t('plugin_collectible_sell')} + + ) : null} + + + + ) } diff --git a/packages/mask/src/plugins/Collectible/SNSAdaptor/Collectible.tsx b/packages/mask/src/plugins/Collectible/SNSAdaptor/Collectible.tsx index cb4d5b9afac0..eadb415fdc7a 100644 --- a/packages/mask/src/plugins/Collectible/SNSAdaptor/Collectible.tsx +++ b/packages/mask/src/plugins/Collectible/SNSAdaptor/Collectible.tsx @@ -1,6 +1,6 @@ import { ReactElement, useCallback } from 'react' import { Box, Button, CardActions, CardContent, CardHeader, Link, Paper, Tab, Tabs, Typography } from '@mui/material' -import { makeStyles } from '@masknet/theme' +import { makeStyles, MaskColorVar } from '@masknet/theme' import { Trans } from 'react-i18next' import { findIndex } from 'lodash-unified' import formatDateTime from 'date-fns/format' @@ -33,7 +33,6 @@ const useStyles = makeStyles()((theme) => { width: '100%', border: `solid 1px ${theme.palette.divider}`, padding: 0, - marginBottom: 12, }, content: { width: '100%', @@ -141,24 +140,35 @@ export function Collectible(props: CollectibleProps) { setProvider, getEnumAsArray(NonFungibleAssetProvider).map((x) => x.value), resolveCollectibleProviderName, + true, ) // #endregion if (!asset.value || !token) return ( - + Failed to load your collectible on {resolveCollectibleProviderName(provider)}. - {CollectibleProviderSwitcher} - + + {CollectibleProviderSwitcher} + + + + ) const tabs = [ diff --git a/packages/mask/src/plugins/Collectible/SNSAdaptor/MakeOfferDialog.tsx b/packages/mask/src/plugins/Collectible/SNSAdaptor/MakeOfferDialog.tsx index cd7c207be1eb..c87ac106b624 100644 --- a/packages/mask/src/plugins/Collectible/SNSAdaptor/MakeOfferDialog.tsx +++ b/packages/mask/src/plugins/Collectible/SNSAdaptor/MakeOfferDialog.tsx @@ -13,14 +13,19 @@ import { import { makeStyles } from '@masknet/theme' import { first, uniqBy } from 'lodash-unified' import BigNumber from 'bignumber.js' -import { FungibleTokenDetailed, EthereumTokenType, useAccount, useFungibleTokenWatched } from '@masknet/web3-shared-evm' +import { + FungibleTokenDetailed, + EthereumTokenType, + useAccount, + useFungibleTokenWatched, + useChainId, +} from '@masknet/web3-shared-evm' import formatDateTime from 'date-fns/format' import { useI18N } from '../../../utils' import { InjectedDialog } from '@masknet/shared' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' import { UnreviewedWarning } from './UnreviewedWarning' import ActionButton, { ActionButtonPromise } from '../../../extension/options-page/DashboardComponents/ActionButton' -import { EthereumWalletConnectedBoundary } from '../../../web3/UI/EthereumWalletConnectedBoundary' import { DateTimePanel } from '../../../web3/UI/DateTimePanel' import { PluginCollectibleRPC } from '../messages' import { toAsset } from '../helpers' @@ -32,6 +37,7 @@ import { rightShift, ZERO } from '@masknet/web3-shared-base' import type { Coin } from '../../Trader/types' import { SelectTokenListPanel } from './SelectTokenListPanel' import { isWyvernSchemaName } from '../utils' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const useStyles = makeStyles()((theme) => { return { @@ -86,7 +92,7 @@ export function MakeOfferDialog(props: MakeOfferDialogProps) { const { classes } = useStyles() const account = useAccount() - + const chainId = useChainId() const [expirationDateTime, setExpirationDateTime] = useState(new Date()) const [unreviewedChecked, setUnreviewedChecked] = useState(false) const [ToS_Checked, setToS_Checked] = useState(false) @@ -236,7 +242,7 @@ export function MakeOfferDialog(props: MakeOfferDialogProps) { )} - + ) : null} - + diff --git a/packages/mask/src/plugins/Collectible/SNSAdaptor/PostInspector.tsx b/packages/mask/src/plugins/Collectible/SNSAdaptor/PostInspector.tsx index bad1491c86bd..0e66ed8a0044 100644 --- a/packages/mask/src/plugins/Collectible/SNSAdaptor/PostInspector.tsx +++ b/packages/mask/src/plugins/Collectible/SNSAdaptor/PostInspector.tsx @@ -1,7 +1,6 @@ import type { CollectibleJSON_Payload } from '../types' import { Collectible } from './Collectible' import { CollectibleState } from '../hooks/useCollectibleState' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' export interface PostInspectorProps { payload: CollectibleJSON_Payload @@ -11,15 +10,13 @@ export function PostInspector(props: PostInspectorProps) { const token = props.payload return ( - - - - - + + + ) } diff --git a/packages/mask/src/plugins/Collectible/hooks/useCollectibleState.ts b/packages/mask/src/plugins/Collectible/hooks/useCollectibleState.ts index 976962f468f9..f3f79d40d886 100644 --- a/packages/mask/src/plugins/Collectible/hooks/useCollectibleState.ts +++ b/packages/mask/src/plugins/Collectible/hooks/useCollectibleState.ts @@ -15,7 +15,6 @@ function useCollectibleState(token?: CollectibleToken) { const [provider, setProvider] = useState(NonFungibleAssetProvider.OPENSEA) const asset = useAsset(token?.contractAddress ?? '', token?.tokenId ?? '', provider) - // #region asset order from sdk const assetOrder = useAssetOrder(provider, token) // #endregion diff --git a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/ActionBar.tsx b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/ActionBar.tsx index f6dce0601a4b..ef9a9d9fccfd 100644 --- a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/ActionBar.tsx +++ b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/ActionBar.tsx @@ -10,13 +10,14 @@ import { CheckoutDialog } from './CheckoutDialog' const useStyles = makeStyles()((theme) => { return { - root: { - marginLeft: theme.spacing(-0.5), - marginRight: theme.spacing(-0.5), - }, + root: {}, button: { flex: 1, - margin: `0 ${theme.spacing(0.5)}`, + backgroundColor: theme.palette.maskColor.dark, + color: 'white', + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, }, } }) @@ -43,7 +44,7 @@ export function ActionBar(props: ActionBarProps) { if (!asset.value) return null return ( - + {!assetSource?.isSoldOut && !assetSource?.is_owner && assetSource?.is24Auction && diff --git a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/Collectible.tsx b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/Collectible.tsx index 12718c75e0e1..40165f6de8cf 100644 --- a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/Collectible.tsx +++ b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/Collectible.tsx @@ -16,6 +16,7 @@ import { resolveAssetLinkOnCryptoartAI, resolveWebLinkOnCryptoartAI } from '../p import { Markdown } from '../../Snapshot/SNSAdaptor/Markdown' import { ActionBar } from './ActionBar' import { useChainId } from '@masknet/web3-shared-evm' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const useStyles = makeStyles()((theme) => { return { @@ -77,7 +78,7 @@ export function Collectible(props: CollectibleProps) { const { t } = useI18N() const { classes } = useStyles() const chainId = useChainId() - const { asset, events, tabIndex, setTabIndex } = CollectibleState.useContainer() + const { asset, events, tabIndex, setTabIndex, chainId: expectChainId } = CollectibleState.useContainer() const assetSource = useMemo(() => { if (!asset.value || asset.error) return @@ -265,7 +266,11 @@ export function Collectible(props: CollectibleProps) { - + + + + + ) } diff --git a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/PostInspector.tsx b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/PostInspector.tsx index b611ed2f1710..745131e28932 100644 --- a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/PostInspector.tsx +++ b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/PostInspector.tsx @@ -1,7 +1,6 @@ import type { PayloadType } from '../types' import { Collectible } from './Collectible' import { CollectibleState } from '../hooks/useCollectibleState' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' export interface PostInspectorProps { payload: PayloadType @@ -11,16 +10,14 @@ export function PostInspector(props: PostInspectorProps) { const token = props.payload return ( - - - - - + + + ) } diff --git a/packages/mask/src/plugins/CryptoartAI/hooks/useCollectibleState.ts b/packages/mask/src/plugins/CryptoartAI/hooks/useCollectibleState.ts index 282dd2f04f34..057f45b6c10e 100644 --- a/packages/mask/src/plugins/CryptoartAI/hooks/useCollectibleState.ts +++ b/packages/mask/src/plugins/CryptoartAI/hooks/useCollectibleState.ts @@ -20,6 +20,7 @@ function useCollectibleState(token?: Token) { setTabIndex, offers, events, + chainId: token?.chainId, } } diff --git a/packages/mask/src/plugins/EVM/hooks/useAsset.ts b/packages/mask/src/plugins/EVM/hooks/useAsset.ts index fbca7176d93e..4ee7eba31865 100644 --- a/packages/mask/src/plugins/EVM/hooks/useAsset.ts +++ b/packages/mask/src/plugins/EVM/hooks/useAsset.ts @@ -7,6 +7,7 @@ import { useChainId, useTokenConstants, resolveIPFSLinkFromURL, + ChainId, } from '@masknet/web3-shared-evm' import { EVM_RPC } from '../messages' import { resolveAvatarLinkOnCurrentProvider } from '../../Collectible/pipes' @@ -17,14 +18,24 @@ export function useAsset(address: string, tokenId: string, provider: NonFungible const { WNATIVE_ADDRESS } = useTokenConstants() return useAsyncRetry(async () => { - const asset = await EVM_RPC.getAsset({ address, tokenId, chainId, provider }) + const asset = await EVM_RPC.getAsset({ + address, + tokenId, + chainId: provider === NonFungibleAssetProvider.OPENSEA ? ChainId.Mainnet : chainId, + provider, + }) + if (!asset) return return { ...asset, image_url: resolveIPFSLinkFromURL(asset?.image_url ?? ''), isOrderWeth: isSameAddress(asset?.desktopOrder?.payment_token ?? '', WNATIVE_ADDRESS) ?? false, isCollectionWeth: asset?.collection?.payment_tokens?.some(currySameAddress(WNATIVE_ADDRESS)) ?? false, isOwner: asset?.top_ownerships.some((item) => isSameAddress(item.owner.address, account)) ?? false, - collectionLinkUrl: resolveAvatarLinkOnCurrentProvider(chainId, asset, provider), + collectionLinkUrl: resolveAvatarLinkOnCurrentProvider( + provider === NonFungibleAssetProvider.OPENSEA ? ChainId.Mainnet : chainId, + asset, + provider, + ), } }, [account, chainId, WNATIVE_ADDRESS, address, tokenId, provider]) } diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/FindTruman.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/FindTruman.tsx index 9ab793fd4f4a..fd870fe64ebf 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/FindTruman.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/FindTruman.tsx @@ -1,7 +1,7 @@ import { useContext, useState } from 'react' import { makeStyles } from '@masknet/theme' import { FindTrumanContext } from '../context' -import { Alert, Avatar, Box, Card, CardHeader, CardMedia, Chip, Skeleton, Tooltip, Typography } from '@mui/material' +import { Avatar, Box, Card, CardHeader, CardMedia, Chip, Skeleton, Tooltip, Typography } from '@mui/material' import type { CompletionQuestionAnswer, PollResult, @@ -18,6 +18,10 @@ import Footer from './Footer' import StageCard from './StageCard' import EncryptionCard from './EncryptionCard' import CompletionCard from './CompletionCard' +import { PluginWalletConnectIcon } from '@masknet/icons' +import { EthereumWalletConnectedBoundary } from '../../../web3/UI/EthereumWalletConnectedBoundary' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' +import { useChainId } from '@masknet/web3-shared-evm' const useStyles = makeStyles()((theme) => { return { @@ -137,6 +141,7 @@ export function getPostTypeTitle(t: FindTrumanI18nFunction, postType: PostType) export function FindTruman(props: FindTrumanProps) { const { classes } = useStyles() const { address, t } = useContext(FindTrumanContext) + const chainId = useChainId() const { postType, clueId, @@ -182,74 +187,87 @@ export function FindTruman(props: FindTrumanProps) { } return ( - - {postType !== PostType.Encryption ? ( - <> - { - setLoadImg(false) - }} - alt="" - component="img" - height={140} - sx={{ - visibility: loadImg ? 'hidden' : 'unset', - }} - image={storyInfo?.img} - /> - {loadImg && ( - - - - )} - - - {storyInfo.name} - - - - - {isCritical && C} - {isNoncritical && N} - - - + <> + + {postType !== PostType.Encryption ? ( + <> + { + setLoadImg(false) + }} + alt="" + component="img" + height={140} + sx={{ + visibility: loadImg ? 'hidden' : 'unset', + }} + image={storyInfo?.img} + /> + {loadImg && ( + + + + )} + + + {storyInfo.name} + + + + + {isCritical && C} + {isNoncritical && ( + N + )} + + + + - - ) - } + ) + } + /> + {renderCard()} + + ) : ( + + )} + +
+ + + + + } /> - {renderCard()} - - ) : ( - - )} - {!address && ( - - {t('plugin_find_truman_connect_wallet_tip')} - - )} -
- + + + ) } diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx index d623af5cede9..2d7f34795942 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx @@ -114,6 +114,15 @@ const sns: Plugin.SNSAdaptor.Definition = { } })(), ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(251, 49, 32, 0.2) 100%), #FFFFFF;', + }, } export default sns diff --git a/packages/mask/src/plugins/FindTruman/base.ts b/packages/mask/src/plugins/FindTruman/base.ts index ad23830b6f09..4895ed1f8934 100644 --- a/packages/mask/src/plugins/FindTruman/base.ts +++ b/packages/mask/src/plugins/FindTruman/base.ts @@ -1,6 +1,4 @@ import type { Plugin } from '@masknet/plugin-infra' -import { NetworkPluginID } from '@masknet/plugin-infra/web3' -import { ChainId } from '@masknet/web3-shared-evm' import { FIND_TRUMAN_PLUGIN_ID, FIND_TRUMAN_PLUGIN_NAME } from './constants' export const base: Plugin.Shared.Definition = { @@ -14,24 +12,6 @@ export const base: Plugin.Shared.Definition = { architecture: { app: true, web: true }, networks: { type: 'opt-out', networks: {} }, target: 'stable', - web3: { - [NetworkPluginID.PLUGIN_EVM]: { - supportedChainIds: [ - ChainId.Mainnet, - ChainId.BSC, - ChainId.Matic, - ChainId.Arbitrum, - ChainId.xDai, - ChainId.Fantom, - ChainId.Avalanche, - ChainId.Aurora, - ChainId.Conflux, - ChainId.Harmony, - ], - }, - [NetworkPluginID.PLUGIN_FLOW]: { supportedChainIds: [] }, - [NetworkPluginID.PLUGIN_SOLANA]: { supportedChainIds: [] }, - }, }, contribution: { postContent: new Set([ diff --git a/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx index 7e96c7999908..b5ba4e7383a8 100644 --- a/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx @@ -6,7 +6,6 @@ import { extractTextFromTypedMessage } from '@masknet/typed-message' import { parseURL } from '@masknet/shared-base' import { FurucomboIcon } from '@masknet/icons' import { FurucomboView } from '../UI/FurucomboView' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const matchLink = /^https:\/\/furucombo.app\/invest\/(pool|farm)\/(137|1)\/(0x\w+)/ const isFurucomboLink = (link: string): boolean => matchLink.test(link) @@ -47,11 +46,7 @@ const sns: Plugin.SNSAdaptor.Definition = { function Renderer(props: React.PropsWithChildren<{ url: string }>) { const [, category, chainId, address] = props.url.match(matchLink) ?? [] usePluginWrapper(true) - return ( - - - - ) + return } export default sns diff --git a/packages/mask/src/plugins/Furucombo/UI/FurucomboView.tsx b/packages/mask/src/plugins/Furucombo/UI/FurucomboView.tsx index 3f3411e84c74..b7118e239bc0 100644 --- a/packages/mask/src/plugins/Furucombo/UI/FurucomboView.tsx +++ b/packages/mask/src/plugins/Furucombo/UI/FurucomboView.tsx @@ -1,8 +1,9 @@ -import { makeStyles } from '@masknet/theme' +import { makeStyles, MaskColorVar } from '@masknet/theme' import { isSameAddress, useChainId } from '@masknet/web3-shared-evm' -import { Card, CardContent, Tabs, Tab, Typography, Paper } from '@mui/material' +import { Card, CardContent, Tabs, Tab, Typography, Paper, CircularProgress, Button, Stack, Box } from '@mui/material' import { useState } from 'react' import { useI18N } from '../../../utils/i18n-next-ui' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { useFetchPools } from '../hooks/usePool' import type { Investable } from '../types' import { InvestmentsView } from './InvestmentsView' @@ -33,11 +34,20 @@ const useStyles = makeStyles()((theme) => ({ fontFamily: 'inherit', color: 'white', }, + reload: { + backgroundColor: theme.palette.maskColor.dark, + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, + color: 'white', + width: 254, + }, })) interface PoolViewProps { address: string category: string + chainId: number } export function FurucomboView(props: PoolViewProps) { @@ -46,15 +56,25 @@ export function FurucomboView(props: PoolViewProps) { const [tabIndex, setTabIndex] = useState(0) const currentChainId = useChainId() - const { value, loading, error } = useFetchPools() + const { value, loading, error, retry } = useFetchPools() - if (loading) return {t('loading')} + if (loading) + return ( + + + + ) if (error || !value) return ( - - {t('plugin_furucombo_smt_wrong')} - + + + {t('plugin_furucombo_load_failed')} + + + ) const { investables = [] } = value @@ -68,29 +88,40 @@ export function FurucomboView(props: PoolViewProps) { if (!investable) return ( - - {t('plugin_furucombo_pool_not_found')} - + <> + + {t('plugin_furucombo_pool_not_found')} + + + + + + ) return ( - - - setTabIndex(newValue)}> - , - , - - - {tabIndex === 0 ? : null} - {tabIndex === 1 ? : null} - - - + <> + + + setTabIndex(newValue)}> + , + , + + + {tabIndex === 0 ? : null} + {tabIndex === 1 ? : null} + + + + + + + ) } diff --git a/packages/mask/src/plugins/Furucombo/UI/PoolView.tsx b/packages/mask/src/plugins/Furucombo/UI/PoolView.tsx index 990d1e37cc1f..4b8ae7705579 100644 --- a/packages/mask/src/plugins/Furucombo/UI/PoolView.tsx +++ b/packages/mask/src/plugins/Furucombo/UI/PoolView.tsx @@ -1,4 +1,5 @@ import { makeStyles } from '@masknet/theme' +import { useAccount, useChainIdMatched } from '@masknet/web3-shared-evm' import { Button, Divider, Grid, Typography, Container } from '@mui/material' import { FurucomboIcon } from '../../../resources/FurucomboIcon' import { useI18N } from '../../../utils' @@ -87,6 +88,8 @@ export function PoolView(props: PoolProps) { const { classes } = useStyles() const { t } = useI18N() const { category, chainId, address, name, protocol, liquidity, apy, angels } = props.investable + const account = useAccount() + const isValidChainId = useChainIdMatched(chainId) const displayRewardIcon = (rewardToken: Token) => { if (rewardToken.symbol === 'WMATIC') return @@ -114,14 +117,16 @@ export function PoolView(props: PoolProps) { - + {isValidChainId && account ? ( + + ) : null} diff --git a/packages/mask/src/plugins/Gitcoin/SNSAdaptor/PreviewCard.tsx b/packages/mask/src/plugins/Gitcoin/SNSAdaptor/PreviewCard.tsx index 4fccc31502fa..05c1e3d799ad 100644 --- a/packages/mask/src/plugins/Gitcoin/SNSAdaptor/PreviewCard.tsx +++ b/packages/mask/src/plugins/Gitcoin/SNSAdaptor/PreviewCard.tsx @@ -1,5 +1,5 @@ import { useCallback } from 'react' -import { Box, Card, Typography, Button, Grid, Avatar } from '@mui/material' +import { Box, Card, Typography, Button, Avatar, CircularProgress, useTheme } from '@mui/material' import { makeStyles } from '@masknet/theme' import QueryBuilderIcon from '@mui/icons-material/QueryBuilder' import VerifiedUserIcon from '@mui/icons-material/VerifiedUser' @@ -9,6 +9,9 @@ import { useGrant } from '../hooks/useGrant' import { PluginGitcoinMessages } from '../messages' import urlcat from 'urlcat' import { usePostLink } from '../../../components/DataSource/usePostInfo' +import { NetworkPluginID, useChainId } from '@masknet/plugin-infra/web3' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' +import { ChainId } from '@masknet/web3-shared-evm' const useStyles = makeStyles()((theme) => ({ root: { @@ -56,7 +59,8 @@ const useStyles = makeStyles()((theme) => ({ margin: theme.spacing(0, 1), }, buttons: { - padding: theme.spacing(4, 0, 0), + width: '100%', + margin: 0, }, verified: { borderRadius: 50, @@ -68,6 +72,10 @@ const useStyles = makeStyles()((theme) => ({ '-webkit-line-clamp': '4', '-webkit-box-orient': 'vertical', }, + button: { + color: theme.palette.mode === 'dark' ? 'white' : 'black', + width: '100%', + }, })) interface PreviewCardProps { @@ -78,6 +86,9 @@ export function PreviewCard(props: PreviewCardProps) { const { t } = useI18N() const { classes } = useStyles() const { value: grant, error, loading, retry } = useGrant(props.id) + const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) + const isGitCoinSupported = (chainId: ChainId) => [ChainId.Mainnet, ChainId.Matic].includes(chainId) + const theme = useTheme() // #region the donation dialog const postLink = usePostLink() @@ -93,12 +104,26 @@ export function PreviewCard(props: PreviewCardProps) { }, [grant, setDonationDialog]) // #endregion - if (loading) return {t('loading')} + if (loading) + return ( + + + + ) if (error) return ( - + {t('go_wrong')} - @@ -106,60 +131,78 @@ export function PreviewCard(props: PreviewCardProps) { if (!grant) return null return ( - -
- -
-
- - {grant.title} - - {grant.verified ? : null} -
-
- - {grant.description} - -
-
-
- - - {t('plugin_gitcoin_last_updated')} {grant.last_update_natural} - + <> + +
+
-
- - {t('plugin_gitcoin_by')} +
+ + {grant.title} - - - {grant.admin_profile.handle} + {grant.verified ? : null} +
+
+ + {grant.description}
-
- - +
+
+ + + {t('plugin_gitcoin_last_updated')} {grant.last_update_natural} + +
+
+ + {t('plugin_gitcoin_by')} + + + + {grant.admin_profile.handle} + +
+
+
+ + - - - - - - + + + + + + + + ) } diff --git a/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx index 440dac162f56..956f016b34d3 100644 --- a/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx @@ -10,7 +10,6 @@ import { Trans } from 'react-i18next' import { base } from '../base' import { PLUGIN_NAME, PLUGIN_META_KEY } from '../constants' import { DonateDialog } from './DonateDialog' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const isGitcoin = (x: string): boolean => /^https:\/\/gitcoin.co\/grants\/\d+/.test(x) const isGitCoinSupported = (chainId: ChainId) => [ChainId.Mainnet, ChainId.Matic].includes(chainId) @@ -55,11 +54,7 @@ function Renderer(props: React.PropsWithChildren<{ url: string }>) { const [id = ''] = props.url.match(/\d+/) ?? [] const chainId = useChainId(NetworkPluginID.PLUGIN_EVM) usePluginWrapper(true) - return ( - - - - ) + return } export default sns diff --git a/packages/mask/src/plugins/Gitcoin/base.ts b/packages/mask/src/plugins/Gitcoin/base.ts index c247ddc24c7b..65995d21a8a0 100644 --- a/packages/mask/src/plugins/Gitcoin/base.ts +++ b/packages/mask/src/plugins/Gitcoin/base.ts @@ -1,6 +1,4 @@ -import { NetworkPluginID } from '@masknet/plugin-infra/web3' import type { Plugin } from '@masknet/plugin-infra' -import { ChainId } from '@masknet/web3-shared-evm' import { PLUGIN_ID, PLUGIN_NAME, PLUGIN_DESCRIPTION } from './constants' export const base: Plugin.Shared.Definition = { @@ -12,13 +10,6 @@ export const base: Plugin.Shared.Definition = { architecture: { app: true, web: true }, networks: { type: 'opt-out', networks: {} }, target: 'stable', - web3: { - [NetworkPluginID.PLUGIN_EVM]: { - supportedChainIds: [ChainId.Mainnet, ChainId.Rinkeby, ChainId.Matic, ChainId.Mumbai], - }, - [NetworkPluginID.PLUGIN_FLOW]: { supportedChainIds: [] }, - [NetworkPluginID.PLUGIN_SOLANA]: { supportedChainIds: [] }, - }, }, contribution: { postContent: new Set([/https:\/\/gitcoin.co\/grants\/\d+/]) }, } diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/ITO.tsx b/packages/mask/src/plugins/ITO/SNSAdaptor/ITO.tsx index 0233d450294e..fb5df44e3024 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/ITO.tsx +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/ITO.tsx @@ -16,14 +16,13 @@ import { } from '@masknet/web3-shared-evm' import { isZero, ZERO, isGreaterThan } from '@masknet/web3-shared-base' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' -import { Box, Card, Grid, Link, Typography } from '@mui/material' +import { Box, Card, Link, Typography } from '@mui/material' import { makeStyles } from '@masknet/theme' import OpenInNewIcon from '@mui/icons-material/OpenInNew' import { BigNumber } from 'bignumber.js' import classNames from 'classnames' import formatDateTime from 'date-fns/format' import urlcat from 'urlcat' -import { startCase } from 'lodash-unified' import { EnhanceableSite } from '@masknet/shared-base' import { usePostLink } from '../../../components/DataSource/usePostInfo' import ActionButton from '../../../extension/options-page/DashboardComponents/ActionButton' @@ -44,6 +43,10 @@ import { StyledLinearProgress } from './StyledLinearProgress' import { SwapGuide, SwapStatus } from './SwapGuide' import { isFacebook } from '../../../social-network-adaptor/facebook.com/base' import { isTwitter } from '../../../social-network-adaptor/twitter.com/base' +import { SharedIcon, PluginWalletConnectIcon } from '@masknet/icons' +import { EthereumWalletConnectedBoundary } from '../../../web3/UI/EthereumWalletConnectedBoundary' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' +import { startCase } from 'lodash-unified' export interface IconProps { size?: number @@ -56,6 +59,7 @@ interface StyleProps { } const useStyles = makeStyles()((theme, props) => ({ root: { + width: '100%', position: 'relative', color: theme.palette.common.white, flexDirection: 'column', @@ -68,17 +72,14 @@ const useStyles = makeStyles()((theme, props) => ({ backgroundRepeat: 'no-repeat', backgroundColor: '#FF5238', borderRadius: theme.spacing(1), - paddingLeft: theme.spacing(4), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(4), - paddingBottom: theme.spacing(2), + padding: theme.spacing(2), }, header: { display: 'flex', justifyContent: 'space-between', alignItems: 'end', width: props.snsId === EnhanceableSite.Facebook ? '98%' : '100%', - maxWidth: props.snsId === EnhanceableSite.Facebook ? 'auto' : 470, + maxWidth: props.snsId === EnhanceableSite.Facebook ? 'auto' : '100%', }, title: { fontSize: props.titleLength! > 31 ? '1.3rem' : '1.6rem', @@ -151,10 +152,22 @@ const useStyles = makeStyles()((theme, props) => ({ }, }, actionFooter: { - marginTop: theme.spacing(1), + padding: 0, + display: 'flex', }, actionButton: { width: '100%', + backgroundColor: theme.palette.maskColor.dark, + color: 'white', + fontSize: 14, + paddingTop: 10, + fontWeight: 700, + margin: '0 !important', + paddingBottom: 10, + lineHeight: '20px', + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, }, textProviderErr: { color: '#EB5757', @@ -185,6 +198,10 @@ const useStyles = makeStyles()((theme, props) => ({ marginTop: 16, color: '#F4212E', }, + grid: { + width: '100%', + margin: 0, + }, })) // #region token item @@ -266,7 +283,6 @@ export function ITO(props: ITO_Props) { const { listOfStatus, startTime, unlockTime, isUnlocked, hasLockTime, endTime, qualificationAddress } = availabilityComputed // #endregion - const total = new BigNumber(payload_total) const total_remaining = new BigNumber(availability?.remaining ?? '0') const sold = total.minus(total_remaining) @@ -575,7 +591,7 @@ export function ITO(props: ITO_Props) { const FooterBuyerWithLockTimeButton = useMemo( () => ( - + {(() => { if (isUnlocked) return FooterBuyerLockedButton @@ -590,7 +606,7 @@ export function ITO(props: ITO_Props) { ) })()} - + ), [noRemain, listOfStatus, isUnlocked], ) @@ -599,21 +615,18 @@ export function ITO(props: ITO_Props) { () => (
{(() => { - if (hasLockTime) - return ( - - {FooterBuyerWithLockTimeButton} - - ) + if (hasLockTime) return FooterBuyerWithLockTimeButton if (canWithdraw) { return ( - - {t('plugin_ito_withdraw')} - + + + {t('plugin_ito_withdraw')} + + ) } return null @@ -624,8 +637,11 @@ export function ITO(props: ITO_Props) { ) return ( -
- + <> + {title} @@ -699,14 +715,16 @@ export function ITO(props: ITO_Props) { if (!isRegionAllow) { return ( - undefined} - variant="contained" - size="large" - className={classes.actionButton}> - {t('plugin_ito_region_ban')} - + + undefined} + variant="contained" + size="large" + className={classes.actionButton}> + {t('plugin_ito_region_ban')} + + ) } @@ -720,26 +738,16 @@ export function ITO(props: ITO_Props) { if (loadingTradeInfo || loadingAvailability) { return ( - undefined} - variant="contained" - size="large" - className={classes.actionButton}> - {t('plugin_ito_loading')} - - ) - } - - if (!account || !chainIdValid) { - return ( - - {t('plugin_wallet_connect_a_wallet')} - + + undefined} + variant="contained" + size="large" + className={classes.actionButton}> + {t('plugin_ito_loading')} + + ) } @@ -747,13 +755,15 @@ export function ITO(props: ITO_Props) { if (canWithdraw) { return ( - - {t('plugin_ito_withdraw')} - + + + {t('plugin_ito_withdraw')} + + ) } @@ -762,20 +772,41 @@ export function ITO(props: ITO_Props) { !isNativeTokenAddress(qualificationAddress) ) { return ( - - {loadingIfQualified - ? t('plugin_ito_qualification_loading') - : !ifQualified - ? t('plugin_ito_qualification_failed') - : !(ifQualified as Qual_V2).qualified - ? startCase((ifQualified as Qual_V2).errorMsg) - : null} - + <> + + } + onClick={onShareSuccess} + variant="contained" + size="large" + className={classes.actionButton}> + {t('plugin_ito_share')} + + + + + } + classes={{ button: classes.actionButton }}> + + {loadingIfQualified + ? t('plugin_ito_qualification_loading') + : !ifQualified + ? t('plugin_ito_qualification_failed') + : !(ifQualified as Qual_V2).qualified + ? startCase((ifQualified as Qual_V2).errorMsg) + : null} + + + + + ) } @@ -783,8 +814,8 @@ export function ITO(props: ITO_Props) { if (listOfStatus.includes(ITO_Status.waited)) { return ( - - + <> + {t('plugin_ito_unlock_in_advance')} - + {shareText ? ( - + } onClick={onShare} variant="contained" size="large" className={classes.actionButton}> {t('plugin_ito_share')} - + ) : undefined} - + ) } if (listOfStatus.includes(ITO_Status.started)) { return ( - - + <> + {t('plugin_ito_enter')} - - + + } onClick={onShareSuccess} variant="contained" size="large" className={classes.actionButton}> {t('plugin_ito_share')} - - + + ) } @@ -849,7 +882,7 @@ export function ITO(props: ITO_Props) { onClose={() => setOpenClaimDialog(false)} retryPayload={retryITOCard} /> -
+ ) } @@ -858,7 +891,7 @@ export function ITO_Loading() { const PoolBackground = getAssetAsBlobURL(new URL('../assets/pool-loading-background.jpg', import.meta.url)) const { classes } = useStyles({}) return ( -
+
), ), [JSON.stringify(_payload.exchange_tokens)], @@ -65,7 +67,7 @@ export function PostInspector(props: PostInspectorProps) { value: exchangeTokensDetailed, loading: loadingExchangeTokensDetailed, retry: retryExchangeTokensDetailed, - } = useFungibleTokensDetailed(exchangeFungibleTokens) + } = useFungibleTokensDetailed(exchangeFungibleTokens, _payload.chain_id) const retry = useCallback(() => { retryPayload() @@ -97,9 +99,5 @@ export function PostInspector(props: PostInspectorProps) { const theme = useClassicMaskSNSPluginTheme() - return ( - - {renderITO()} - - ) + return {renderITO()} } diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailability.ts b/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailability.ts index 3e738a0cf28f..360546fee49f 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailability.ts +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailability.ts @@ -1,16 +1,17 @@ import { useAsyncRetry } from 'react-use' -import { useAccount, useITOConstants, useChainId, isSameAddress } from '@masknet/web3-shared-evm' +import { useAccount, useITOConstants, useChainId, isSameAddress, ChainId } from '@masknet/web3-shared-evm' import { checkAvailability } from '../../Worker/apis/checkAvailability' -export function useAvailability(id: string, contract_address: string) { +export function useAvailability(id: string, contract_address: string, from?: string, chainId?: ChainId) { const account = useAccount() - const chainId = useChainId() + const fromAccount = from ?? account + const _chainId = useChainId() const { ITO_CONTRACT_ADDRESS } = useITOConstants() const isV1 = isSameAddress(contract_address ?? '', ITO_CONTRACT_ADDRESS) return useAsyncRetry(async () => { if (!id || !contract_address) return null - return checkAvailability(id, account, contract_address, chainId, isV1) - }, [id, account]) + return checkAvailability(id, account ?? fromAccount, contract_address, chainId ?? _chainId, isV1) + }, [id, account, fromAccount, _chainId, chainId]) } diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailabilityComputed.ts b/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailabilityComputed.ts index a1da99b9af88..d8df7c1a0b77 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailabilityComputed.ts +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useAvailabilityComputed.ts @@ -9,7 +9,12 @@ import { ITO_CONTRACT_BASE_TIMESTAMP } from '../../constants' export function useAvailabilityComputed(payload: JSON_PayloadInMask | JSON_PayloadFromChain) { const chainId = useChainId() const { DEFAULT_QUALIFICATION2_ADDRESS } = useITOConstants() - const asyncResult = useAvailability(payload.pid, payload.contract_address) + const asyncResult = useAvailability( + payload.pid, + payload.contract_address, + payload.seller.address, + payload.chain_id ?? chainId, + ) const { value: availability, loading: loadingITO } = asyncResult const qualificationAddress = payload.qualification_address ?? availability?.qualification_addr ?? DEFAULT_QUALIFICATION2_ADDRESS diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useIfQualified.ts b/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useIfQualified.ts index 602c0c61b636..d7b655333501 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useIfQualified.ts +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/hooks/useIfQualified.ts @@ -1,11 +1,12 @@ import { useAsyncRetry } from 'react-use' -import { useAccount } from '@masknet/web3-shared-evm' +import { useAccount, useChainId } from '@masknet/web3-shared-evm' import type { Qualification } from '@masknet/web3-contracts/types/Qualification' import type { Qualification2 } from '@masknet/web3-contracts/types/Qualification2' import { useQualificationContract } from './useQualificationContract' export function useIfQualified(address: string, ito_address: string) { const account = useAccount() + const chainId = useChainId() const { contract: qualificationContract, version } = useQualificationContract(address, ito_address) return useAsyncRetry(async () => { @@ -17,5 +18,5 @@ export function useIfQualified(address: string, ito_address: string) { ).call({ from: account, }) - }, [account, qualificationContract]) + }, [account, qualificationContract, chainId]) } diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx b/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx index 141b5d0b1ecb..a25c322daaf4 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx @@ -16,7 +16,6 @@ import type { JSON_PayloadComposeMask } from '../types' import { ITO_MetadataReader, payloadIntoMask } from './helpers' import { CompositionDialog } from './CompositionDialog' import { set } from 'lodash-unified' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { MarketsIcon, MarketsClaimIcon } from '@masknet/icons' import { ApplicationEntry } from '@masknet/shared' import { CrossIsolationMessages } from '@masknet/shared-base' @@ -39,11 +38,7 @@ const sns: Plugin.SNSAdaptor.Definition = { const payload = ITO_MetadataReader(props.message.meta) usePluginWrapper(payload.ok) if (!payload.ok) return null - return ( - - - - ) + return }, CompositionDialogMetadataBadgeRender: new Map([ [ITO_MetaKey_1, onAttached_ITO], @@ -120,6 +115,11 @@ const sns: Plugin.SNSAdaptor.Definition = { } })(), ], + wrapperProps: { + icon: , + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(41, 228, 253, 0.2) 100%), #FFFFFF;', + }, } function onAttached_ITO(payload: JSON_PayloadComposeMask) { diff --git a/packages/mask/src/plugins/ITO/base.ts b/packages/mask/src/plugins/ITO/base.ts index 84fc5cbb4949..eddc066a64c6 100644 --- a/packages/mask/src/plugins/ITO/base.ts +++ b/packages/mask/src/plugins/ITO/base.ts @@ -1,6 +1,4 @@ -import { NetworkPluginID } from '@masknet/plugin-infra/web3' import type { Plugin } from '@masknet/plugin-infra' -import { ChainId } from '@masknet/web3-shared-evm' import { ITO_MetaKey_1, ITO_MetaKey_2, ITO_PluginID } from './constants' export const base: Plugin.Shared.Definition = { @@ -17,23 +15,6 @@ export const base: Plugin.Shared.Definition = { networks: {}, }, target: 'stable', - web3: { - [NetworkPluginID.PLUGIN_EVM]: { - supportedChainIds: [ - ChainId.Mainnet, - ChainId.BSC, - ChainId.Matic, - ChainId.Arbitrum, - ChainId.xDai, - ChainId.Aurora, - ChainId.Avalanche, - ChainId.Fantom, - ChainId.Harmony, - ], - }, - [NetworkPluginID.PLUGIN_FLOW]: { supportedChainIds: [] }, - [NetworkPluginID.PLUGIN_SOLANA]: { supportedChainIds: [] }, - }, }, contribution: { metadataKeys: new Set([ITO_MetaKey_1, ITO_MetaKey_2]) }, } diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/ArticlesTab.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/ArticlesTab.tsx index 9c1ab0004493..50a92ddaf103 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/ArticlesTab.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/ArticlesTab.tsx @@ -5,7 +5,10 @@ import { MaskSharpIconOfSize } from '../../../../resources/MaskIcon' import { Video } from '../../../../components/shared/Video' const useStyles = makeStyles()((theme) => ({ - main: {}, + main: { + paddingLeft: 16, + paddingRight: 16, + }, body: { width: '100%', height: 360, diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/DrawResultDialog.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/DrawResultDialog.tsx index cbcd770a0b99..e371a827b775 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/DrawResultDialog.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/DrawResultDialog.tsx @@ -10,9 +10,10 @@ import ActionButton from '../../../../extension/options-page/DashboardComponents import { activatedSocialNetworkUI } from '../../../../social-network' import { usePostLink } from '../../../../components/DataSource/usePostInfo' import { Context } from '../../hooks/useContext' +import { SharedIcon } from '@masknet/icons' const useStyles = makeStyles()((theme) => ({ - main: {}, + main: { padding: 8 }, list: { height: 360, overflow: 'auto', @@ -21,6 +22,7 @@ const useStyles = makeStyles()((theme) => ({ flexWrap: 'wrap', gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))', gridGap: theme.spacing(1), + padding: 8, }, token: {}, })) @@ -59,7 +61,12 @@ export function DrawResultDialog(props: DrawResultDialogProps) { ))} - + } + size="medium" + fullWidth + variant="contained" + onClick={onShare}> Share diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/PreviewCard.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/PreviewCard.tsx index 94a9a1fbd89c..bded23df3d24 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/PreviewCard.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/components/PreviewCard.tsx @@ -1,8 +1,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useContainer } from 'unstated-next' import { makeStyles } from '@masknet/theme' -import { Box, Button, Skeleton, Typography } from '@mui/material' -import { formatBalance, TransactionStateType, useTransactionCallback } from '@masknet/web3-shared-evm' +import { Box, Button, CircularProgress, Typography, useTheme } from '@mui/material' +import { formatBalance, TransactionStateType, useChainId, useTransactionCallback } from '@masknet/web3-shared-evm' import AbstractTab, { AbstractTabProps } from '../../../../components/shared/AbstractTab' import { EthereumWalletConnectedBoundary } from '../../../../web3/UI/EthereumWalletConnectedBoundary' import ActionButton from '../../../../extension/options-page/DashboardComponents/ActionButton' @@ -14,6 +14,7 @@ import { DetailsTab } from './DetailsTab' import { DrawResultDialog } from './DrawResultDialog' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' import { WalletMessages } from '../../../Wallet/messages' +import { EthereumChainBoundary } from '../../../../web3/UI/EthereumChainBoundary' const useTabsStyles = makeStyles()((theme) => ({ tab: { @@ -47,6 +48,8 @@ export function PreviewCard(props: PreviewCardProps) { const state = useState(CardTab.Articles) const [openDrawDialog, setOpenDrawDialog] = useState(false) const [openDrawResultDialog, setOpenDrawResultDialog] = useState(false) + const chainId = useChainId() + const theme = useTheme() const { boxId, @@ -147,16 +150,26 @@ export function PreviewCard(props: PreviewCardProps) { if (boxState === BoxState.UNKNOWN) return ( - - - + + ) if (boxState === BoxState.ERROR) return ( - Something went wrong. - @@ -164,8 +177,19 @@ export function PreviewCard(props: PreviewCardProps) { if (boxState === BoxState.NOT_FOUND || !boxInfo) return ( - Failed to load box. - @@ -189,47 +213,62 @@ export function PreviewCard(props: PreviewCardProps) { } return ( - - - - setOpenDrawDialog(true)}> - {(() => { - return boxState === BoxState.READY && paymentTokenAddress ? ( - <> - {boxStateMessage} ( - {formatBalance(paymentTokenPrice, paymentTokenDetailed?.decimals ?? 0)}{' '} - {paymentTokenDetailed?.symbol}/Time) - - ) : ( - boxStateMessage - ) - })()} - - - { - setOpenBoxTransactionOverrides(null) - setOpenDrawDialog(false) - }} - onSubmit={onDraw} - /> - { - refreshLastPurchasedTokenIds() - setOpenDrawResultDialog(false) - }} - /> - + <> + + + + { + setOpenBoxTransactionOverrides(null) + setOpenDrawDialog(false) + }} + onSubmit={onDraw} + /> + { + refreshLastPurchasedTokenIds() + setOpenDrawResultDialog(false) + }} + /> + + + + + setOpenDrawDialog(true)}> + {(() => { + return boxState === BoxState.READY && paymentTokenAddress ? ( + <> + {boxStateMessage} ( + {formatBalance(paymentTokenPrice, paymentTokenDetailed?.decimals ?? 0)}{' '} + {paymentTokenDetailed?.symbol}/Time) + + ) : ( + boxStateMessage + ) + })()} + + + + + ) } diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx index b471787ab708..f40ea9b5b7f5 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx @@ -4,7 +4,6 @@ import { base } from '../base' import { extractTextFromTypedMessage } from '@masknet/typed-message' import { Trans } from 'react-i18next' import { parseURL } from '@masknet/shared-base' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { PreviewCard } from './components/PreviewCard' import { Context } from '../hooks/useContext' import { ApplicationEntry } from '@masknet/shared' @@ -70,10 +69,8 @@ function Renderer(props: React.PropsWithChildren<{ url: string }>) { if (shouldNotRender) return null return ( - - - - - + + + ) } diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index 6618f9b41ba0..82f6f215d111 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -1,10 +1,7 @@ -import { Typography, SnackbarContent, Button, Link } from '@mui/material' +import { Typography, SnackbarContent, Link, useTheme } from '@mui/material' import { makeStyles, MaskColorVar } from '@masknet/theme' -import { activatedSocialNetworkUI } from '../social-network' import { MaskIcon } from '../resources/MaskIcon' import { Suspense, ReactNode, useMemo, forwardRef, useImperativeHandle, useState } from 'react' -import { isTwitter } from '../social-network-adaptor/twitter.com/base' -import { usePersonaConnectStatus } from '../components/DataSource/usePersonaConnectStatus' import { useI18N } from '../utils' import { Box } from '@mui/system' import { @@ -14,104 +11,110 @@ import { Plugin, PluginWrapperMethods, } from '@masknet/plugin-infra/content-script' +import { ProviderByIcon } from '@masknet/icons' interface PluginWrapperProps extends React.PropsWithChildren<{}> { open?: boolean - title: string + title: JSX.Element | string width?: number + content?: ReactNode action?: ReactNode publisher?: JSX.Element + wrapperProps?: Plugin.SNSAdaptor.PluginWrapperProps publisherLink?: string } -const useStyles = makeStyles()((theme) => { +const useStyles = makeStyles<{ backgroundGradient?: string }>()((theme, props) => { return { card: { + background: + props?.backgroundGradient ?? + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(45, 41, 253, 0.2) 100%), #FFFFFF;', margin: theme.spacing(2, 0), width: '100%', boxSizing: 'border-box', - border: `1px solid ${theme.palette.secondaryDivider}`, cursor: 'default', - ...(isTwitter(activatedSocialNetworkUI) - ? { - borderRadius: 15, - overflow: 'hidden', - } - : null), + borderRadius: 15, + overflow: 'hidden', }, header: { backgroundColor: 'transparent', color: theme.palette.text.primary, display: 'flex', alignItems: 'center', - padding: theme.spacing(2), + padding: 15, }, title: { display: 'flex', flexDirection: 'column', paddingLeft: theme.spacing(1.5), }, - action: { + provider: { + display: 'flex', + alignItems: 'center', + '& > a': { + lineHeight: 0, + }, + }, + publish: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'flex-end', }, + action: { + textAlign: 'center', + margin: theme.spacing(1), + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + marginBottom: 16, + }, body: { - borderTop: `1px solid ${theme.palette.secondaryDivider}`, - padding: theme.spacing(2), + padding: theme.spacing(0), }, button: { - color: MaskColorVar.twitterButtonText, + backgroundColor: theme.palette.maskColor.dark, + color: 'white', + width: 254, '&,&:hover': { - background: MaskColorVar.twitterButton, + background: theme.palette.maskColor.dark, }, + borderRadius: 9999, }, } }) export default function MaskPostExtraInfoWrapper(props: PluginWrapperProps) { - const { classes } = useStyles() - const { open, title, children, action, publisher, publisherLink } = props - const personaConnectStatus = usePersonaConnectStatus() + const { open, title, children, action, publisher, publisherLink, content, wrapperProps } = props + const { classes } = useStyles({ backgroundGradient: wrapperProps?.backgroundGradient }) + const theme = useTheme() const { t } = useI18N() - const name = !personaConnectStatus.hasPersona - ? t('please_create_persona') - : !personaConnectStatus.connected - ? t('please_connect_persona') - : title - - const actionButton = useMemo(() => { - if (!personaConnectStatus.action) return null - - const button = personaConnectStatus.hasPersona ? t('connect_persona') : t('create_persona') - return ( - - ) - }, [personaConnectStatus, t]) - const publisherInfo = useMemo(() => { - if (!publisher) return null + if (!publisher) return const main = ( - + {publisher} ) return ( - - - Provided by + + + {t('plugin_provider_by')} + {main} {publisherLink ? ( - {main} + - ) : ( - main - )} + ) : null} ) }, [publisher, publisherLink]) @@ -122,26 +125,39 @@ export default function MaskPostExtraInfoWrapper(props: PluginWrapperProps) { style={{ display: open ? 'block' : 'none' }} onClick={(ev) => ev.stopPropagation()}>
- -
- - Mask Plugin {!personaConnectStatus.connected && title ? `(${title})` : ''} - - - {name} - -
-
{actionButton || action || publisherInfo}
+ {wrapperProps?.icon ?? ( + + )} + + {wrapperProps?.title ?? title ?? t('plugin_default_title')} + +
{publisherInfo}
- {personaConnectStatus.connected && children ?
{children}
: null} + {action ? ( + <> + + {content} + +
{action}
+ + ) : null} + {children ?
{children}
: null}
) + return } children={inner} /> } export const MaskPostExtraPluginWrapper: PluginWrapperComponent = forwardRef( (props, ref) => { - const { ID, name, publisher } = props.definition + const { ID, name, publisher, wrapperProps } = props.definition const t = usePluginI18NField() const [width, setWidth] = useState(undefined) const [open, setOpen] = useState(false) @@ -159,6 +175,7 @@ export const MaskPostExtraPluginWrapper: PluginWrapperComponent URL_PATTERN.test(url) @@ -46,17 +44,20 @@ const sns: Plugin.SNSAdaptor.Definition = { icon: , }, ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + ' linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(70, 39, 155, 0.2) 100%), #FFFFFF;', + }, } export default sns function Renderer(props: React.PropsWithChildren<{ url: string }>) { usePluginWrapper(true) - return ( - [ChainId.Mainnet, ChainId.Matic].includes(chainId)}> - - - ) + return } diff --git a/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx b/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx index bcc6a144941b..c97b4f92f9f9 100644 --- a/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx +++ b/packages/mask/src/plugins/PoolTogether/UI/PoolTogetherView.tsx @@ -1,7 +1,7 @@ import { RefreshIcon } from '@masknet/icons' import { DarkColor } from '@masknet/theme/base' -import { usePoolTogetherConstants } from '@masknet/web3-shared-evm' -import { Card, CardContent, CircularProgress, Paper, Tab, Tabs, Typography } from '@mui/material' +import { ChainId, usePoolTogetherConstants } from '@masknet/web3-shared-evm' +import { Box, Card, CardContent, CircularProgress, Paper, Tab, Tabs, Typography } from '@mui/material' import { makeStyles } from '@masknet/theme' import React, { useState, useEffect } from 'react' import { useI18N } from '../../../utils/i18n-next-ui' @@ -9,6 +9,7 @@ import { usePool, usePools } from '../hooks/usePools' import type { Pool } from '../types' import { Account } from './Account' import { PoolsView } from './PoolsView' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const useStyles = makeStyles()((theme) => ({ root: { @@ -18,10 +19,11 @@ const useStyles = makeStyles()((theme) => ({ padding: 0, backgroundColor: '#290b5a', textAlign: 'center', + width: '100%', }, message: { - color: theme.palette.text.primary, textAlign: 'center', + padding: 16, }, refresh: { bottom: theme.spacing(1), @@ -112,31 +114,43 @@ export function PoolTogetherView(props: PoolTogetherViewProps) { } if (pools.length === 0) { - return {t('plugin_pooltogether_no_pool')} + return ( + + {t('plugin_pooltogether_no_pool')} + + ) } return ( - - - , newValue: number) => setTabIndex(newValue)} - TabIndicatorProps={{ - style: { - display: 'none', - }, - }}> - {tabs} - - - {tabIndex === 0 ? : null} - {tabIndex === 1 ? : null} - - - + <> + + + , newValue: number) => setTabIndex(newValue)} + TabIndicatorProps={{ + style: { + display: 'none', + }, + }}> + {tabs} + + + {tabIndex === 0 ? : null} + {tabIndex === 1 ? : null} + + + + + [ChainId.Mainnet, ChainId.Matic].includes(chainId)} + /> + + ) } diff --git a/packages/mask/src/plugins/PoolTogether/UI/PoolView.tsx b/packages/mask/src/plugins/PoolTogether/UI/PoolView.tsx index 54a94a62dd84..883d734b2ab1 100644 --- a/packages/mask/src/plugins/PoolTogether/UI/PoolView.tsx +++ b/packages/mask/src/plugins/PoolTogether/UI/PoolView.tsx @@ -2,7 +2,7 @@ import { first } from 'lodash-unified' import type { Pool } from '../types' import { Typography, Grid, CircularProgress, Button } from '@mui/material' import { makeStyles } from '@masknet/theme' -import { useChainId, useERC20TokenDetailed } from '@masknet/web3-shared-evm' +import { useAccount, useChainId, useERC20TokenDetailed } from '@masknet/web3-shared-evm' import { RefreshIcon } from '@masknet/icons' import { usePoolURL } from '../hooks/usePoolURL' import { CountdownView } from './CountdownView' @@ -13,6 +13,7 @@ import { NetworkView } from './NetworkView' import { useI18N } from '../../../utils' import { TokenIcon } from '@masknet/shared' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' +import { NetworkPluginID, useCurrentWeb3NetworkPluginID } from '@masknet/plugin-infra/web3' const useStyles = makeStyles()((theme) => ({ root: { @@ -172,6 +173,8 @@ export function PoolView(props: PoolProps) { const chainId = useChainId() const [prize, setPrize] = useState('TBD') const [period, setPeriod] = useState('Custom Period') + const currentPluginID = useCurrentWeb3NetworkPluginID() + const account = useAccount() // #region pool token const { @@ -261,9 +264,16 @@ export function PoolView(props: PoolProps) { /> - + {currentPluginID === NetworkPluginID.PLUGIN_EVM && account ? ( + + ) : null} diff --git a/packages/mask/src/plugins/PoolTogether/base.tsx b/packages/mask/src/plugins/PoolTogether/base.tsx index 0ffc2b3de710..948c07d5d994 100644 --- a/packages/mask/src/plugins/PoolTogether/base.tsx +++ b/packages/mask/src/plugins/PoolTogether/base.tsx @@ -3,7 +3,7 @@ import { POOLTOGETHER_PLUGIN_ID, URL_PATTERN } from './constants' export const base: Plugin.Shared.Definition = { ID: POOLTOGETHER_PLUGIN_ID, - name: { fallback: 'PoolTogether' }, + name: { fallback: 'Pooltogether' }, description: { fallback: 'PoolTogether is a protocol for no-loss prize games on the Ethereum blockchain' }, publisher: { name: { fallback: 'iRhonin' }, link: 'https://github.com/iRhonin' }, enableRequirement: { diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/OperationFooter.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/OperationFooter.tsx index 589980fe5af0..27f65dc82f39 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/OperationFooter.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/OperationFooter.tsx @@ -1,13 +1,16 @@ +import { SharedIcon, PluginWalletConnectIcon } from '@masknet/icons' import { WalletMessages } from '@masknet/plugin-wallet' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' -import { TransactionState, TransactionStateType, useAccount, useChainIdValid } from '@masknet/web3-shared-evm' -import { Box } from '@mui/material' +import { ChainId, TransactionState, TransactionStateType, useAccount, useChainIdValid } from '@masknet/web3-shared-evm' +import { Box, useTheme } from '@mui/material' import ActionButton from '../../../../extension/options-page/DashboardComponents/ActionButton' import { useI18N } from '../../../../utils' +import { EthereumChainBoundary } from '../../../../web3/UI/EthereumChainBoundary' import { EthereumWalletConnectedBoundary } from '../../../../web3/UI/EthereumWalletConnectedBoundary' import { useStyles } from './useStyles' interface OperationFooterProps { + chainId?: ChainId canClaim: boolean canRefund: boolean claimState: TransactionState @@ -16,6 +19,7 @@ interface OperationFooterProps { onClaimOrRefund: () => void | Promise } export function OperationFooter({ + chainId, canClaim, canRefund, claimState, @@ -27,6 +31,7 @@ export function OperationFooter({ const { t } = useI18N() const account = useAccount() const chainIdValid = useChainIdValid() + const theme = useTheme() // #region remote controlled select provider dialog const { openDialog: openSelectProviderDialog } = useRemoteControlledDialog( @@ -39,14 +44,14 @@ export function OperationFooter({ if (!account) { return ( - + {t('plugin_wallet_connect_a_wallet')} ) } if (!chainIdValid) { return ( - + {t('plugin_wallet_invalid_network')} ) @@ -57,11 +62,18 @@ export function OperationFooter({ return ( {canClaim ? claimState.type === TransactionStateType.HASH @@ -75,18 +87,37 @@ export function OperationFooter({ } return ( - - - {canRefund ? null : ( - - {t('share')} - - )} - - - + + + } + classes={{ + connectWallet: classes.connectWallet, + }}> + + {canRefund ? null : ( + } + variant="contained" + fullWidth + onClick={onShare}> + {t('share')} + + )} + + + + + ) } diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/index.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/index.tsx index bf01e18c4647..47361baad7e1 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/index.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/index.tsx @@ -3,25 +3,21 @@ import { useCallback, useEffect, useMemo } from 'react' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' import { Card, Typography } from '@mui/material' import { - ChainId, formatBalance, - getChainIdFromName, resolveNetworkName, TransactionStateType, useAccount, - useFungibleTokenDetailed, useNetworkType, useWeb3, useTokenConstants, - EthereumTokenType, - isSameAddress, + getChainIdFromName, + ChainId, } from '@masknet/web3-shared-evm' import { usePostLink } from '../../../../components/DataSource/usePostInfo' import { activatedSocialNetworkUI } from '../../../../social-network' import { isTwitter } from '../../../../social-network-adaptor/twitter.com/base' import { isFacebook } from '../../../../social-network-adaptor/facebook.com/base' import { useI18N } from '../../../../utils' -import { EthereumChainBoundary } from '../../../../web3/UI/EthereumChainBoundary' import { WalletMessages } from '../../../Wallet/messages' import type { RedPacketAvailability, RedPacketJSONPayload } from '../../types' import { RedPacketStatus } from '../../types' @@ -51,22 +47,12 @@ export function RedPacket(props: RedPacketProps) { value: availability, computed: availabilityComputed, retry: revalidateAvailability, - } = useAvailabilityComputed(account, payload) + } = useAvailabilityComputed(account ?? payload.contract_address, payload) const { NATIVE_TOKEN_ADDRESS } = useTokenConstants() - const { value: tokenDetailed } = useFungibleTokenDetailed( - payload.token?.type ?? - payload.token_type ?? - (isSameAddress(NATIVE_TOKEN_ADDRESS, payload.token_address) - ? EthereumTokenType.Native - : EthereumTokenType.ERC20), - payload.token?.address ?? payload.token_address ?? '', - ) - const token = - payload.token && ['chainId', 'decimal', 'symbol'].every((k) => Reflect.has(payload.token ?? {}, k)) - ? payload.token - : tokenDetailed + const token = payload.token + // #endregion const { canFetch, canClaim, canRefund, listOfStatus } = availabilityComputed @@ -180,17 +166,15 @@ export function RedPacket(props: RedPacketProps) { // the red packet can fetch without account if (!availability || !token) return ( - - - - {t('loading')} - - - + + + {t('loading')} + + ) return ( - + <>
{/* it might be fontSize: 12 on twitter based on theme? */} @@ -219,6 +203,7 @@ export function RedPacket(props: RedPacketProps) { {listOfStatus.includes(RedPacketStatus.empty) ? null : ( )} - + ) } diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/useStyles.ts b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/useStyles.ts index c1981af2d161..b05f09cec7e1 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/useStyles.ts +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacket/useStyles.ts @@ -24,6 +24,7 @@ to { padding: theme.spacing(1, 1.5), height: 202, }, + width: '100%', }, header: { display: 'flex', @@ -44,7 +45,6 @@ to { flexWrap: 'wrap', }, footer: { - paddingTop: theme.spacing(2), width: '100%', display: 'flex', gap: theme.spacing(2), diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNft.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNft.tsx index 30bd4ca1f3aa..7ed8a172141f 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNft.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNft.tsx @@ -23,10 +23,13 @@ import { isTwitter } from '../../../social-network-adaptor/twitter.com/base' import { isFacebook } from '../../../social-network-adaptor/facebook.com/base' import { NFTCardStyledAssetPlayer } from '@masknet/shared' import { openWindow } from '@masknet/shared-base-ui' +import { PluginWalletConnectIcon } from '@masknet/icons' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const useStyles = makeStyles()((theme) => ({ root: { position: 'relative', + width: '100%', }, actions: { paddingTop: theme.spacing(2), @@ -98,7 +101,7 @@ const useStyles = makeStyles()((theme) => ({ }, }, buttonWrapper: { - marginTop: 4, + marginTop: 0, }, loadingBox: { borderRadius: theme.spacing(1), @@ -432,23 +435,25 @@ export function RedPacketNft({ payload }: RedPacketNftProps) { {availability.isClaimed ? null : ( - - - {isClaiming ? t('plugin_red_packet_claiming') : t('plugin_red_packet_claim')} - - + + } + classes={{ + connectWallet: classes.button, + unlockMetaMask: classes.button, + gasFeeButton: classes.button, + }}> + + {isClaiming ? t('plugin_red_packet_claiming') : t('plugin_red_packet_claim')} + + + )} diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNftInPost.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNftInPost.tsx index 3183e6bc7213..4711aae40d63 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNftInPost.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedPacketNftInPost.tsx @@ -1,5 +1,4 @@ import { useEffect } from 'react' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { RedPacketRPC } from '../messages' import type { RedPacketNftJSONPayload } from '../types' import { RedPacketNft } from './RedPacketNft' @@ -17,9 +16,5 @@ export function RedPacketNftInPost({ payload }: RedPacketNftInPostProps) { contract_version: payload.contractVersion, }) }, [payload]) - return ( - - - - ) + return } diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedpacketNftConfirmDialog.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedpacketNftConfirmDialog.tsx index 882358c0816f..0a676a0f9a01 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedpacketNftConfirmDialog.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/RedpacketNftConfirmDialog.tsx @@ -108,7 +108,7 @@ const useStyles = makeStyles()((theme) => ({ textOverflow: 'ellipsis', }, buttonWrapper: { - marginTop: 16, + marginTop: 0, }, button: { minHeight: 36, diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailability.ts b/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailability.ts index 69e321ad3803..090137577199 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailability.ts +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useAvailability.ts @@ -1,16 +1,15 @@ import { useAsyncRetry } from 'react-use' -import { ChainId, useChainId } from '@masknet/web3-shared-evm' +import type { ChainId } from '@masknet/web3-shared-evm' import { useRedPacketContract } from './useRedPacketContract' export function useAvailability(version: number, from: string, id: string, redpacketChainId: ChainId) { - const redPacketContract = useRedPacketContract(version) - const currentChainId = useChainId() + const redPacketContract = useRedPacketContract(version, redpacketChainId) return useAsyncRetry(async () => { - if (!id || redpacketChainId !== currentChainId) return null + if (!id) return null if (!redPacketContract) return null return redPacketContract.methods.check_availability(id).call({ // check availability is ok w/o account from, }) - }, [id, from, redpacketChainId, currentChainId, redPacketContract]) + }, [id, from, redpacketChainId, redPacketContract]) } diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useRedPacketContract.ts b/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useRedPacketContract.ts index b4556452b883..2b0039114616 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useRedPacketContract.ts +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/hooks/useRedPacketContract.ts @@ -6,20 +6,20 @@ import type { HappyRedPacketV1 } from '@masknet/web3-contracts/types/HappyRedPac import type { HappyRedPacketV2 } from '@masknet/web3-contracts/types/HappyRedPacketV2' import type { HappyRedPacketV3 } from '@masknet/web3-contracts/types/HappyRedPacketV3' import type { HappyRedPacketV4 } from '@masknet/web3-contracts/types/HappyRedPacketV4' -import { useContract, useRedPacketConstants } from '@masknet/web3-shared-evm' +import { useContract, useRedPacketConstants, ChainId } from '@masknet/web3-shared-evm' import type { AbiItem } from 'web3-utils' -export function useRedPacketContract(version: number) { +export function useRedPacketContract(version: number, chainId?: ChainId) { const { HAPPY_RED_PACKET_ADDRESS_V1: addressV1, HAPPY_RED_PACKET_ADDRESS_V2: addressV2, HAPPY_RED_PACKET_ADDRESS_V3: addressV3, HAPPY_RED_PACKET_ADDRESS_V4: addressV4, - } = useRedPacketConstants() - const v1 = useContract(addressV1, HappyRedPacketV1ABI as AbiItem[]) - const v2 = useContract(addressV2, HappyRedPacketV2ABI as AbiItem[]) - const v3 = useContract(addressV3, HappyRedPacketV3ABI as AbiItem[]) - const v4 = useContract(addressV4, HappyRedPacketV4ABI as AbiItem[]) + } = useRedPacketConstants(chainId) + const v1 = useContract(addressV1, HappyRedPacketV1ABI as AbiItem[], chainId) + const v2 = useContract(addressV2, HappyRedPacketV2ABI as AbiItem[], chainId) + const v3 = useContract(addressV3, HappyRedPacketV3ABI as AbiItem[], chainId) + const v4 = useContract(addressV4, HappyRedPacketV4ABI as AbiItem[], chainId) const versions = [v1, v2, v3, v4] as const return versions[version - 1] } diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx index 845a1cfb01f1..f56ca1eb9aec 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx @@ -133,6 +133,15 @@ const sns: Plugin.SNSAdaptor.Definition = { } })(), ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(249, 55, 55, 0.2) 100%), #FFFFFF', + }, } interface ERC20RedpacketBadgeProps { payload: RedPacketJSONPayload diff --git a/packages/mask/src/plugins/RedPacket/base.ts b/packages/mask/src/plugins/RedPacket/base.ts index 42cc70a2d840..017b71a9a04b 100644 --- a/packages/mask/src/plugins/RedPacket/base.ts +++ b/packages/mask/src/plugins/RedPacket/base.ts @@ -1,11 +1,9 @@ -import { NetworkPluginID } from '@masknet/plugin-infra/web3' import type { Plugin } from '@masknet/plugin-infra' -import { ChainId } from '@masknet/web3-shared-evm' import { RedPacketMetaKey, RedPacketNftMetaKey, RedPacketPluginID } from './constants' export const base: Plugin.Shared.Definition = { ID: RedPacketPluginID, - name: { fallback: 'Lucky drop' }, + name: { fallback: 'Lucky Drop' }, description: { fallback: 'Lucky drop is a special feature in Mask Network which was launched in early 2020. Once users have installed the Chrome/Firefox plugin, they can claim and give out cryptocurrencies on Twitter.', @@ -18,24 +16,6 @@ export const base: Plugin.Shared.Definition = { networks: {}, }, target: 'stable', - web3: { - [NetworkPluginID.PLUGIN_EVM]: { - supportedChainIds: [ - ChainId.Mainnet, - ChainId.BSC, - ChainId.Matic, - ChainId.Arbitrum, - ChainId.xDai, - ChainId.Fantom, - ChainId.Avalanche, - ChainId.Aurora, - ChainId.Harmony, - ChainId.Conflux, - ], - }, - [NetworkPluginID.PLUGIN_FLOW]: { supportedChainIds: [] }, - [NetworkPluginID.PLUGIN_SOLANA]: { supportedChainIds: [] }, - }, }, contribution: { metadataKeys: new Set([RedPacketMetaKey, RedPacketNftMetaKey]), diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/LoadingFailCard.tsx b/packages/mask/src/plugins/Snapshot/SNSAdaptor/LoadingFailCard.tsx index fdb45c198733..f9ad3e55f307 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/LoadingFailCard.tsx +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/LoadingFailCard.tsx @@ -1,6 +1,6 @@ import { Component, PropsWithChildren } from 'react' import { SnapshotCard } from './SnapshotCard' -import { Typography, Button } from '@mui/material' +import { Typography, Button, Box } from '@mui/material' export class LoadingFailCard extends Component< PropsWithChildren<{ title: string; retry: () => void; isFullPluginDown?: boolean }> @@ -12,24 +12,35 @@ export class LoadingFailCard extends Component< override render() { if (this.state.error) { return this.props.isFullPluginDown ? ( - <> - Loading fails due to Snapshot API service breakdown. + + + Loading fails due to Snapshot API service breakdown. + - + ) : ( Loading fails due to Snapshot API service breakdown. - ))} - - - + {account && networkPluginId === NetworkPluginID.PLUGIN_EVM ? ( + <> + {choices.map((choiceText, i) => ( + + ))} + + + + ) : null} , }, ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(255, 159, 10, 0.2) 100%), #FFFFFF;', + }, } export default sns diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx index ec738c3ac367..2594adcb01a4 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx @@ -51,6 +51,15 @@ const sns: Plugin.SNSAdaptor.Definition = { } })(), ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(254, 156, 0, 0.2) 100%), #FFFFFF;', + }, } export default sns diff --git a/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx b/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx index 0721071fbcbd..61354024815c 100644 --- a/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx @@ -56,6 +56,15 @@ const sns: Plugin.SNSAdaptor.Definition = { tutorialLink: 'https://realmasknetwork.notion.site/fb00ff2e626949279c83b59ed9207b9a', }, ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(0, 150, 202, 0.2) 100%), #FFFFFF;', + }, } export default sns diff --git a/packages/mask/src/plugins/dHEDGE/UI/PoolView.tsx b/packages/mask/src/plugins/dHEDGE/UI/PoolView.tsx index b134d31ee75d..158285d2c292 100644 --- a/packages/mask/src/plugins/dHEDGE/UI/PoolView.tsx +++ b/packages/mask/src/plugins/dHEDGE/UI/PoolView.tsx @@ -1,14 +1,14 @@ import { RefreshIcon } from '@masknet/icons' import { useChainId } from '@masknet/web3-shared-evm' -import { Card, CardContent, CardHeader, Paper, Tab, Tabs, Typography } from '@mui/material' +import { Box, Card, CardContent, CardHeader, CircularProgress, Paper, Tab, Tabs, Typography } from '@mui/material' import { makeStyles } from '@masknet/theme' import { useState } from 'react' import { useI18N } from '../../../utils/i18n-next-ui' -import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { useFetchPool, usePoolDepositAssets } from '../hooks/usePool' import { PerformanceChart } from './PerformanceChart' import { PoolStats } from './PoolStats' import { PoolViewDeck } from './PoolViewDeck' +import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' const useStyles = makeStyles()((theme) => ({ root: { @@ -86,8 +86,8 @@ export function PoolView(props: PoolViewProps) { if (loading || loadingAllowedTokens) return ( - - {t('plugin_dhedge_loading')} + + ) if (!pool) @@ -108,7 +108,7 @@ export function PoolView(props: PoolViewProps) { ) return ( - + <> } /> @@ -132,6 +132,9 @@ export function PoolView(props: PoolViewProps) { - + + + + ) } diff --git a/packages/mask/src/plugins/dHEDGE/UI/PoolViewDeck.tsx b/packages/mask/src/plugins/dHEDGE/UI/PoolViewDeck.tsx index 9e58bebd5911..8274f0abb469 100644 --- a/packages/mask/src/plugins/dHEDGE/UI/PoolViewDeck.tsx +++ b/packages/mask/src/plugins/dHEDGE/UI/PoolViewDeck.tsx @@ -1,4 +1,4 @@ -import { resolveAddressLinkOnExplorer, useChainId } from '@masknet/web3-shared-evm' +import { resolveAddressLinkOnExplorer, useAccount, useChainId } from '@masknet/web3-shared-evm' import { Avatar, Button, Grid, Link, Typography } from '@mui/material' import { makeStyles } from '@masknet/theme' import BigNumber from 'bignumber.js' @@ -65,6 +65,7 @@ export function PoolViewDeck(props: PoolDeckProps) { const blockie = useAvatar(pool.managerAddress) const chainId = useChainId() + const account = useAccount() // #region manager share const managerShare = new BigNumber(pool.balanceOfManager) @@ -138,9 +139,11 @@ export function PoolViewDeck(props: PoolDeckProps) { - + {account && pool.chainId === chainId ? ( + + ) : null} ) diff --git a/packages/mask/src/utils/hooks/useSettingSwitcher.tsx b/packages/mask/src/utils/hooks/useSettingSwitcher.tsx index d804a8105252..c109ca983fdc 100644 --- a/packages/mask/src/utils/hooks/useSettingSwitcher.tsx +++ b/packages/mask/src/utils/hooks/useSettingSwitcher.tsx @@ -2,6 +2,7 @@ import { useMemo, useCallback } from 'react' import { useValueRef } from '@masknet/shared-base-ui' import ActionButton from '../../extension/options-page/DashboardComponents/ActionButton' import type { InternalSettings } from '../../settings/createSettings' +import { useTheme } from '@mui/material' export function useSettingsSwitcher>( settings: S, @@ -36,7 +37,9 @@ export function useSwitcher( onSwitch: (option: T) => void, options: T[], resolver: (option: T) => string, + fullWidth?: boolean, ) { + const theme = useTheme() const nextOption = useMemo(() => { if (options.length === 0) return if (typeof currentOption === 'undefined') return options[0] @@ -50,7 +53,18 @@ export function useSwitcher( if (typeof nextOption === 'undefined') return null return ( - onSwitch(nextOption)}> + onSwitch(nextOption)}> Switch to {resolver(nextOption)} ) diff --git a/packages/mask/src/web3/UI/EthereumChainBoundary.tsx b/packages/mask/src/web3/UI/EthereumChainBoundary.tsx index 0fd96c4c8388..5eaaa17c574c 100644 --- a/packages/mask/src/web3/UI/EthereumChainBoundary.tsx +++ b/packages/mask/src/web3/UI/EthereumChainBoundary.tsx @@ -1,16 +1,20 @@ import React, { useCallback } from 'react' -import { Box, Typography, Theme } from '@mui/material' -import { makeStyles, useStylesExtends } from '@masknet/theme' +import { Box, Typography, Theme, useTheme } from '@mui/material' +import { makeStyles, MaskColorVar, ShadowRootTooltip, useStylesExtends } from '@masknet/theme' import type { SxProps } from '@mui/system' import { useActivatedPlugin } from '@masknet/plugin-infra/dom' -import { NetworkPluginID, useCurrentWeb3NetworkPluginID, useAccount } from '@masknet/plugin-infra/web3' +import { + NetworkPluginID, + useCurrentWeb3NetworkPluginID, + useAccount, + useNetworkDescriptor, +} from '@masknet/plugin-infra/web3' import { ChainId, getChainDetailedCAIP, getChainName, getNetworkTypeFromChainId, isChainIdValid, - isValidAddress as isValidEthereumAddress, NetworkType, ProviderType, resolveNetworkName, @@ -27,9 +31,32 @@ import { currentProviderSettings } from '../../plugins/Wallet/settings' import { useI18N } from '../../utils' import { WalletMessages, WalletRPC } from '../../plugins/Wallet/messages' import Services from '../../extension/service' -import { pluginIDSettings } from '../../settings/settings' +import { WalletIcon } from '@masknet/shared' +import { PluginWalletConnectIcon } from '@masknet/icons' -const useStyles = makeStyles()(() => ({})) +const useStyles = makeStyles()((theme) => ({ + button: { + backgroundColor: theme.palette.maskColor.dark, + color: 'white', + width: 254, + '&,&:hover': { + background: theme.palette.maskColor.dark, + }, + }, + action: { + textAlign: 'center', + margin: theme.spacing(1), + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + marginBottom: 48, + }, + tooltip: { + borderRadius: 4, + padding: 10, + }, +})) export interface EthereumChainBoundaryProps extends withClasses<'switchButton'> { className?: string @@ -45,16 +72,18 @@ export interface EthereumChainBoundaryProps extends withClasses<'switchButton'> export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { const { t } = useI18N() + const theme = useTheme() const pluginID = useCurrentWeb3NetworkPluginID() const plugin = useActivatedPlugin(pluginID, 'any') const account = useAccount() const chainId = useChainId() + const allowTestnet = useAllowTestnet() const providerType = useValueRef(currentProviderSettings) - const { noSwitchNetworkTip = false } = props + const { noSwitchNetworkTip = true } = props const classes = useStylesExtends(useStyles(), props) const expectedChainId = props.chainId const expectedNetwork = getChainName(expectedChainId) @@ -80,12 +109,7 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { WalletMessages.events.selectProviderDialogUpdated, ) - // #region connect wallet dialog - const { setDialog: setConnectWalletDialog } = useRemoteControlledDialog( - WalletMessages.events.connectWalletDialogUpdated, - ) - // #endregion - + const networkDescriptor = useNetworkDescriptor(expectedChainId, NetworkPluginID.PLUGIN_EVM) // request ethereum-compatible network const networkType = getNetworkTypeFromChainId(expectedChainId) @@ -134,41 +158,54 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { } } - const switchToPlugin = async () => { - pluginIDSettings.value = NetworkPluginID.PLUGIN_EVM + if (providerType === ProviderType.WalletConnect && networkType) { + openSelectProviderDialog() + return } - if (!isChainMatched) await switchToChain() if (!isPluginMatched) { - await switchToPlugin() - if (!networkType || networkType !== NetworkType.Ethereum || isValidEthereumAddress(account)) return - setConnectWalletDialog({ - open: true, - providerType: ProviderType.MetaMask, - networkType, - }) + openSelectProviderDialog() + return } + if (!isChainMatched) await switchToChain() }, [account, isAllowed, isChainMatched, isPluginMatched, providerType, expectedChainId]) - const renderBox = (children?: React.ReactNode) => { + const renderBox = (children?: React.ReactNode, tips?: string) => { return ( - - {children} - + + + {children} + + ) } if (!account) return renderBox( <> - - {t('plugin_wallet_connect_wallet_tip')} - {!props.hiddenConnectButton ? ( + startIcon={} + variant="contained" + size={props.ActionButtonPromiseProps?.size} + sx={{ + backgroundColor: theme.palette.maskColor.dark, + width: '100%', + color: 'white', + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, + margin: 0, + lineHeight: 0, + paddingTop: 1.25, + paddingBottom: 1.25, + }} + onClick={openSelectProviderDialog}> {t('plugin_wallet_connect_wallet')} ) : null} @@ -179,7 +216,7 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { if (!isAllowed) return renderBox( - + {t('plugin_wallet_not_available_on', { network: actualNetwork, @@ -192,7 +229,7 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { return renderBox( <> {!noSwitchNetworkTip ? ( - + {t('plugin_wallet_not_available_on', { network: plugin?.name?.fallback ?? 'Unknown Plugin', @@ -203,19 +240,37 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { {isAllowed ? ( + } + sx={ + props.switchButtonStyle ?? { + backgroundColor: theme.palette.maskColor.dark, + width: '100%', + color: 'white', + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, + padding: 1, + margin: 0, + } + } + style={{ borderRadius: 10 }} init={ - {t('plugin_wallet_switch_network', { - network: expectedNetwork, + {t('plugin_wallet_connect_network', { + network: 'EVM', })} } - waiting={t('plugin_wallet_switch_network_under_going', { - network: expectedNetwork, + waiting={t('plugin_wallet_connect_network_under_going', { + network: 'EVM', })} - complete={t('plugin_wallet_switch_network', { - network: expectedNetwork, + complete={t('plugin_wallet_connect_network', { + network: 'EVM', })} failed={t('retry')} executor={onSwitchChain} @@ -231,7 +286,7 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { return renderBox( <> {!noSwitchNetworkTip ? ( - + {t('plugin_wallet_not_available_on', { network: actualNetwork, @@ -241,21 +296,35 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { ) : null} {isAllowed ? ( + } + sx={ + props.switchButtonStyle ?? { + backgroundColor: theme.palette.maskColor.dark, + width: '100%', + color: 'white', + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, + padding: 1, + margin: 0, + } + } + style={{ borderRadius: 10, paddingTop: 11, paddingBottom: 11 }} init={ - {t('plugin_wallet_switch_network', { - network: expectedNetwork, - })} + {t('plugin_wallet_switch_network', { network: expectedNetwork.replace('Mainnet', '') })} } waiting={t('plugin_wallet_switch_network_under_going', { - network: expectedNetwork, - })} - complete={t('plugin_wallet_switch_network', { - network: expectedNetwork, + network: expectedNetwork.replace('Mainnet', ''), })} + complete={t('plugin_wallet_switch_network', { network: expectedNetwork.replace('Mainnet', '') })} failed={t('retry')} executor={onSwitchChain} completeOnClick={onSwitchChain} @@ -264,5 +333,6 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { /> ) : null} , + providerType === ProviderType.WalletConnect ? t('plugin_wallet_connect_tips') : '', ) } diff --git a/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx b/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx index 2eb116847743..1f5a08c3e18d 100644 --- a/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx +++ b/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx @@ -1,4 +1,3 @@ -import { Grid } from '@mui/material' import { makeStyles, useStylesExtends } from '@masknet/theme' import classNames from 'classnames' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' @@ -11,7 +10,19 @@ import { useWalletRiskWarningDialog } from '../../plugins/Wallet/hooks/useWallet const useStyles = makeStyles()((theme) => ({ button: { - marginTop: theme.spacing(1.5), + backgroundColor: theme.palette.maskColor.dark, + color: 'white', + fontSize: 14, + fontWeight: 700, + width: '100%', + '&:hover': { + backgroundColor: theme.palette.maskColor.dark, + }, + margin: 0, + }, + grid: { + justifyContent: 'center', + padding: 8, }, })) @@ -21,6 +32,7 @@ export interface EthereumWalletConnectedBoundaryProps children?: React.ReactNode hideRiskWarningConfirmed?: boolean ActionButtonProps?: ActionButtonProps + startIcon?: React.ReactNode } export function EthereumWalletConnectedBoundary(props: EthereumWalletConnectedBoundaryProps) { @@ -45,64 +57,53 @@ export function EthereumWalletConnectedBoundary(props: EthereumWalletConnectedBo if (!account) return ( - - - {t('plugin_wallet_connect_a_wallet')} - - + + {t('plugin_wallet_connect_a_wallet')} + ) if (!isRiskWarningConfirmed && !hideRiskWarningConfirmed) return ( - - - {t('plugin_wallet_confirm_risk_warning')} - - + + {t('plugin_wallet_confirm_risk_warning')} + ) if (isZero(nativeTokenBalance.value ?? '0') && !offChain) return ( - - - {t(nativeTokenBalance.loading ? 'plugin_wallet_update_gas_fee' : 'plugin_wallet_no_gas_fee')} - - + + {t(nativeTokenBalance.loading ? 'plugin_wallet_update_gas_fee' : 'plugin_wallet_no_gas_fee')} + ) if (!chainIdValid && !offChain) return ( - - - {t('plugin_wallet_invalid_network')} - - + + {t('plugin_wallet_invalid_network')} + ) - return {children} + return <>{children} } diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 99697cefb7ed..6c2f87585320 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -244,6 +244,8 @@ export namespace Plugin.SNSAdaptor { ProfileSliders?: ProfileSlider[] /** This UI will be rendered as tabs on the profile page */ ProfileTabs?: ProfileTab[] + /** This UI will be rendered as plugin wrapper page */ + wrapperProps?: PluginWrapperProps /** * A hook for if this plugin can enhance the #hash or $cash tag. */ @@ -350,6 +352,12 @@ export namespace Plugin.SNSAdaptor { } } + export interface PluginWrapperProps { + icon?: React.ReactNode + title?: string + backgroundGradient?: string + } + export interface ProfileIdentity { avatar?: string bio?: string diff --git a/packages/plugins/CrossChainBridge/src/base.ts b/packages/plugins/CrossChainBridge/src/base.ts index 790a217a8f6e..7625b7388e5b 100644 --- a/packages/plugins/CrossChainBridge/src/base.ts +++ b/packages/plugins/CrossChainBridge/src/base.ts @@ -6,7 +6,7 @@ export const base: Plugin.Shared.Definition = { ID: PLUGIN_ID, name: { fallback: PLUGIN_NAME }, description: { fallback: PLUGIN_DESCRIPTION }, - publisher: { name: { fallback: '' }, link: '' }, + publisher: { name: { fallback: 'Mask Network' }, link: 'https://mask.io/' }, enableRequirement: { architecture: { app: false, web: true }, networks: { type: 'opt-out', networks: {} }, diff --git a/packages/plugins/CyberConnect/src/SNSAdaptor/FollowTab.tsx b/packages/plugins/CyberConnect/src/SNSAdaptor/FollowTab.tsx index df9a9ff21a91..ea74e6be060d 100644 --- a/packages/plugins/CyberConnect/src/SNSAdaptor/FollowTab.tsx +++ b/packages/plugins/CyberConnect/src/SNSAdaptor/FollowTab.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { Typography } from '@mui/material' -import { makeStyles, MaskColorVar } from '@masknet/theme' +import { makeStyles } from '@masknet/theme' import Box from '@mui/material/Box' import Tab from '@mui/material/Tab' import TabContext from '@mui/lab/TabContext' @@ -62,18 +62,18 @@ export default function FollowTab({ {followingList.map((f: IFollowIdentity) => { @@ -98,7 +98,7 @@ export default function FollowTab({ className={classes.tabPanel} value="2" sx={{ - color: MaskColorVar.cyberconnectPrimary, + color: 'black', width: '100%', }}> {followerList.map((f: IFollowIdentity) => { diff --git a/packages/plugins/CyberConnect/src/SNSAdaptor/Profile.tsx b/packages/plugins/CyberConnect/src/SNSAdaptor/Profile.tsx index 5cd00e93d46a..f5e6a3711b5e 100644 --- a/packages/plugins/CyberConnect/src/SNSAdaptor/Profile.tsx +++ b/packages/plugins/CyberConnect/src/SNSAdaptor/Profile.tsx @@ -38,9 +38,9 @@ const useStyles = makeStyles()((theme) => ({ textAlign: 'center', wordBreak: 'break-word', marginTop: '20px', - color: MaskColorVar.textPrimary, + color: 'black', }, - address: { marginTop: '20px', opacity: 0.6, color: MaskColorVar.textPrimary }, + address: { marginTop: '20px', opacity: 0.6, color: 'black' }, socialMedia: { width: '100%', display: 'flex', diff --git a/packages/plugins/CyberConnect/src/SNSAdaptor/index.tsx b/packages/plugins/CyberConnect/src/SNSAdaptor/index.tsx index 16730db08508..49eb7d2d0a9a 100644 --- a/packages/plugins/CyberConnect/src/SNSAdaptor/index.tsx +++ b/packages/plugins/CyberConnect/src/SNSAdaptor/index.tsx @@ -44,6 +44,15 @@ const sns: Plugin.SNSAdaptor.Definition = { tutorialLink: 'https://cyberconnect.me/', }, ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(45, 41, 253, 0.2) 100%), #FFFFFF;', + }, } export default sns diff --git a/packages/plugins/CyberConnect/src/base.tsx b/packages/plugins/CyberConnect/src/base.tsx index 1d133b171379..83a0be124b1d 100644 --- a/packages/plugins/CyberConnect/src/base.tsx +++ b/packages/plugins/CyberConnect/src/base.tsx @@ -1,6 +1,4 @@ import type { Plugin } from '@masknet/plugin-infra' -import { NetworkPluginID } from '@masknet/plugin-infra/web3' -import { ChainId } from '@masknet/web3-shared-evm' import { CYBERCONNECT_PLUGIN_ID } from './constants' export const base: Plugin.Shared.Definition = { @@ -14,17 +12,6 @@ export const base: Plugin.Shared.Definition = { architecture: { app: false, web: true }, networks: { type: 'opt-out', networks: {} }, target: 'stable', - web3: { - [NetworkPluginID.PLUGIN_EVM]: { - supportedChainIds: [ChainId.Mainnet, ChainId.BSC, ChainId.Matic, ChainId.Arbitrum, ChainId.xDai], - }, - [NetworkPluginID.PLUGIN_SOLANA]: { - supportedChainIds: [], - }, - [NetworkPluginID.PLUGIN_FLOW]: { - supportedChainIds: [], - }, - }, }, contribution: { postContent: new Set([/https:\/\/app.cyberconnect.me/]) }, } diff --git a/packages/plugins/FileService/src/SNSAdaptor/index.tsx b/packages/plugins/FileService/src/SNSAdaptor/index.tsx index 2170634bb605..94d5a656f151 100644 --- a/packages/plugins/FileService/src/SNSAdaptor/index.tsx +++ b/packages/plugins/FileService/src/SNSAdaptor/index.tsx @@ -71,6 +71,15 @@ const definition: Plugin.SNSAdaptor.Definition = { } })(), ], + wrapperProps: { + icon: ( + + ), + backgroundGradient: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(255, 177, 16, 0.2) 100%), #FFFFFF;', + }, } export default definition diff --git a/packages/theme/src/CSSVariables/constants.ts b/packages/theme/src/CSSVariables/constants.ts index 8c6025ff1db5..48d83bcda028 100644 --- a/packages/theme/src/CSSVariables/constants.ts +++ b/packages/theme/src/CSSVariables/constants.ts @@ -70,6 +70,10 @@ export const LightColor = { tooltipBackground: '#ffffff', warningBackground: 'rgba(255, 185, 21, 0.1)', cyberconnectPrimary: '#000000', + errorPlugin: '#FF3545', + buttonPluginBackground: '#07101B', + textPluginColor: '#07101B', + buttonPluginColor: '#FFFFFF', } export const DarkColor: typeof LightColor = { primary: '#1c68f3', @@ -145,5 +149,9 @@ export const DarkColor: typeof LightColor = { tooltipBackground: '#1A1D20', warningBackground: 'rgba(255, 185, 21, 0.1)', cyberconnectPrimary: '#ffffff', + errorPlugin: '#FF3545', + buttonPluginBackground: '#07101B', + textPluginColor: '#07101B', + buttonPluginColor: '#FFFFFF', } export type Color = typeof LightColor diff --git a/packages/web3-providers/src/opensea/index.ts b/packages/web3-providers/src/opensea/index.ts index 6e1bfb50ebe3..1cd048fd2ed6 100644 --- a/packages/web3-providers/src/opensea/index.ts +++ b/packages/web3-providers/src/opensea/index.ts @@ -79,7 +79,7 @@ function createERC721TokenFromAsset( { name: asset.collection.name, image: asset.collection.image_url || undefined, - slug: asset.collection.slug, + slug: asset.collection.slug ?? '', }, ) } diff --git a/packages/web3-shared/evm/contracts/useBalanceChecker.ts b/packages/web3-shared/evm/contracts/useBalanceChecker.ts index 1429800c8caf..91c4059b9dff 100644 --- a/packages/web3-shared/evm/contracts/useBalanceChecker.ts +++ b/packages/web3-shared/evm/contracts/useBalanceChecker.ts @@ -7,5 +7,5 @@ import type { ChainId } from '../types' export function useBalanceCheckerContract(chainId?: ChainId) { const { BALANCE_CHECKER_ADDRESS } = useEthereumConstants(chainId) - return useContract(BALANCE_CHECKER_ADDRESS, BalanceCheckerABI as AbiItem[]) + return useContract(BALANCE_CHECKER_ADDRESS, BalanceCheckerABI as AbiItem[], chainId) } diff --git a/packages/web3-shared/evm/contracts/useMulticallContract.ts b/packages/web3-shared/evm/contracts/useMulticallContract.ts index 47b20e9aa883..220e18523c7e 100644 --- a/packages/web3-shared/evm/contracts/useMulticallContract.ts +++ b/packages/web3-shared/evm/contracts/useMulticallContract.ts @@ -7,5 +7,5 @@ import type { ChainId } from '../types' export function useMulticallContract(chainId?: ChainId) { const { MULTICALL_ADDRESS } = useEthereumConstants(chainId) - return useContract(MULTICALL_ADDRESS, MulticallABI as AbiItem[]) + return useContract(MULTICALL_ADDRESS, MulticallABI as AbiItem[], chainId) } diff --git a/packages/web3-shared/evm/contracts/useWrappedEtherContract.ts b/packages/web3-shared/evm/contracts/useWrappedEtherContract.ts index 65fee1ab9e59..9e2f33d8b58f 100644 --- a/packages/web3-shared/evm/contracts/useWrappedEtherContract.ts +++ b/packages/web3-shared/evm/contracts/useWrappedEtherContract.ts @@ -7,5 +7,5 @@ import type { ChainId } from '../types' export function useNativeTokenWrapperContract(chainId?: ChainId) { const { WNATIVE_ADDRESS } = useTokenConstants(chainId) - return useContract(WNATIVE_ADDRESS, WETH_ABI as AbiItem[]) + return useContract(WNATIVE_ADDRESS, WETH_ABI as AbiItem[], chainId) } diff --git a/packages/web3-shared/evm/hooks/useFungibleTokenDetailed.ts b/packages/web3-shared/evm/hooks/useFungibleTokenDetailed.ts index 005f17304a3d..38211d089312 100644 --- a/packages/web3-shared/evm/hooks/useFungibleTokenDetailed.ts +++ b/packages/web3-shared/evm/hooks/useFungibleTokenDetailed.ts @@ -1,6 +1,6 @@ import type { AsyncStateRetry } from 'react-use/lib/useAsyncRetry' import { unreachable } from '@dimensiondev/kit' -import { ERC20TokenDetailed, EthereumTokenDetailedType, EthereumTokenType } from '../types' +import { ChainId, ERC20TokenDetailed, EthereumTokenDetailedType, EthereumTokenType } from '../types' import { useERC20TokenDetailed } from './useERC20TokenDetailed' import { useNativeTokenDetailed } from './useNativeTokenDetailed' @@ -10,11 +10,13 @@ export function useFungibleTokenDetailed< type: EthereumTokenType.ERC20 | EthereumTokenType.Native, address: string, token?: Partial

, + chainId?: ChainId, ): AsyncStateRetry

{ const r1 = useNativeTokenDetailed() const r2 = useERC20TokenDetailed( type === EthereumTokenType.ERC20 ? address : '', token as unknown as ERC20TokenDetailed, + chainId, ) switch (type) { case EthereumTokenType.Native: From ffeb9b078a3d63c16dbe03237cf34bd95f6545a7 Mon Sep 17 00:00:00 2001 From: lelenei <72531217+lelenei@users.noreply.github.com> Date: Wed, 18 May 2022 01:45:16 +0800 Subject: [PATCH 8/9] feat: nft avatar (#6079) * feat: nft avatar * feat: upload avatar image * feat: update twitter avatar * feat: move code * fix: remove unused code * fix: import error * refactor: code style * fix: typo * fix: can't read wallet address * feat: use wizard page mode * fix: typo * fix: userid lowercase * feat: add badge for persona avatar * fix: add rainbow at avatar * fix: remove unused code * feat: selcted token * fix: icons * fix: button status * fix: save button status * fix: save button status * fix: when user has no avatar, can't open nft list page * fix: save button status * fix: show rainbow * feat: use nextID strorage * refactor: remove console.log * feat: save avatar to nextid storage * fix: wallet sign * feat: useI18N * fix: reply review * fix: typo * fix: use generateSignResult sign * fix: get nickname * fix: nextid kv storage * fix: use context * fix: reply review * fix: wallet background * feat: new nft list page for polygon * refactor: remove unused code * fix: login user * feat: application board tooltip * fix: style * fix: useI18N * refactor: code style * fix: icon color * fix: wallet icon * fix: css style * fix: css style * fix: open nft pfp dialog from edit profile * fix: cspell * fix: need popup for sign * fix: tranlate component * fix: nextid sign * fix: sign flow * fix: css style * fix: wallet connect dialog * fix: get current persona from nextid * fix: save nft avatar meta * fix: kv storage * chore: temp * chore: disable tips entry as no nextId * chore: remove useless interface * chore: handle sns persona unmatched * chore: rename * fix: little fix * chore: little fix * fix: code style * chore: icon * fix: reply review * fix: reply review * fix: reply review * fix(twitter): renmove unused code * fix: css style * chore: hide entry on unsupported sns * fix: can't show avatar plugin * fix: nft pfp button at profile page * fix: update avatar * fix: css style * fix: get nft at polygon * fix: css style * fix: css style * fix: profile icon * fix: save nft error * chore: translate * fix: css style * fix: connect wallet * fix: typo * fix: recovery code * fix: recovery code * fix: pnpm-lock * fix: revert pnpm-lock * fix: revert pnpm-lock * fix: lockfile * fix: css style * fix: typo * fix: get nft from opensea * fix: have nft avatar * fix: css style * fix: css style * fix: css style * fix: add nft dialog * fix: code style * fix: css style * fix: remove nft avatar selector * fix: css style * fix: css style * fix: css style * fix: css style * fix: css style * fix: navigate to connect wallet when params has internal * fix: adjust facebook profile edit dom selector * fix: css style * fix: css style * fix: chain link address * fix: scollbar style * fix: find avatar meta from next id by avatarid * fix: list persona * fix: show local persona * fix: filter user * fix: name * fix: css style * fix: ploygon contract * fix: opensea link for polygon * fix: check owner * fix: get nft from polygon * fix: revert code * fix: reply review * fix: typo * fix: typo * fix: revert code * fix: connect / create persona * refactor: remove unused code * fix: filter non-twitter user * fix: verifed persona * fix: remove non-evm wallet * fix: scroll page * fix: verified user token * fix: css style * fix: css style * fix: css style * chore: add recommend area * chore: style * chore: add shadow color * chore: style * fix: application tips * chore: tooltip hint postion * chore: style * chore: style * fix: reply review * fix: build error * fix: add loading * fix: remove console.log * fix: reply review * chore: add disabled * fix: reply review * fix: typo * fix: disabled * fix: reply review * fix: remove unused word Co-authored-by: zhouhanseng Co-authored-by: unclebill Co-authored-by: nuanyang233 --- .i18n-codegen.json | 12 + cspell.json | 3 +- packages/icons/plugins/NFTAvatar.tsx | 29 ++ packages/icons/plugins/index.ts | 1 + packages/mask/package.json | 2 + packages/mask/shared-ui/locales/en-US.json | 14 +- packages/mask/shared-ui/locales/ko-KR.json | 1 - packages/mask/shared-ui/locales/qya-AA.json | 3 - packages/mask/shared-ui/locales/zh-CN.json | 1 - .../components/shared/ApplicationBoard.tsx | 22 +- .../shared/ApplicationSettingPluginList.tsx | 11 +- .../pages/Personas/ConnectedWallets/index.tsx | 10 + .../plugins/Avatar/Application/NFTAvatar.tsx | 46 +++ .../Avatar/Application/NFTAvatarsDialog.tsx | 106 ++++++ .../plugins/Avatar/Application/NFTInfo.tsx | 65 ++++ .../plugins/Avatar/Application/NFTList.tsx | 103 ++++++ .../Avatar/Application/NFTListDialog.tsx | 279 +++++++++++++++ .../Avatar/Application/NFTListPage.tsx | 118 +++++++ .../Avatar/Application/PersonaItem.tsx | 94 +++++ .../Avatar/Application/PersonaPage.tsx | 107 ++++++ .../Avatar/Application/UploadAvatarDialog.tsx | 202 +++++++++++ .../Avatar/Application/WalletConnect.tsx | 114 ++++++ .../plugins/Avatar/Application/WalletList.tsx | 331 ++++++++++++++++++ .../src/plugins/Avatar/SNSAdaptor/AddNFT.tsx | 56 ++- .../Avatar/SNSAdaptor/NFTAvatarButton.tsx | 17 +- .../plugins/Avatar/SNSAdaptor/NFTBadge.tsx | 6 +- .../Avatar/SNSAdaptor/NFTBadgeTimeline.tsx | 4 +- .../plugins/Avatar/SNSAdaptor/NFTImage.tsx | 20 +- .../Avatar/SNSAdaptor/background/amount.png | Bin 1246 -> 0 bytes .../Avatar/SNSAdaptor/background/noamount.png | Bin 1128 -> 0 bytes .../Avatar/SNSAdaptor/background/noname.png | Bin 1075 -> 0 bytes .../src/plugins/Avatar/SNSAdaptor/index.tsx | 51 ++- .../src/plugins/Avatar/assets/Verify2.tsx | 19 + .../src/plugins/Avatar/assets/application.tsx | 63 ++++ .../src/plugins/Avatar/assets/checked.tsx | 25 ++ .../mask/src/plugins/Avatar/assets/close.tsx | 12 + .../mask/src/plugins/Avatar/assets/copy.tsx | 20 ++ .../mask/src/plugins/Avatar/assets/frame.tsx | 44 +++ .../mask/src/plugins/Avatar/assets/info.tsx | 26 ++ .../mask/src/plugins/Avatar/assets/link.tsx | 14 + .../mask/src/plugins/Avatar/assets/more.tsx | 14 + .../src/plugins/Avatar/assets/nftavatar.png | Bin 0 -> 1007 bytes .../mask/src/plugins/Avatar/assets/point.tsx | 12 + .../src/plugins/Avatar/assets/selected.tsx | 16 + .../src/plugins/Avatar/assets/setting.tsx | 16 + .../src/plugins/Avatar/assets/twitter.tsx | 20 ++ .../mask/src/plugins/Avatar/assets/verify.tsx | 17 + .../mask/src/plugins/Avatar/assets/wallet.tsx | 32 ++ packages/mask/src/plugins/Avatar/base.ts | 9 +- packages/mask/src/plugins/Avatar/constants.ts | 9 +- packages/mask/src/plugins/Avatar/context.ts | 5 + .../mask/src/plugins/Avatar/hooks/useNFT.ts | 28 +- .../Avatar/hooks/usePersonaNFTAvatar.ts | 22 ++ .../Avatar/hooks/usePersonaVerified.ts | 23 ++ .../src/plugins/Avatar/hooks/usePersonas.ts | 38 ++ .../src/plugins/Avatar/hooks/useTokenOwner.ts | 45 +++ .../src/plugins/Avatar/locales/en-US.json | 27 ++ .../mask/src/plugins/Avatar/locales/index.ts | 6 + .../src/plugins/Avatar/locales/languages.ts | 19 + packages/mask/src/plugins/Avatar/types.ts | 20 +- .../mask/src/plugins/Avatar/utils/index.ts | 116 +++++- .../plugins/FindTruman/SNSAdaptor/index.tsx | 3 + .../mask/src/plugins/ITO/SNSAdaptor/index.tsx | 6 + .../src/plugins/MaskBox/SNSAdaptor/index.tsx | 3 + .../src/plugins/Pets/SNSAdaptor/index.tsx | 3 + .../src/plugins/Savings/SNSAdaptor/index.tsx | 3 + .../src/plugins/Tips/SNSAdaptor/index.tsx | 3 + .../src/plugins/Trader/SNSAdaptor/index.tsx | 3 + .../src/plugins/Transak/SNSAdaptor/index.tsx | 3 + packages/mask/src/resources/NFTAvatar.tsx | 28 ++ .../facebook.com/utils/selector.ts | 4 +- .../twitter.com/collecting/identity.ts | 40 ++- .../injection/NFT/NFTAvatarEditProfile.tsx | 52 ++- .../injection/NFT/NFTAvatarInTwitter.tsx | 10 +- .../injection/NFT/ProfileNFTAvatar.tsx | 105 ------ .../twitter.com/ui-provider.ts | 4 +- .../twitter.com/utils/selector.ts | 3 + packages/plugin-infra/src/types.ts | 2 + .../CrossChainBridge/src/SNSAdaptor/index.tsx | 3 + .../FileService/src/SNSAdaptor/index.tsx | 25 +- .../GoPlusSecurity/src/SNSAdaptor/index.tsx | 3 + .../UI/components/ApplicationEntry/index.tsx | 158 +++++---- .../contexts/components/InjectedDialog.tsx | 6 +- packages/web3-providers/src/NextID/kv.ts | 24 +- packages/web3-providers/src/twitter/index.ts | 46 ++- packages/web3-providers/src/types.ts | 35 +- .../evm/contracts/useERC721TokenContract.ts | 5 +- .../web3-shared/evm/hooks/useCollectibles.ts | 10 +- .../evm/hooks/useERC721TokenDetailed.ts | 1 + packages/web3-shared/evm/pipes/index.ts | 8 +- pnpm-lock.yaml | 205 +++++++++-- 91 files changed, 3015 insertions(+), 334 deletions(-) create mode 100644 packages/icons/plugins/NFTAvatar.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/NFTAvatar.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/NFTInfo.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/NFTList.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/PersonaItem.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/PersonaPage.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/UploadAvatarDialog.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx create mode 100644 packages/mask/src/plugins/Avatar/Application/WalletList.tsx delete mode 100644 packages/mask/src/plugins/Avatar/SNSAdaptor/background/amount.png delete mode 100644 packages/mask/src/plugins/Avatar/SNSAdaptor/background/noamount.png delete mode 100644 packages/mask/src/plugins/Avatar/SNSAdaptor/background/noname.png create mode 100644 packages/mask/src/plugins/Avatar/assets/Verify2.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/application.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/checked.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/close.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/copy.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/frame.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/info.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/link.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/more.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/nftavatar.png create mode 100644 packages/mask/src/plugins/Avatar/assets/point.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/selected.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/setting.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/twitter.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/verify.tsx create mode 100644 packages/mask/src/plugins/Avatar/assets/wallet.tsx create mode 100644 packages/mask/src/plugins/Avatar/context.ts create mode 100644 packages/mask/src/plugins/Avatar/hooks/usePersonaNFTAvatar.ts create mode 100644 packages/mask/src/plugins/Avatar/hooks/usePersonaVerified.ts create mode 100644 packages/mask/src/plugins/Avatar/hooks/usePersonas.ts create mode 100644 packages/mask/src/plugins/Avatar/hooks/useTokenOwner.ts create mode 100644 packages/mask/src/plugins/Avatar/locales/en-US.json create mode 100644 packages/mask/src/plugins/Avatar/locales/index.ts create mode 100644 packages/mask/src/plugins/Avatar/locales/languages.ts create mode 100644 packages/mask/src/resources/NFTAvatar.tsx delete mode 100644 packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/ProfileNFTAvatar.tsx diff --git a/.i18n-codegen.json b/.i18n-codegen.json index ded70c3006bd..d54cdcd12b53 100644 --- a/.i18n-codegen.json +++ b/.i18n-codegen.json @@ -229,6 +229,18 @@ "trans": "Translate", "sourceMap": "inline" } + }, + { + "input": "./packages/mask/src/plugins/Avatar/locales/en-US.json", + "output": "./packages/mask/src/plugins/Avatar/locales/i18n_generated", + "parser": "i18next", + "generator": { + "type": "i18next/react-hooks", + "hooks": "useI18N", + "namespace": "com.maskbook.avatar", + "trans": "Translate", + "sourceMap": "inline" + } } ] } diff --git a/cspell.json b/cspell.json index 9e1391ac7183..b26de3d954c0 100644 --- a/cspell.json +++ b/cspell.json @@ -120,6 +120,7 @@ "multicall", "multihop", "newsfeed", + "nftavatar", "nftrss", "nftscan", "nums", @@ -215,7 +216,7 @@ "aicanft", "algr", "anft", - "avator", + "armv", "blocto", "bsct", "btcb", diff --git a/packages/icons/plugins/NFTAvatar.tsx b/packages/icons/plugins/NFTAvatar.tsx new file mode 100644 index 000000000000..4ba11fbe2ed0 --- /dev/null +++ b/packages/icons/plugins/NFTAvatar.tsx @@ -0,0 +1,29 @@ +import { createIcon } from '../utils' +import type { SvgIcon } from '@mui/material' + +export const NFTAvatarIcon: typeof SvgIcon = createIcon( + 'nft_avatar', + + + + + + + + + + , + '0 0 37 36', +) diff --git a/packages/icons/plugins/index.ts b/packages/icons/plugins/index.ts index 042cbb8b08a1..3915a4d0166c 100644 --- a/packages/icons/plugins/index.ts +++ b/packages/icons/plugins/index.ts @@ -24,5 +24,6 @@ export * from './DHEDGEIcon' export * from './PoolTogetherIcon' export * from './SecurityChecker' export * from './ArtBlocks' +export * from './NFTAvatar' export * from './connect' export * from './shared' diff --git a/packages/mask/package.json b/packages/mask/package.json index 25d28a0b9d5a..68d24f9efcda 100644 --- a/packages/mask/package.json +++ b/packages/mask/package.json @@ -56,6 +56,7 @@ "@types/json-stable-stringify": "^1.0.34", "@types/json2csv": "^5.0.3", "@types/node": "^17.0.31", + "@types/react-avatar-editor": "^10.3.6", "@types/react-highlight-words": "^0.16.4", "@types/react-router-dom": "^5.3.3", "@types/react-virtualized-auto-sizer": "^1.0.1", @@ -100,6 +101,7 @@ "pure-react-carousel": "^1.28.1", "promievent": "^0.1.4", "protobufjs": "^6.11.2", + "react-avatar-editor": "^12.0.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-draggable": "^4.4.4", diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index 5fee71e29b8f..5471db0b8fa6 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -336,12 +336,14 @@ "plugin_wallet_name_placeholder": "Enter 1-12 characters", "plugin_wallet_fail_to_sign": "Failed to sign password.", "plugin_wallet_cancel_sign": "Signature canceled.", + "plugin_nft_avatar_recommend_feature_description": "Set your NFT as profile picture with exclusive aura", "plugin_red_packet_display_name": "Plugin: Lucky Drop", + "application_hint": "Socialize and show off your NFTs. People can bid,buy, view your valuable NFTs without leaving Twitter.", "plugin_red_packet_claimed": "Claimed", "plugin_red_packet_erc20_tab_title": "Token", "plugin_red_packet_erc721_tab_title": "Collectibles", "plugin_red_packet_name": "Lucky Drop", - "plugin_red_packet_recommend_feature_description": "Surpirse your social friends with Lucky Drop", + "plugin_red_packet_recommend_feature_description": "Astonish your friends with a surprise gift", "plugin_red_packet_description": "Gift crypto or NFTs to any users, first come, first served.", "plugin_red_packet_erc721_insufficient_balance": "Insufficient Balance", "plugin_red_packet_details": "Lucky Drop Details", @@ -950,8 +952,6 @@ "popups_social_account": "Social Accounts", "popups_connected_wallets": "Connected Wallets", "popups_loading": "Loading", - "popups_wallet_disconnect_success": "Wallet disconnect successfully", - "popups_wallet_disconnect_failed": "Wallet disconnect failed", "popups_connect_your_web2_social_accounts": "Connect your web2 social accounts", "popups_connect_social_account": "Connect Social Account", "popups_disconnect_success": " Disconnect successfully. ", @@ -1018,6 +1018,7 @@ "popups_wallet_token_buy": "Buy", "popups_wallet_token_send": "Send", "popups_wallet_token_swap": "Swap", + "popups_wallet_disconnect_failed": "Wallet disconnect failed", "popups_wallet_view_on_explorer": "View on Explorer", "popups_wallet_gas_fee_settings": "Gas fee settings", "popups_wallet_gas_fee_settings_description": "Gas fees are the fees for paying ethereum miners. The miners prefer to pack transactions with higher gas fees. Transactions with low gas fees might fail, and the paid gas fees won’t be returned.", @@ -1029,7 +1030,6 @@ "popups_wallet_gas_fee_settings_max_priority_fee": "Max priority fee", "popups_wallet_gas_fee_settings_max_fee": "Max fee", "popups_wallet_gas_fee_settings_min_gas_limit_tips": "Gas limit must be at least {{limit}}", - "popups_wallet_unsupported_network": "Unsupported network type", "popups_wallet_signature_request_title": "Signature Request", "popups_wallet_signature_request": "Signature request", "popups_wallet_signature_request_message": "Message", @@ -1075,13 +1075,13 @@ "plugin_vcent_last_offer_at": "LATEST OFFER at", "nft_input_address_label": "Please input contract address", "nft_input_tokenid_label": "Please input token ID", - "nft_owner_hint": "This NFT does not exist or does not belong to you.", + "nft_owner_hint": "The contract address is incorrect or the collection does not belong to you", "nft_add_dialog_title": "Add Collectible", "nft_add_button_label": "Add", "nft_list_title": "NFT Avatar Setting", "nft_wallet_change": "Change", "nft_button_add_collectible": "Add Collectible", - "nft_avatar": "NFT Avatar", + "nft_avatar": "NFT PFP", "web3_tab_hint": "No address found.", "plugin_artblocks_not_active": "This project is no more active", "plugin_artblocks_completed": "Completed", @@ -1104,6 +1104,7 @@ "plugin_artblocks_blockchain_row": "Blockchain:", "plugin_artblocks_contract_row": "Contract:", "plugin_artblocks_smt_wrong": "Something went wrong!", + "popups_wallet_disconnect_success": "Wallet disconnect successfully", "plugin_artblocks_share": "I just purchased a beautiful piece of art from '{{name}}' collection for {{price}} {{symbol}}. Install @realMaskNetwork to get yours.", "plugin_artblocks_share_no_official_account": "I just purchased a beautiful piece of art from '{{name}}' collection for {{price}} {{symbol}}. Welcome to join.", "plugin_tips_disconnect_introduction": "Are you going to disconnect {{persona}} from wallet {{address}}?", @@ -1121,6 +1122,7 @@ "plugin_transak_description": "Fiat On-Ramp Aggregator on Twitter. Buy crypto in 60+ countries with Transak support.", "plugin_valuables_name": "Valuables", "plugin_valuables_description": "Buy & sell tweets autographed by their original creators.", + "popups_wallet_unsupported_network": "Unsupported network type", "plugin_default_title": "Default", "plugin_provider_by": "Provided by", "plugin_enables": "Enable plugins" diff --git a/packages/mask/shared-ui/locales/ko-KR.json b/packages/mask/shared-ui/locales/ko-KR.json index 309f9b81d1b8..03f0790092aa 100644 --- a/packages/mask/shared-ui/locales/ko-KR.json +++ b/packages/mask/shared-ui/locales/ko-KR.json @@ -721,7 +721,6 @@ "popups_wallet_gas_fee_settings_max_priority_fee": "최대 우선 가스비", "popups_wallet_gas_fee_settings_max_fee": "최대 가스비", "popups_wallet_gas_fee_settings_min_gas_limit_tips": "최소한 가스비는 {{limit}} 입니다", - "popups_wallet_unsupported_network": "지원되지 않는 네트워크", "popups_wallet_signature_request": "서명", "popups_wallet_signature_request_message": "메시지", "popups_wallet_contract_interaction": "컨트렉트 인터액션", diff --git a/packages/mask/shared-ui/locales/qya-AA.json b/packages/mask/shared-ui/locales/qya-AA.json index fa190e5951ae..2d3a312335e6 100644 --- a/packages/mask/shared-ui/locales/qya-AA.json +++ b/packages/mask/shared-ui/locales/qya-AA.json @@ -948,8 +948,6 @@ "popups_social_account": "crwdns16328:0crwdne16328:0", "popups_connected_wallets": "crwdns16330:0crwdne16330:0", "popups_loading": "crwdns16332:0crwdne16332:0", - "popups_wallet_disconnect_success": "crwdns16334:0crwdne16334:0", - "popups_wallet_disconnect_failed": "crwdns16336:0crwdne16336:0", "popups_connect_your_web2_social_accounts": "crwdns16338:0crwdne16338:0", "popups_connect_social_account": "crwdns16340:0crwdne16340:0", "popups_disconnect_success": "crwdns16342:0crwdne16342:0", @@ -1027,7 +1025,6 @@ "popups_wallet_gas_fee_settings_max_priority_fee": "crwdns7857:0crwdne7857:0", "popups_wallet_gas_fee_settings_max_fee": "crwdns7859:0crwdne7859:0", "popups_wallet_gas_fee_settings_min_gas_limit_tips": "crwdns8993:0{{limit}}crwdne8993:0", - "popups_wallet_unsupported_network": "crwdns8995:0crwdne8995:0", "popups_wallet_signature_request_title": "crwdns16386:0crwdne16386:0", "popups_wallet_signature_request": "crwdns7861:0crwdne7861:0", "popups_wallet_signature_request_message": "crwdns8059:0crwdne8059:0", diff --git a/packages/mask/shared-ui/locales/zh-CN.json b/packages/mask/shared-ui/locales/zh-CN.json index 8794b0935615..74cde5626191 100644 --- a/packages/mask/shared-ui/locales/zh-CN.json +++ b/packages/mask/shared-ui/locales/zh-CN.json @@ -837,7 +837,6 @@ "popups_wallet_gas_fee_settings_max_priority_fee": "Max priority fee", "popups_wallet_gas_fee_settings_max_fee": "Max fee", "popups_wallet_gas_fee_settings_min_gas_limit_tips": "Gas limit 必须至少 {{limit}}", - "popups_wallet_unsupported_network": "不支持的网络类型", "popups_wallet_signature_request": "签名请求", "popups_wallet_signature_request_message": "信息", "popups_wallet_contract_interaction": "合约交互", diff --git a/packages/mask/src/components/shared/ApplicationBoard.tsx b/packages/mask/src/components/shared/ApplicationBoard.tsx index 9f8b3016c9ae..bba3a2fd9cfc 100644 --- a/packages/mask/src/components/shared/ApplicationBoard.tsx +++ b/packages/mask/src/components/shared/ApplicationBoard.tsx @@ -4,7 +4,7 @@ import { Typography } from '@mui/material' import { useChainId } from '@masknet/web3-shared-evm' import { useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra/content-script' import { useCurrentWeb3NetworkPluginID, useAccount, NetworkPluginID } from '@masknet/plugin-infra/web3' -import { CrossIsolationMessages, formatPersonaPublicKey } from '@masknet/shared-base' +import { formatPersonaPublicKey } from '@masknet/shared-base' import { getCurrentSNSNetwork } from '../../social-network-adaptor/utils' import { activatedSocialNetworkUI } from '../../social-network' import { useI18N } from '../../utils' @@ -31,7 +31,7 @@ const useStyles = makeStyles<{ shouldScroll: boolean }>()((theme, props) => { gridGap: 10, justifyContent: 'space-between', height: 320, - width: props.shouldScroll ? 575 : 562, + width: props.shouldScroll ? 589 : 576, '::-webkit-scrollbar': { backgroundColor: 'transparent', width: 20, @@ -145,7 +145,9 @@ function ApplicationBoardContent(props: Props) { [snsAdaptorPlugins, currentWeb3Network, chainId, account], ) - const recommendFeatureAppList = applicationList.filter((x) => x.entry.recommendFeature) + const recommendFeatureAppList = applicationList + .filter((x) => x.entry.recommendFeature) + .sort((a, b) => (a.entry.appBoardSortingDefaultPriority ?? 0) - (b.entry.appBoardSortingDefaultPriority ?? 0)) const listedAppList = applicationList.filter((x) => !x.entry.recommendFeature).filter((x) => !getUnlistedApp(x)) const { classes } = useStyles({ shouldScroll: listedAppList.length > 12 }) @@ -208,7 +210,7 @@ function RenderEntryComponent({ application }: { application: Application }) { const verifyPersona = useCallback(() => { closeApplicationBoard() - CrossIsolationMessages.events.verifyNextID.sendToAll(undefined) + ApplicationEntryStatus.personaNextIDReset?.() }, []) const clickHandler = (() => { @@ -225,6 +227,7 @@ function RenderEntryComponent({ application }: { application: Application }) { // #region tooltip hint const tooltipHint = (() => { + if (ApplicationEntryStatus.isLoading) return if (application.isWalletConnectedRequired) return t('application_tooltip_hint_connect_wallet') if (application.isWalletConnectedEVMRequired) return t('application_tooltip_hint_switch_to_evm_wallet') if (!application.entry.nextIdRequired) return @@ -261,6 +264,7 @@ interface ApplicationEntryStatusContextProps { currentPersonaPublicKey: string | undefined currentSNSConnectedPersonaPublicKey: string | undefined personaConnectAction: (() => void) | undefined + personaNextIDReset: (() => void) | undefined isLoading: boolean } @@ -274,6 +278,7 @@ const ApplicationEntryStatusContext = createContext) { const personaConnectStatus = usePersonaConnectStatus() const nextIDConnectStatus = useNextIDConnectStatus() - const { value: ApplicationCurrentStatus, retry } = usePersonaAgainstSNSConnectStatus() + const { + value: ApplicationCurrentStatus, + retry, + loading: personaAgainstSNSConnectStatusLoading, + } = usePersonaAgainstSNSConnectStatus() useEffect(() => { return MaskMessages.events.currentPersonaIdentifier.on(retry) @@ -294,6 +303,7 @@ function ApplicationEntryStatusProvider(props: PropsWithChildren<{}>) { ) { shouldVerifyNextId: Boolean(!nextIDConnectStatus.isVerified && ApplicationCurrentStatus), currentPersonaPublicKey, currentSNSConnectedPersonaPublicKey, - isLoading: nextIDConnectStatus.loading, + isLoading: nextIDConnectStatus.loading || personaAgainstSNSConnectStatusLoading, }}> {props.children} diff --git a/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx b/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx index 5e5d47c7e912..e1ae1c7860e9 100644 --- a/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx +++ b/packages/mask/src/components/shared/ApplicationSettingPluginList.tsx @@ -24,7 +24,7 @@ export function getUnlistedApp(app: Application): boolean { } // #endregion -const useStyles = makeStyles()((theme) => ({ +const useStyles = makeStyles<{ iconFilterColor?: string }>()((theme, { iconFilterColor }) => ({ list: { display: 'grid', gap: theme.spacing(2, 1), @@ -54,6 +54,9 @@ const useStyles = makeStyles()((theme) => ({ width: 36, height: 36, }, + ...(iconFilterColor + ? { filter: `drop-shadow(0px 6px 12px ${iconFilterColor})`, backdropFilter: 'blur(16px)' } + : {}), }, loadingWrapper: { display: 'flex', @@ -77,7 +80,7 @@ const useStyles = makeStyles()((theme) => ({ })) export function ApplicationSettingPluginList() { - const { classes } = useStyles() + const { classes } = useStyles({ iconFilterColor: undefined }) const { t } = useI18N() const snsAdaptorPlugins = useActivatedPluginsSNSAdaptor('any') const applicationList = useMemo(() => { @@ -123,7 +126,7 @@ interface AppListProps { function AppList(props: AppListProps) { const { appList, setUnlistedApp, isListed } = props - const { classes } = useStyles() + const { classes } = useStyles({ iconFilterColor: undefined }) const { t } = useI18N() return appList.length > 0 ? ( @@ -156,7 +159,7 @@ interface AppListItemProps { function AppListItem(props: AppListItemProps) { const { application, setUnlistedApp, isListed } = props - const { classes } = useStyles() + const { classes } = useStyles({ iconFilterColor: application.entry.iconFilterColor }) return ( setUnlistedApp(application, isListed)}>

{application.entry.icon}
diff --git a/packages/mask/src/extension/popups/pages/Personas/ConnectedWallets/index.tsx b/packages/mask/src/extension/popups/pages/Personas/ConnectedWallets/index.tsx index b47e4de10d78..09e057afa2b9 100644 --- a/packages/mask/src/extension/popups/pages/Personas/ConnectedWallets/index.tsx +++ b/packages/mask/src/extension/popups/pages/Personas/ConnectedWallets/index.tsx @@ -12,12 +12,15 @@ import type { ConnectedWalletInfo } from '../type' import { NextIDProof } from '@masknet/web3-providers' import Service from '../../../../service' import { usePopupCustomSnackbar } from '@masknet/theme' +import { useLocation, useNavigate } from 'react-router-dom' const ConnectedWallets = memo(() => { const { t } = useI18N() const chainId = useChainId() const { NameService } = useWeb3State() const wallets = useWallets() + const navigate = useNavigate() + const location = useLocation() const { proofs, currentPersona, refreshProofs, fetchProofsLoading } = PersonaContext.useContainer() const { showSnackbar } = usePopupCustomSnackbar() @@ -107,6 +110,13 @@ const ConnectedWallets = memo(() => { ) const navigateToConnectWallet = async () => { + const params = new URLSearchParams(location.search) + const internal = params.get('internal') + + if (internal) { + navigate(PopupRoutes.ConnectWallet) + return + } await Service.Helper.openPopupWindow(PopupRoutes.ConnectWallet) window.close() } diff --git a/packages/mask/src/plugins/Avatar/Application/NFTAvatar.tsx b/packages/mask/src/plugins/Avatar/Application/NFTAvatar.tsx new file mode 100644 index 000000000000..33205b509739 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/NFTAvatar.tsx @@ -0,0 +1,46 @@ +import { EnhanceableSite } from '@masknet/shared-base' +import { Avatar, Stack } from '@mui/material' +import { PointIcon } from '../assets/point' +import { TwitterIcon } from '../assets/twitter' +import { RainbowBox } from '../SNSAdaptor/RainbowBox' + +export const SOCIAL_MEDIA_ICON_MAPPING: Record = { + [EnhanceableSite.Twitter]: , + [EnhanceableSite.Localhost]: null, +} + +interface NFTAvatarProps { + hasBorder: boolean + platform?: string + avatar?: string + owner?: boolean +} + +export function NFTAvatar(props: NFTAvatarProps) { + const { avatar, hasBorder, platform = '', owner = false } = props + + return ( + + {hasBorder ? ( + + + + ) : ( + + )} + + + {SOCIAL_MEDIA_ICON_MAPPING[EnhanceableSite.Twitter]} + + {owner ? : null} + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx b/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx new file mode 100644 index 000000000000..d76817e316b6 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx @@ -0,0 +1,106 @@ +import { useCallback, useState } from 'react' +import { NFTListDialog } from './NFTListDialog' +import { InjectedDialog } from '@masknet/shared' +import { UploadAvatarDialog } from './UploadAvatarDialog' +import type { BindingProof } from '@masknet/shared-base' +import type { SelectTokenInfo, TokenInfo } from '../types' +import { PersonaPage } from './PersonaPage' +import { DialogContent } from '@mui/material' +import { useI18N } from '../locales/i18n_generated' +import { isSameAddress } from '@masknet/web3-shared-evm' +import { makeStyles } from '@masknet/theme' + +const useStyles = makeStyles()((theme) => ({ + root: { + margin: 0, + padding: '1px !important', + '::-webkit-scrollbar': { + backgroundColor: 'transparent', + width: 20, + }, + '::-webkit-scrollbar-thumb': { + borderRadius: '20px', + width: 5, + border: '7px solid rgba(0, 0, 0, 0)', + backgroundColor: theme.palette.mode === 'dark' ? 'rgba(250, 250, 250, 0.2)' : 'rgba(0, 0, 0, 0.2)', + backgroundClip: 'padding-box', + }, + }, +})) +enum CreateNFTAvatarStep { + Persona = 'persona', + NFTList = 'NFTList', + UploadAvatar = 'UploadAvatar', +} + +interface NFTAvatarsDialogProps { + open: boolean + onClose: () => void +} + +export function NFTAvatarDialog(props: NFTAvatarsDialogProps) { + const [step, setStep] = useState(CreateNFTAvatarStep.Persona) + const [wallets, setWallets] = useState() + const [selectedTokenInfo, setSelectedTokenInfo] = useState() + const [tokenInfo, setTokenInfo] = useState() + const [proof, setProof] = useState() + const t = useI18N() + const { classes } = useStyles() + + const onPersonaChange = (proof: BindingProof, wallets?: BindingProof[], tokenInfo?: TokenInfo) => { + setWallets(wallets) + setTokenInfo(tokenInfo) + setProof(proof) + } + + const onSelected = (info: SelectTokenInfo) => { + setSelectedTokenInfo(info) + } + + const onNext = useCallback(() => { + if (step === CreateNFTAvatarStep.Persona) setStep(CreateNFTAvatarStep.NFTList) + else if (step === CreateNFTAvatarStep.NFTList) setStep(CreateNFTAvatarStep.UploadAvatar) + }, [step]) + + const onBack = useCallback(() => { + if (step === CreateNFTAvatarStep.UploadAvatar) setStep(CreateNFTAvatarStep.NFTList) + else if (step === CreateNFTAvatarStep.NFTList) setStep(CreateNFTAvatarStep.Persona) + else props.onClose() + }, [step]) + + const onClose = useCallback(() => { + setStep(CreateNFTAvatarStep.Persona) + props.onClose() + }, [props.onClose]) + + return ( + + + {step === CreateNFTAvatarStep.Persona ? ( + + ) : null} + {step === CreateNFTAvatarStep.NFTList ? ( + + ) : null} + {step === CreateNFTAvatarStep.UploadAvatar ? ( + isSameAddress(x.identity, selectedTokenInfo?.account))} + account={selectedTokenInfo?.account} + image={selectedTokenInfo?.image} + token={selectedTokenInfo?.token} + onBack={onBack} + onClose={onClose} + /> + ) : null} + + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/NFTInfo.tsx b/packages/mask/src/plugins/Avatar/Application/NFTInfo.tsx new file mode 100644 index 000000000000..77647436ee5a --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/NFTInfo.tsx @@ -0,0 +1,65 @@ +import { Box, CircularProgress, Link, Stack, Typography } from '@mui/material' +import { makeStyles, useStylesExtends } from '@masknet/theme' +import { LinkIcon } from '../assets/link' +import { ChainId, resolveOpenSeaLink } from '@masknet/web3-shared-evm' +import { formatTokenId } from '../utils' +import { useI18N } from '../locales/i18n_generated' +import { ApplicationRoundIcon } from '../assets/application' +import { formatPersonaName } from '@masknet/shared-base' + +const useStyles = makeStyles()(() => ({ + root: { + width: 160, + }, + nft: { + display: 'flex', + alignItems: 'center', + }, +})) +interface NFTInfoProps extends withClasses<'root'> { + nft?: { name: string; address: string; tokenId: string; symbol: string; chainId: ChainId } + owner: boolean + loading?: boolean +} + +export function NFTInfo(props: NFTInfoProps) { + const { nft, owner, loading = false } = props + const classes = useStylesExtends(useStyles(), props) + const t = useI18N() + + if (loading) return + return ( + + {!nft ? ( + + {t.persona_set_nft()} + + ) : !owner ? ( + + {t.persona_verification_failed()} + + ) : ( + + + + + {formatPersonaName(nft.name.replace(/#\d+/, ''))} + + + + {formatTokenId(nft.symbol, nft.tokenId)} + + + + + + + + )} + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/NFTList.tsx b/packages/mask/src/plugins/Avatar/Application/NFTList.tsx new file mode 100644 index 000000000000..eb9615527ce4 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/NFTList.tsx @@ -0,0 +1,103 @@ +import { makeStyles, useTabs } from '@masknet/theme' +import { ChainId, ERC721TokenDetailed } from '@masknet/web3-shared-evm' +import { TabContext, TabPanel } from '@mui/lab' +import { Tab, Tabs, Typography } from '@mui/material' +import { Application_NFT_LIST_PAGE, SUPPORTED_CHAIN_IDS } from '../constants' +import type { TokenInfo } from '../types' +import { NFTListPage } from './NFTListPage' + +const useStyles = makeStyles<{ currentTab: Application_NFT_LIST_PAGE }>()((theme, props) => ({ + selected: { + backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white', + border: 'none', + borderTop: `1px solid ${theme.palette.mode === 'dark' ? '#2F3336' : '#EFF3F4'}`, + color: `${theme.palette.text.primary} !important`, + minHeight: 37, + height: 37, + zIndex: 1, + }, + tab: { + backgroundColor: theme.palette.mode === 'dark' ? '#15171A' : '#F6F8F8', + color: theme.palette.text.secondary, + border: `1px solid ${theme.palette.mode === 'dark' ? '#2F3336' : '#EFF3F4'}`, + minHeight: 37, + height: 37, + zIndex: 1, + }, + tabPanel: { + padding: theme.spacing(1), + paddingTop: 50, + paddingBottom: 80, + }, +})) +interface NFTListProps { + address: string + tokenInfo?: TokenInfo + onSelect: (token: ERC721TokenDetailed) => void + onChangePage?: (page: Application_NFT_LIST_PAGE) => void + tokens?: ERC721TokenDetailed[] + children?: React.ReactElement +} + +export function NFTList(props: NFTListProps) { + const { address, onSelect, tokenInfo, onChangePage, tokens = [], children } = props + + const [currentTab, onChange, tabs] = useTabs( + Application_NFT_LIST_PAGE.Application_nft_tab_eth_page, + Application_NFT_LIST_PAGE.Application_nft_tab_polygon_page, + ) + + const { classes } = useStyles({ currentTab }) + const _onChange = (event: unknown, value: any) => { + onChange(event, value) + onChangePage?.(value) + } + + if (!address) return null + return ( + + + {SUPPORTED_CHAIN_IDS.map((x, i) => { + const curChainId = currentTab === tabs.ETH ? ChainId.Mainnet : ChainId.Matic + return ( + + {x === ChainId.Mainnet + ? Application_NFT_LIST_PAGE.Application_nft_tab_eth_page + : Application_NFT_LIST_PAGE.Application_nft_tab_polygon_page} +
+ } + value={x === ChainId.Mainnet ? tabs.ETH : tabs.Polygon} + className={curChainId === x ? classes.selected : classes.tab} + /> + ) + })} + + {SUPPORTED_CHAIN_IDS.map((x, i) => ( + + y.contractDetailed.chainId === x) ?? []} + tokenInfo={tokenInfo} + chainId={x} + address={address} + onSelect={onSelect} + children={children} + /> + + ))} + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx b/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx new file mode 100644 index 000000000000..1488f4fc3deb --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx @@ -0,0 +1,279 @@ +import { makeStyles, useCustomSnackbar } from '@masknet/theme' +import { ChainId, ERC721TokenDetailed, isSameAddress, SocketState, useCollectibles } from '@masknet/web3-shared-evm' +import { Box, Button, DialogActions, DialogContent, Skeleton, Stack, Typography } from '@mui/material' +import { useCallback, useState, useEffect } from 'react' +import { downloadUrl } from '../../../utils' +import { AddNFT } from '../SNSAdaptor/AddNFT' +import type { BindingProof } from '@masknet/shared-base' +import type { SelectTokenInfo, TokenInfo } from '../types' +import { range, uniqBy } from 'lodash-unified' +import { Translate, useI18N } from '../locales' +import { AddressNames } from './WalletList' +import { NFTList } from './NFTList' +import { Application_NFT_LIST_PAGE } from '../constants' +import { NetworkPluginID, useAccount, useCurrentWeb3NetworkPluginID } from '@masknet/plugin-infra/web3' +import { NFTWalletConnect } from './WalletConnect' + +const useStyles = makeStyles()((theme) => ({ + AddressNames: { + position: 'absolute', + top: 10, + right: 10, + }, + + button: { + width: 219.5, + borderRadius: 999, + }, + AddCollectiblesButton: { + fontWeight: 600, + color: '#1D9BF0', + }, + actions: { + padding: theme.spacing(2), + backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white', + position: 'absolute', + left: 0, + bottom: 0, + width: 'calc(100% - 32px)', + }, + content: { + height: 612, + padding: 0, + backgroundColor: theme.palette.mode === 'dark' ? 'black' : 'white', + }, + error: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + margin: 'auto', + paddingTop: 260, + }, + skeleton: { + width: 97, + height: 97, + objectFit: 'cover', + borderRadius: '100%', + boxSizing: 'border-box', + padding: 6, + margin: theme.spacing(0.5, 1), + }, + skeletonBox: { + marginLeft: 'auto', + marginRight: 'auto', + }, + gallery: { + display: 'flex', + flexFlow: 'row wrap', + overflowY: 'auto', + '&::-webkit-scrollbar': { + display: 'none', + }, + }, +})) + +function isSameToken(token?: ERC721TokenDetailed, tokenInfo?: TokenInfo) { + if (!token && !tokenInfo) return false + return isSameAddress(token?.contractDetailed.address, tokenInfo?.address) && token?.tokenId === tokenInfo?.tokenId +} +interface NFTListDialogProps { + onNext: () => void + tokenInfo?: TokenInfo + wallets?: BindingProof[] + onSelected: (info: SelectTokenInfo) => void +} + +export function NFTListDialog(props: NFTListDialogProps) { + const { onNext, wallets, onSelected, tokenInfo } = props + const { classes } = useStyles() + + const account = useAccount() + const [open_, setOpen_] = useState(false) + const [selectedAccount, setSelectedAccount] = useState('') + const [selectedToken, setSelectedToken] = useState() + const [disabled, setDisabled] = useState(false) + const t = useI18N() + const [tokens, setTokens] = useState([]) + const [currentPage, setCurrentPage] = useState( + Application_NFT_LIST_PAGE.Application_nft_tab_eth_page, + ) + + const POLYGON_PAGE = Application_NFT_LIST_PAGE.Application_nft_tab_polygon_page + + const currentPluginId = useCurrentWeb3NetworkPluginID() + const { + data: collectibles, + error, + retry, + state, + } = useCollectibles(selectedAccount, currentPage !== POLYGON_PAGE ? ChainId.Mainnet : ChainId.Matic) + + const { showSnackbar } = useCustomSnackbar() + const onChange = useCallback((address: string) => { + setSelectedAccount(address) + }, []) + + const onSelect = (token: ERC721TokenDetailed) => { + setSelectedToken(token) + } + + const onSave = useCallback(async () => { + if (!selectedToken?.info?.imageURL) return + setDisabled(true) + try { + const image = await downloadUrl(selectedToken.info.imageURL) + onSelected({ image: URL.createObjectURL(image), account: selectedAccount, token: selectedToken }) + onNext() + setDisabled(false) + } catch (error) { + console.log(error) + } + setDisabled(false) + }, [selectedToken, selectedAccount]) + + const onClick = useCallback(() => { + if (!account && !wallets?.length) { + showSnackbar('Please connect your wallet!', { variant: 'error' }) + return + } + setOpen_(true) + }, [account, wallets, showSnackbar]) + + useEffect(() => { + setDisabled(!selectedToken || isSameToken(selectedToken, tokenInfo)) + }, [selectedToken, tokenInfo]) + + useEffect(() => setSelectedAccount(account || wallets?.[0]?.identity || ''), [account, wallets]) + + const onAddClick = (token: ERC721TokenDetailed) => { + setTokens((_tokens) => uniqBy([..._tokens, token], (x) => x.contractDetailed.address && x.tokenId)) + } + + const onChangePage = (name: Application_NFT_LIST_PAGE) => { + setCurrentPage(name) + setSelectedToken(undefined) + } + + const AddCollectible = ( + + + {currentPluginId !== NetworkPluginID.PLUGIN_EVM ? ( + , + }} + /> + ) : currentPage === POLYGON_PAGE ? ( + , + }} + /> + ) : ( + t.collectible_no_eth() + )} + + {currentPluginId === NetworkPluginID.PLUGIN_EVM ? ( + + ) : null} + + ) + + const LoadStatus = ( +
+ {range(8).map((i) => ( + + ))} +
+ ) + + const Retry = ( + + {t.no_collectible_found()} + + + ) + + const NoNFTList = () => { + if (currentPage === POLYGON_PAGE && tokens.length === 0) return AddCollectible + else if (currentPage === POLYGON_PAGE && tokens.length) return + if (state !== SocketState.done) { + return LoadStatus + } + if (error) { + return Retry + } + if (tokens.length === 0 && collectibles.length === 0) { + return AddCollectible + } + + return + } + + if (!wallets?.length && (currentPluginId !== NetworkPluginID.PLUGIN_EVM || !account)) + return ( + + + + ) + + return ( + <> + + + {((account && currentPluginId === NetworkPluginID.PLUGIN_EVM) || Boolean(wallets?.length)) && ( + x.contractDetailed.address && x.tokenId)} + children={NoNFTList()} + /> + )} + + + {tokens.length || collectibles.length ? ( + + + {t.collectible_not_found()} + + + {t.add_collectible()} + + + ) : null} + + + + setOpen_(false)} + onAddClick={onAddClick} + /> + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx b/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx new file mode 100644 index 000000000000..065ead46a817 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx @@ -0,0 +1,118 @@ +import { makeStyles } from '@masknet/theme' +import { + ChainId, + createERC721Token, + ERC721TokenDetailed, + EthereumTokenType, + useImageChecker, +} from '@masknet/web3-shared-evm' +import { Box, Skeleton } from '@mui/material' +import { useState } from 'react' +import { NFTImage } from '../SNSAdaptor/NFTImage' +import type { TokenInfo } from '../types' + +const useStyles = makeStyles()((theme) => ({ + root: {}, + + button: { + textAlign: 'center', + paddingTop: theme.spacing(1), + display: 'flex', + justifyContent: 'space-around', + flexDirection: 'row', + color: '#1D9BF0', + }, + gallery: { + display: 'flex', + flexFlow: 'row wrap', + overflowY: 'auto', + '&::-webkit-scrollbar': { + display: 'none', + }, + }, + skeleton: { + width: 97, + height: 97, + objectFit: 'cover', + borderRadius: '100%', + boxSizing: 'border-box', + padding: 6, + margin: theme.spacing(0.5, 1), + }, + skeletonBox: { + marginLeft: 'auto', + marginRight: 'auto', + }, +})) + +interface NFTListPageProps { + chainId: ChainId + address: string + tokenInfo?: TokenInfo + tokens: ERC721TokenDetailed[] + onSelect?: (token: ERC721TokenDetailed) => void + children?: React.ReactElement +} + +export function NFTListPage(props: NFTListPageProps) { + const { classes } = useStyles() + const { onSelect, chainId, tokenInfo, tokens, children } = props + const [selectedToken, setSelectedToken] = useState( + tokenInfo + ? createERC721Token( + { + name: '', + address: tokenInfo.address, + chainId, + symbol: '', + type: EthereumTokenType.ERC721, + }, + {}, + tokenInfo.tokenId, + ) + : undefined, + ) + + const onChange = (token: ERC721TokenDetailed) => { + if (!token) return + setSelectedToken(token) + onSelect?.(token) + } + + return ( + <> + + + {children ?? + tokens.map((token: ERC721TokenDetailed, i) => ( + onChange(token)} + /> + ))} + + + + ) +} + +interface NFTImageCollectibleAvatarProps { + token: ERC721TokenDetailed + onChange: (token: ERC721TokenDetailed) => void + selectedToken?: ERC721TokenDetailed +} + +function NFTImageCollectibleAvatar({ token, onChange, selectedToken }: NFTImageCollectibleAvatarProps) { + const { classes } = useStyles() + const { value: isImageToken, loading } = useImageChecker(token.info?.imageURL) + + if (loading) + return ( +
+ +
+ ) + return isImageToken ? : null +} diff --git a/packages/mask/src/plugins/Avatar/Application/PersonaItem.tsx b/packages/mask/src/plugins/Avatar/Application/PersonaItem.tsx new file mode 100644 index 000000000000..7aee1cc9a42c --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/PersonaItem.tsx @@ -0,0 +1,94 @@ +import { makeStyles } from '@masknet/theme' +import { Box, Typography, ListItemButton } from '@mui/material' +import { NFTAvatar } from './NFTAvatar' +import { NFTInfo } from './NFTInfo' +import { MoreIcon } from '../assets/more' +import { RSS3_KEY_SNS } from '../constants' +import { useCheckTokenOwner, useTokenOwner } from '../hooks/useTokenOwner' +import { getAvatarId } from '../../../social-network-adaptor/twitter.com/utils/user' +import type { TokenInfo } from '../types' +import { useCallback } from 'react' +import type { BindingProof } from '@masknet/shared-base' +import { usePersonaNFTAvatar } from '../hooks/usePersonaNFTAvatar' +import { ChainId } from '@masknet/web3-shared-evm' + +const useStyles = makeStyles<{ disabled: boolean }>()((theme, props) => ({ + root: { + margin: theme.spacing(2, 0.5), + border: `1px solid ${theme.palette.divider}`, + borderRadius: 16, + padding: 16, + display: 'flex', + alignItems: 'center', + cursor: 'pointer', + }, + + userInfo: { + fontSize: 14, + marginLeft: 16, + flex: 1, + }, +})) + +interface PersonaItemProps { + owner?: boolean + avatar: string + userId: string + nickname?: string + proof?: BindingProof + onSelect?: (proof: BindingProof, tokenInfo?: TokenInfo) => void +} + +export function PersonaItem(props: PersonaItemProps) { + const { userId, onSelect, owner = false, proof, avatar, nickname = '' } = props + const { classes } = useStyles({ disabled: !owner }) + const { value: _avatar, loading } = usePersonaNFTAvatar(userId, getAvatarId(avatar) ?? '', RSS3_KEY_SNS.TWITTER) + const { value: token, loading: loadingToken } = useTokenOwner( + _avatar?.address ?? '', + _avatar?.tokenId ?? '', + _avatar?.chainId, + ) + const { loading: loadingCheckOwner, isOwner } = useCheckTokenOwner(userId, token?.owner) + + const onClick = useCallback(() => { + if (!proof) return + onSelect?.(proof, _avatar && isOwner ? { address: _avatar?.address, tokenId: _avatar?.tokenId } : undefined) + }, [_avatar, proof]) + + return ( + + + + + {nickname || _avatar?.nickname} + + + @{userId} + + + + + + + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/PersonaPage.tsx b/packages/mask/src/plugins/Avatar/Application/PersonaPage.tsx new file mode 100644 index 000000000000..38a67e5b0312 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/PersonaPage.tsx @@ -0,0 +1,107 @@ +import { BindingProof, NextIDPlatform } from '@masknet/shared-base' +import { makeStyles } from '@masknet/theme' +import { Box, CircularProgress, DialogContent, Stack, Typography } from '@mui/material' +import { useCallback, useState } from 'react' +import { useSubscription } from 'use-subscription' +import { CloseIcon } from '../assets/close' +import { context } from '../context' +import { usePersonas } from '../hooks/usePersonas' +import { useI18N } from '../locales/i18n_generated' +import type { TokenInfo } from '../types' +import { PersonaItem } from './PersonaItem' +import { InfoIcon } from '../assets/info' +import { useMyPersonas } from '../../../components/DataSource/useMyPersonas' + +const useStyles = makeStyles()((theme) => ({ + messageBox: { + display: 'flex', + borderRadius: 4, + padding: 8, + backgroundColor: theme.palette.mode === 'dark' ? '#15171A' : '#F9F9F9', + fontSize: 14, + alignItems: 'center', + color: theme.palette.text.primary, + }, +})) + +interface PersonaPageProps { + onNext: () => void + onClose(): void + onChange: (proof: BindingProof, wallets?: BindingProof[], tokenInfo?: TokenInfo) => void +} + +export function PersonaPage(props: PersonaPageProps) { + const { onNext, onChange, onClose } = props + const [visible, setVisible] = useState(true) + const currentIdentity = useSubscription(context.lastRecognizedProfile) + const { classes } = useStyles() + const { loading, value: persona } = usePersonas() + const myPersonas = useMyPersonas() + const t = useI18N() + + const onSelect = useCallback( + (proof: BindingProof, tokenInfo?: TokenInfo) => { + onChange(proof, persona?.wallets, tokenInfo) + onNext() + }, + [persona?.wallets], + ) + + return ( + + {loading ? ( + + + + ) : ( + <> + {visible ? ( + + + + {t.persona_hint()} + + setVisible(false)} /> + + ) : null} + {persona?.binds?.proofs + .filter((proof) => proof.platform === NextIDPlatform.Twitter) + .filter((x) => x.identity.toLowerCase() === currentIdentity?.identifier?.userId.toLowerCase()) + .map((x, i) => ( + + ))} + + {myPersonas?.[0] && + myPersonas[0].linkedProfiles + .filter((x) => x.identifier.network === currentIdentity?.identifier?.network) + .map((x, i) => + persona?.binds.proofs.some( + (y) => y.identity === x.identifier.userId.toLowerCase(), + ) ? null : ( + + ), + )} + {persona?.binds?.proofs + .filter((proof) => proof.platform === NextIDPlatform.Twitter) + .filter((x) => x.identity.toLowerCase() !== currentIdentity?.identifier?.userId.toLowerCase()) + .map((x, i) => ( + + ))} + + )} + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/UploadAvatarDialog.tsx b/packages/mask/src/plugins/Avatar/Application/UploadAvatarDialog.tsx new file mode 100644 index 000000000000..c310ea817d8e --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/UploadAvatarDialog.tsx @@ -0,0 +1,202 @@ +import { Button, DialogActions, DialogContent, Slider } from '@mui/material' +import AvatarEditor from 'react-avatar-editor' +import { makeStyles, useCustomSnackbar } from '@masknet/theme' +import { useCallback, useState } from 'react' +import { NextIDStorage, Twitter, TwitterBaseAPI } from '@masknet/web3-providers' +import type { ERC721TokenDetailed } from '@masknet/web3-shared-evm' +import { getAvatarId } from '../../../social-network-adaptor/twitter.com/utils/user' +import { usePersonaConnectStatus } from '../../../components/DataSource/usePersonaConnectStatus' +import { BindingProof, fromHex, PersonaIdentifier, ProfileIdentifier, toBase64 } from '@masknet/shared-base' +import type { NextIDAvatarMeta } from '../types' +import { useI18N } from '../locales/i18n_generated' +import { context } from '../context' +import { PluginNFTAvatarRPC } from '../messages' +import { PLUGIN_ID, RSS3_KEY_SNS } from '../constants' +import { useSubscription } from 'use-subscription' +import Services from '../../../extension/service' + +const useStyles = makeStyles()((theme) => ({ + actions: { + padding: theme.spacing(0, 2, 2, 2), + }, + cancel: { + backgroundColor: theme.palette.background.default, + color: theme.palette.mode === 'dark' ? '#FFFFFF' : '#111418', + border: 'none', + '&:hover': { + border: 'none', + }, + }, +})) + +interface UploadAvatarDialogProps { + account?: string + isBindAccount?: boolean + image?: string | File + token?: ERC721TokenDetailed + proof?: BindingProof + onBack: () => void + onClose: () => void +} + +type AvatarInfo = TwitterBaseAPI.AvatarInfo & { avatarId: string } + +async function saveToRSS3(info: NextIDAvatarMeta, account: string, identifier: ProfileIdentifier) { + const avatar = await PluginNFTAvatarRPC.saveNFTAvatar( + account, + info, + identifier.network, + RSS3_KEY_SNS.TWITTER, + ).catch((error) => { + console.log(error) + return + }) + return avatar +} + +async function saveToNextID(info: NextIDAvatarMeta, persona?: PersonaIdentifier, proof?: BindingProof) { + if (!proof?.identity || !persona?.publicKeyAsHex) return + const payload = await NextIDStorage.getPayload( + persona.publicKeyAsHex, + proof?.platform, + proof?.identity, + info, + PLUGIN_ID, + ) + if (!payload.ok) { + return + } + const result = await Services.Identity.generateSignResult(persona, payload.val.signPayload) + if (!result) return + const response = await NextIDStorage.set( + payload.val.uuid, + persona.publicKeyAsHex, + toBase64(fromHex(result.signature.signature)), + proof.platform, + proof.identity, + payload.val.createdAt, + info, + PLUGIN_ID, + ) + return response.ok +} + +async function Save( + account: string, + isBindAccount: boolean, + token: ERC721TokenDetailed, + data: AvatarInfo, + persona: PersonaIdentifier, + proof: BindingProof, + identifier: ProfileIdentifier, +) { + if (!data) return false + + const info: NextIDAvatarMeta = { + nickname: data.nickname, + userId: data.userId, + imageUrl: data.imageUrl, + avatarId: data.avatarId, + address: token.contractDetailed.address, + tokenId: token.tokenId, + chainId: token.contractDetailed.chainId, + } + + if (isBindAccount) { + return saveToNextID(info, persona, proof) + } + return saveToRSS3(info, account, identifier) +} + +async function uploadAvatar(blob: Blob, userId: string): Promise { + try { + const media = await Twitter.uploadUserAvatar(userId, blob) + const data = await Twitter.updateProfileImage(userId, media.media_id_string) + if (!data) { + return + } + const avatarId = getAvatarId(data?.imageUrl ?? '') + return { ...data, avatarId } + } catch (err) { + return + } +} +export function UploadAvatarDialog(props: UploadAvatarDialogProps) { + const { image, account, token, onClose, onBack, proof, isBindAccount = false } = props + const { classes } = useStyles() + const identifier = useSubscription(context.currentVisitingProfile) + const [editor, setEditor] = useState(null) + const [scale, setScale] = useState(1) + const { showSnackbar } = useCustomSnackbar() + const [disabled, setDisabled] = useState(false) + const { currentConnectedPersona } = usePersonaConnectStatus() + const t = useI18N() + + const onSave = useCallback(() => { + if (!editor) return + editor.getImage().toBlob(async (blob) => { + if (!blob || !account || !token || !currentConnectedPersona?.linkedProfiles[0].identifier || !proof) return + setDisabled(true) + + const avatarData = await uploadAvatar(blob, currentConnectedPersona?.linkedProfiles[0].identifier.userId) + if (!avatarData) { + setDisabled(false) + return + } + + const response = await Save( + account, + isBindAccount, + token, + avatarData, + currentConnectedPersona.identifier, + proof, + currentConnectedPersona.linkedProfiles[0].identifier, + ) + + if (!response) { + showSnackbar(t.upload_avatar_failed_message(), { variant: 'error' }) + setDisabled(false) + return + } + showSnackbar(t.upload_avatar_success_message(), { variant: 'success' }) + location.reload() + onClose() + setDisabled(false) + }) + }, [account, editor, identifier, onClose, currentConnectedPersona, proof, isBindAccount]) + + if (!account || !image || !token || !proof) return null + + return ( + <> + + setEditor(e)} + image={image!} + border={50} + style={{ width: '100%', height: '100%' }} + scale={scale ?? 1} + rotate={0} + borderRadius={300} + /> + setScale(value as number)} + aria-label="Scale" + /> + + + + + + + ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx b/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx new file mode 100644 index 000000000000..14f261fad9cd --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx @@ -0,0 +1,114 @@ +import { WalletMessages } from '@masknet/plugin-wallet' +import { useRemoteControlledDialog } from '@masknet/shared-base-ui' +import { makeStyles, useStylesExtends } from '@masknet/theme' +import { resolveProviderHomeLink, useProviderType } from '@masknet/web3-shared-evm' +import { Box, Button, Link, Typography } from '@mui/material' +import { WalletIcon } from '../assets/wallet' +import LaunchIcon from '@mui/icons-material/Launch' +import { useI18N } from '../locales/i18n_generated' +import type { HTMLProps } from 'react' +import { ApplicationSmallIcon } from '../assets/application' +import { NetworkPluginID } from '@masknet/plugin-infra/web3' + +const useStyles = makeStyles()((theme) => ({ + root: { + background: + 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.2) 0%, rgba(249, 55, 55, 0.2) 100%), #FFFFFF', + borderRadius: 16, + padding: 14, + position: 'relative', + height: 196, + margin: theme.spacing(2), + }, + title: { + display: 'flex', + color: '#07101b', + }, + button: { + textAlign: 'center', + alignItems: 'center', + position: 'absolute', + bottom: 16, + width: '100%', + }, + link: { + padding: 0, + marginLeft: theme.spacing(0.5), + marginTop: 2, + color: '#6E767D', + }, + rectangle: { + marginLeft: theme.spacing(1), + marginTop: theme.spacing(6), + }, +})) + +interface NFTWalletConnectProps extends withClasses<'root'> {} + +export function NFTWalletConnect(props: NFTWalletConnectProps) { + const classes = useStylesExtends(useStyles(), props) + const providerType = useProviderType() + const t = useI18N() + + const { setDialog: openSelectProviderDialog } = useRemoteControlledDialog( + WalletMessages.events.selectProviderDialogUpdated, + ) + return ( + + + + + {t.application_dialog_title()} + + + + {t.provider_by()} + + + Mask Network + + + + + + + + + + + ) +} + +const useRectangleStyles = makeStyles()(() => ({ + rectangle: { + height: 8, + background: 'rgba(255, 255, 255, 0.5)', + borderRadius: 8, + }, +})) +interface RectangleProps extends HTMLProps {} + +export function Rectangle(props: RectangleProps) { + const { classes } = useRectangleStyles() + return ( +
+
+
+
+
+ ) +} diff --git a/packages/mask/src/plugins/Avatar/Application/WalletList.tsx b/packages/mask/src/plugins/Avatar/Application/WalletList.tsx new file mode 100644 index 000000000000..aebe972e725b --- /dev/null +++ b/packages/mask/src/plugins/Avatar/Application/WalletList.tsx @@ -0,0 +1,331 @@ +import { ImageIcon, useSnackbarCallback } from '@masknet/shared' +import { makeStyles, MaskColorVar, ShadowRootMenu, ShadowRootTooltip, useStylesExtends } from '@masknet/theme' +import { isSameAddress } from '@masknet/web3-shared-evm' +import { Button, Divider, IconProps, Link, ListItemIcon, MenuItem, Stack, Typography, useTheme } from '@mui/material' +import { memo, useCallback, useEffect, useState } from 'react' +import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown' +import { WalletSettingIcon } from '../assets/setting' +import { CheckedIcon, UncheckIcon } from '../assets/checked' +import { useRemoteControlledDialog } from '@masknet/shared-base-ui' +import { WalletMessages } from '@masknet/plugin-wallet' +import { NFTWalletConnect } from './WalletConnect' +import { BindingProof, PopupRoutes } from '@masknet/shared-base' +import { + NetworkPluginID, + useChainId, + useCurrentWeb3NetworkPluginID, + useNetworkDescriptor, + useReverseAddress, + useWeb3State, +} from '@masknet/plugin-infra/web3' +import { Services } from '../../../extension/service' +import { useI18N } from '../locales/i18n_generated' +import { useCopyToClipboard } from 'react-use' +import { LinkIcon } from '../assets/link' +import { CopyIcon } from '../assets/copy' +import classNames from 'classnames' +import { VerifyIcon } from '../assets/verify' +import { noop } from 'lodash-unified' +import { Verify2Icon } from '../assets/Verify2' +import { formatAddress } from '../utils' + +const useStyles = makeStyles()((theme) => ({ + root: { + borderRadius: 9999, + paddingLeft: 4, + paddingRight: 4, + cursor: 'pointer', + backgroundColor: theme.palette.mode === 'dark' ? '#15171A' : '#F6F8F8', + }, + wrapper: {}, + address: { + lineHeight: 1.5, + }, + copy: { + color: theme.palette.secondary.main, + }, + + icon: { + width: 24, + height: 24, + }, + iconShadow: { + filter: 'drop-shadow(0px 0px 6px rgba(28, 104, 243, 0.6))', + }, + change: { + marginLeft: theme.spacing(4), + backgroundColor: MaskColorVar.twitterButton, + borderRadius: 9999, + fontWeight: 600, + fontSize: 14, + }, + divider: { + borderColor: theme.palette.mode === 'dark' ? '#2F3336' : '#F2F5F6', + marginLeft: 16, + marginRight: 16, + }, + paper: { + backgroundColor: 'black', + width: 335, + }, +})) + +interface AddressNamesProps extends withClasses<'root'> { + onChange: (address: string) => void + account: string + wallets: BindingProof[] +} + +export function AddressNames(props: AddressNamesProps) { + const { onChange, account, wallets } = props + const classes = useStylesExtends(useStyles(), props) + const [anchorEl, setAnchorEl] = useState(null) + const onClose = () => setAnchorEl(null) + const onOpen = (event: React.MouseEvent) => setAnchorEl(event.currentTarget) + const t = useI18N() + const currentPluginId = useCurrentWeb3NetworkPluginID() + + const [selectedWallet, setSelectedWallet] = useState(account || wallets?.[0]?.identity || '') + const onClick = useCallback((address: string) => { + onChange(address) + setSelectedWallet(address) + onClose() + }, []) + + const theme = useTheme() + + useEffect(() => { + if (!account && !wallets?.[0]?.identity) return + setSelectedWallet(account || wallets?.[0]?.identity) + }, [account, wallets?.[0]?.identity]) + + const { setDialog: openSelectProviderDialog } = useRemoteControlledDialog( + WalletMessages.events.selectProviderDialogUpdated, + ) + const chainId = useChainId() + const openPopupsWindow = useCallback(() => { + Services.Helper.openPopupWindow(PopupRoutes.ConnectedWallets, { + chainId, + internal: true, + }) + }, [chainId]) + + const onConnectWallet = useCallback(() => { + openSelectProviderDialog({ open: true, pluginID: NetworkPluginID.PLUGIN_EVM }) + onClose() + }, [openSelectProviderDialog, onClose]) + + const walletItem = ( + selectedWallet: string, + wallet: string, + enableChange: boolean, + onClick: (wallet: string) => void, + onChange?: () => void, + verify?: boolean, + isETH?: boolean, + ) => ( + onClick(account)}> + + {selectedWallet === wallet ? ( + <> + + + ) : ( + + )} + + + {enableChange && ( + + )} + + ) + + if (!wallets.length && (currentPluginId !== NetworkPluginID.PLUGIN_EVM || !account)) return + + return ( + + + isSameAddress(x.identity, account)) + ? true + : currentPluginId === NetworkPluginID.PLUGIN_EVM + } + /> + + + + {account ? ( + walletItem( + selectedWallet, + account, + Boolean(account), + () => onClick(account), + onConnectWallet, + wallets.some((x) => isSameAddress(x.identity, account)), + wallets.some((x) => isSameAddress(x.identity, account)) + ? true + : currentPluginId === NetworkPluginID.PLUGIN_EVM, + ) + ) : ( + + + + )} + + {wallets + .sort((a, b) => Number.parseInt(b.created_at, 10) - Number.parseInt(a.created_at, 10)) + ?.filter((x) => !isSameAddress(x.identity, account)) + .map((x) => ( + <> + {walletItem( + selectedWallet, + x.identity, + false, + () => onClick(x.identity), + () => noop, + true, + true, + )} + + + ))} + + { + openPopupsWindow() + onClose() + }}> + + + + + {t.wallet_settings()} + + + + + + ) +} + +const useWalletUIStyles = makeStyles()((theme) => ({ + root: {}, + address: { + fontSize: 10, + }, + copy: { + fontSize: 16, + cursor: 'pointer', + }, + link: { + color: theme.palette.text.secondary, + lineHeight: 0, + }, + linkIcon: { + width: 16, + height: 16, + }, + walletName: { + color: theme.palette.mode === 'dark' ? '#D9D9D9' : '#0F1419', + }, + walletAddress: { + color: theme.palette.mode === 'dark' ? '#6E767D' : '#536471', + }, +})) + +interface WalletUIProps { + address: string + verify?: boolean + isETH?: boolean +} + +function WalletUI(props: WalletUIProps) { + const { Utils } = useWeb3State() + const { isETH, address, verify = false } = props + + const { classes } = useWalletUIStyles() + const chainId = useChainId() + const currentPluginId = useCurrentWeb3NetworkPluginID() + const networkDescriptor = useNetworkDescriptor(chainId, isETH ? NetworkPluginID.PLUGIN_EVM : currentPluginId) + const { value: domain } = useReverseAddress(address, NetworkPluginID.PLUGIN_EVM) + if (!address) return null + return ( + + + + + + {currentPluginId === NetworkPluginID.PLUGIN_EVM + ? domain ?? formatAddress(address, 4) + : formatAddress(address, 4)} + + {verify ? : null} + + + + {formatAddress(address, 4)} + + + + + + + + + ) +} + +interface CopyIconButtonProps extends IconProps { + text: string +} +const CopyIconButton = memo(({ text, ...props }) => { + const t = useI18N() + const theme = useTheme() + const [, copyToClipboard] = useCopyToClipboard() + const [open, setOpen] = useState(false) + + const onCopy = useSnackbarCallback({ + executor: async () => copyToClipboard(text), + deps: [], + successText: t.copy_success_of_wallet_address(), + }) + + return ( + {t.copied()}} + open={open} + onMouseLeave={() => setOpen(false)} + disableFocusListener + disableTouchListener> + + + ) +}) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/AddNFT.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/AddNFT.tsx index 97c7c707fe60..2dc642f172f3 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/AddNFT.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/AddNFT.tsx @@ -1,11 +1,11 @@ import { makeStyles } from '@masknet/theme' -import { ERC721TokenDetailed, isSameAddress, useAccount } from '@masknet/web3-shared-evm' -import { Button, DialogContent, Typography } from '@mui/material' +import { ChainId, ERC721TokenDetailed, isSameAddress, useAccount } from '@masknet/web3-shared-evm' +import { Button, DialogContent, InputBase, Typography } from '@mui/material' import { useCallback, useState } from 'react' import { InjectedDialog } from '@masknet/shared' -import { InputBox } from '../../../extension/options-page/DashboardComponents/InputBox' import { useI18N } from '../../../utils' import { createNFT } from '../utils' +import { WalletRPC } from '../../Wallet/messages' const useStyles = makeStyles()((theme) => ({ root: {}, @@ -17,6 +17,13 @@ const useStyles = makeStyles()((theme) => ({ input: { marginTop: theme.spacing(1), marginBottom: theme.spacing(1), + display: 'block', + width: '100%', + border: `1px solid ${theme.palette.mode === 'dark' ? '#2F3336' : '#EFF3F4'}`, + alignItems: 'center', + padding: theme.spacing(1), + boxSizing: 'border-box', + borderRadius: 8, }, message: { '&:before': { @@ -27,9 +34,12 @@ const useStyles = makeStyles()((theme) => ({ }, })) export interface AddNFTProps { + account?: string onClose: () => void - onAddClick: (token: ERC721TokenDetailed) => void + chainId?: ChainId + onAddClick?: (token: ERC721TokenDetailed) => void open: boolean + title?: string } export function AddNFT(props: AddNFTProps) { const { t } = useI18N() @@ -37,8 +47,8 @@ export function AddNFT(props: AddNFTProps) { const [address, setAddress] = useState('') const [tokenId, setTokenId] = useState('') const [message, setMessage] = useState('') - const { onClose, open, onAddClick } = props - const account = useAccount() + const { onClose, open, onAddClick, title, chainId, account } = props + const _account = useAccount() const onClick = useCallback(async () => { if (!address) { @@ -50,14 +60,18 @@ export function AddNFT(props: AddNFTProps) { return } - createNFT(address, tokenId) - .then((token) => { - if (!token || !isSameAddress(token?.info.owner, account)) { + createNFT(address, tokenId, chainId) + .then(async (token) => { + if (chainId && token && token.contractDetailed.chainId !== chainId) { + setMessage('chain does not match.') + return + } + if (!token || !isSameAddress(token?.info.owner, account ?? _account)) { setMessage(t('nft_owner_hint')) return } - - onAddClick(token) + await WalletRPC.addToken(token) + onAddClick?.(token) handleClose() }) .catch((error) => setMessage(t('nft_owner_hint'))) @@ -78,19 +92,31 @@ export function AddNFT(props: AddNFTProps) { } return ( - +
- onAddressChange(address)} /> + onAddressChange(e.target.value)} + />
- onTokenIdChange(tokenId)} /> + onTokenIdChange(e.target.value)} + />
{message ? ( - + {message} ) : null} diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarButton.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarButton.tsx index 93a23fbbab07..17c4115fe58f 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarButton.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTAvatarButton.tsx @@ -2,6 +2,7 @@ import { GearSettingsIcon } from '@masknet/icons' import { makeStyles, useStylesExtends } from '@masknet/theme' import { Typography } from '@mui/material' import { useI18N } from '../../../utils' +import { ApplicationSmallIcon } from '../assets/application' const useStyles = makeStyles()((theme) => ({ root: { @@ -10,11 +11,10 @@ const useStyles = makeStyles()((theme) => ({ justifyContent: 'center', alignItems: 'center', borderRadius: 9999, - paddingLeft: theme.spacing(1), - paddingRight: theme.spacing(1), - border: '1px solid', - backgroundColor: theme.palette.mode === 'dark' ? 'rgb(255, 255, 255)' : 'rgb(0, 0, 0)', - color: theme.palette.mode === 'dark' ? 'rgb(0, 0, 0)' : 'rgb(255, 255, 255)', + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + border: `1px solid ${theme.palette.mode === 'dark' ? '#2F3336' : '#EFF3F4'}`, + color: theme.palette.text.primary, cursor: 'pointer', }, icon: { @@ -25,10 +25,11 @@ const useStyles = makeStyles()((theme) => ({ text: { display: 'flex', alignItems: 'center', + marginLeft: 4, }, })) -interface NFTAvatarButtonProps extends withClasses<'root'> { +interface NFTAvatarButtonProps extends withClasses<'root' | 'text'> { onClick: () => void showSetting?: boolean } @@ -40,9 +41,9 @@ export function NFTAvatarButton(props: NFTAvatarButtonProps) { return (
+ - 🔥 - {t('nft_avatar')} + {t('nft_avatar')} {props.showSetting ? : null}
diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTBadge.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTBadge.tsx index 42a0d94f1b07..fc1cb595c64b 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTBadge.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTBadge.tsx @@ -34,6 +34,7 @@ export function NFTBadge(props: NFTBadgeProps) { const { value = { amount: '0', symbol: 'ETH', name: '', slug: '' }, loading } = useNFT( avatar.address, avatar.tokenId, + avatar.chainId, ) const { amount, symbol, name, slug } = value @@ -45,7 +46,10 @@ export function NFTBadge(props: NFTBadgeProps) { e.preventDefault() openWindow(resolveOpenSeaLink(avatar.address, avatar.tokenId)) }}> - + { userId: string @@ -23,7 +23,7 @@ const useStyles = makeStyles()(() => ({ export function NFTBadgeTimeline(props: NFTBadgeTimelineProps) { const { userId, avatarId, width, height, snsKey } = props - const { loading, value: _avatar } = useNFTAvatar(userId, snsKey) + const { loading, value: _avatar } = usePersonaNFTAvatar(userId, avatarId, snsKey) const [avatar, setAvatar] = useState() const [avatarId_, setAvatarId_] = useState('') const classes = useStylesExtends(useStyles(), props) diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTImage.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTImage.tsx index efd80e29ec7f..5a019eb2032c 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTImage.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/NFTImage.tsx @@ -1,11 +1,12 @@ import { makeStyles } from '@masknet/theme' import { ERC721TokenDetailed, isSameAddress } from '@masknet/web3-shared-evm' import classNames from 'classnames' +import { SelectedIcon } from '../assets/selected' const useStyles = makeStyles()((theme) => ({ imgBackground: { position: 'relative', - margin: theme.spacing(0.5, 1), + margin: theme.spacing(1.25, 1, 1.25, 1.5), borderRadius: '100%', display: 'flex', alignItems: 'center', @@ -13,10 +14,11 @@ const useStyles = makeStyles()((theme) => ({ }, icon: { position: 'absolute', - top: 5, - right: 5, - width: 24, - height: 24, + top: 2, + right: 2, + width: 20, + height: 20, + color: theme.palette.primary.main, }, image: { width: 97, @@ -25,11 +27,11 @@ const useStyles = makeStyles()((theme) => ({ borderRadius: '100%', boxSizing: 'border-box', '&:hover': { - border: `4px solid ${theme.palette.primary.main}`, + border: `1px solid ${theme.palette.primary.main}`, }, }, selected: { - border: `4px solid ${theme.palette.primary.main}`, + border: `1px solid ${theme.palette.primary.main}`, }, })) @@ -37,6 +39,7 @@ interface NFTImageProps { token: ERC721TokenDetailed selectedToken?: ERC721TokenDetailed onChange: (token: ERC721TokenDetailed) => void + showBadge?: boolean } function isSameNFT(a: ERC721TokenDetailed, b?: ERC721TokenDetailed) { @@ -48,7 +51,7 @@ function isSameNFT(a: ERC721TokenDetailed, b?: ERC721TokenDetailed) { } export function NFTImage(props: NFTImageProps) { - const { token, onChange, selectedToken } = props + const { token, onChange, selectedToken, showBadge = false } = props const { classes } = useStyles() return ( @@ -58,6 +61,7 @@ export function NFTImage(props: NFTImageProps) { src={token.info.imageURL} className={classNames(classes.image, isSameNFT(token, selectedToken) ? classes.selected : '')} /> + {showBadge && isSameNFT(token, selectedToken) ? : null}
) } diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/background/amount.png b/packages/mask/src/plugins/Avatar/SNSAdaptor/background/amount.png deleted file mode 100644 index 9df02cb6ee4abc4a3e0b0f10bbed07d2862309ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1246 zcmV<41R?v0P)Iqyt@Z_GwNJIE+x^+Cz`I!0#%lVDKE89tJxY{~1_Ea&`+`VubGT5C^=A*TpZw z0-po;05?Oi38%RggJ^~jWj38`eIr*&bt{<-$t8+ncaC_9N2u|t0`N|Ne23hx8973} zM~G;iI8_gwQFx-``=!hV@3jLIlXa z=5U@6T1rA-fM6m<;EZ$n;V52|g!~}E$*!m5XUhpuPa!)XRGG;%S5pu%i1RN481@y$ zkO49|rDw$`BMc#G2H75CUQkyjVH*?!T7(==gpt?C&rcvi&Tu?qzhTvSnh(2rOT3WZ2 zZf12twj$(5%MbQ|legnbWhBFBB+g9={=J(+BpE9Gj= z0}7e{2gyGq3Gfg0cn#l(zd!>5N5X#m^n!jKt7RNdA5=nQr~fNTsp77V<>+fxI;bf3 za9_NIKu8>m0*@T|%MaMf+iJO*b{CW~3-|Y&OV@6>7p=zyobx#X5b_riqMAF|B;*rt zIw8(QOHsn|1(3@R*s7@=j=D_PEQl2r~#$`%MaM<6U_6=OgIwR{XG=} z2SEtsl%S#kHZ5C#r3P%2eEy6_gdNQk1zIqiPBD_d?bre=S9%(b>(giYRE$JXY$+K| zr=sLFaMt!P4om@-nRFU?lF4SIti+xd=^0yQ45w33R+V$U!(0J?{VDGNBTqBgY_N^G zI{we_XKbYyPN#6>JNIwQAVPDjBC3y z_-;-K`T`PP&%KP>*{*kJ#3s_g#GexBgUb9~UsZ(oE0}eQkG}mw{D31NkP!AOyaI`r zp@1HvI4+*eDVjF`o|-HJF4VB@QQ|5$tcToX=JF(`fC_6EoV)i}_c`EvBp>C~+UK1> z<9f)qL*AHzyiP^GS9DL6K+ys_18fIuI<#jMetqz#c#KH=4+$r`sG}lX-2eap07*qo IM6N<$f=cyjQik`(D z%gk8OBYS9IbkCpjF}>r~q1@i1T`cl<6)Cj1LetaYvd4c%_I%8)fDIhF=K*f<23{0D z3k!S%;4SPg#fX~{D^i5cH^RttvGrcekQx=Uaj{fW?B!1QfZtH#IR)VLnD_&w+h@f> z@re`#5Q^bxKWh5P#)ghf{Jo7i>xN`-! zh!HrY^b{#&B;SZSLu`+Wi%3>;tfFQ>3nufu5%ie&zl-Fv8@S;vPq9w$IR^YSVi_dg0X`PU*R3y_GG(eO4{W7PFq~Gas zYP|~28*$+T=F1Cj3bu6-6__{08<1~;JbmfePOSA_{5$b>lIiag#XroH|C|B2Cdkv5 zo^4Xr$IolA%;QF~WTR2efpQ$tIK4-1B01#~SIz1T!^2;-;nJOg0;=*sSJjy}x5CwLdPn znVkV0;j3dzHd|c8N=%9=;cJ!`|1Z?|VRi;o3UA&@d^csX*@%lk;2^6RQ=$(ln}J9D z{ytt38fRJpXI%Dk$e*6Y^SZ=c17IV26kycw9ey_$i7BAM5-rxd_t@dPW9`I;8TLNz uUb@^pcXu$LT{zJl8h_$@yeu|26vzKnm2@Yav?C)T=$r)+{33%VaYYvqW=A|IC<=S|wxz46-8PmylsE zG7f$M9TW%gBI~%bNhYZz`*w=%qKev3)f;l!z>lg_^&IBMdsXidJbg^qrULrw*g=j1 zWOx-RfQ*Z>ox#PD8!Z!E~DqR4C}mbAdwI8SBre_jJrsBd(5tF{bGavoQKKKdhnO;c$BLoC? zhGiHytI^UgN{j>3q9fivWgi}3q$diNaU0L$UwjFH7lLmV@AE>-k;q&ra*sGBzW9xO zdW;bt*1rjXfAB39xJJYTkP$Sl=kq6R+7y-1m{}dIWA8%5x@p66#J1hYIoFzQ3-}L; za}3YbSj89ky7`5D65$N5Bg6G|Uy@jT%50nhOp4%J#jY{D!2<-r3nY1mkGEdyf8dzo zB?3;8v8vJVTSZ9-r!PgYkVQ*KAZxM1O##+ij8u&V+$y>n%^fAWRghV;BzCc zbYu|7loTsM5@I%vjLzfWEX_Sv7wfYY92u<8DPl>nBV^Nd-d&BBM!Hx;=5HEg0dRX$%b3@Xj}Co?BxpUVQLjB| z-zpwaVjPI@Iv1zZYe~EmW1GEaC8nC!O>EPpj#!d&d~HF4~-5bLJp=(HIq1D z0MLJhT|~GBffTWlps|{^*u7V*zNG1|ZN_KEbL+hjiMu(okoIrnQZ;1vj0R1wsdr;7 tDS)k(sELMs@aBDX_aQ7Q>J`>VLoomV002ovPDHLkV1gsp?c)Fd diff --git a/packages/mask/src/plugins/Avatar/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Avatar/SNSAdaptor/index.tsx index cbabb7a159eb..2f43bfb07606 100644 --- a/packages/mask/src/plugins/Avatar/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Avatar/SNSAdaptor/index.tsx @@ -1,9 +1,56 @@ -import type { Plugin } from '@masknet/plugin-infra' +import type { Plugin } from '@masknet/plugin-infra/content-script' +import { ApplicationEntry } from '@masknet/shared' +import { useState } from 'react' +import { NFTAvatarDialog } from '../Application/NFTAvatarsDialog' import { base } from '../base' +import { setupContext } from '../context' +import { Trans } from 'react-i18next' +import { PluginI18NFieldRender } from '@masknet/plugin-infra/content-script' +import { ApplicationIcon } from '../assets/application' const sns: Plugin.SNSAdaptor.Definition = { ...base, - init(signal) {}, + init(signal, context) { + setupContext(context) + }, + ApplicationEntries: [ + (() => { + const name = { fallback: 'NFT PFP' } + const icon = + const recommendFeature = { + description: , + backgroundGradient: 'linear-gradient(360deg, #FFECD2 -0.43%, #FCB69F 99.57%)', + } + return { + RenderEntryComponent(EntryComponentProps) { + const [open, setOpen] = useState(false) + return ( + <> + } + icon={icon} + recommendFeature={recommendFeature} + {...EntryComponentProps} + onClick={EntryComponentProps.onClick ?? (() => setOpen(true))} + tooltipHint={ + EntryComponentProps.tooltipHint ?? + (EntryComponentProps.disabled ? undefined : ) + } + /> + + setOpen(false)} /> + + ) + }, + appBoardSortingDefaultPriority: 3, + name, + icon, + ApplicationEntryID: base.ID, + nextIdRequired: true, + recommendFeature, + } + })(), + ], } export default sns diff --git a/packages/mask/src/plugins/Avatar/assets/Verify2.tsx b/packages/mask/src/plugins/Avatar/assets/Verify2.tsx new file mode 100644 index 000000000000..32b015145de2 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/Verify2.tsx @@ -0,0 +1,19 @@ +import { createIcon } from '@masknet/icons' +export const Verify2Icon = createIcon( + 'Verify2Icon', + + + + , + '0 0 20 20', +) diff --git a/packages/mask/src/plugins/Avatar/assets/application.tsx b/packages/mask/src/plugins/Avatar/assets/application.tsx new file mode 100644 index 000000000000..7dc9378ccd8a --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/application.tsx @@ -0,0 +1,63 @@ +import { createIcon } from '@masknet/icons' + +export const ApplicationIcon = createIcon( + 'ApplicationIcon', + + + + + + + + + + , + '0 0 24 24', +) + +export const ApplicationRoundIcon = createIcon( + 'ApplicationRoundIcon', + + + + + + + + + + , + '0 0 24 25', +) + +export const ApplicationSmallIcon = createIcon( + 'ApplicationSmallIcon', + + + , + '0 0 21 20', +) diff --git a/packages/mask/src/plugins/Avatar/assets/checked.tsx b/packages/mask/src/plugins/Avatar/assets/checked.tsx new file mode 100644 index 000000000000..4b3ce7be9630 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/checked.tsx @@ -0,0 +1,25 @@ +import { createIcon } from '@masknet/icons' + +export const CheckedIcon = createIcon( + 'CheckedIcon', + + + + , + '0 0 24 24', +) + +export const UncheckIcon = createIcon( + 'UncheckIcon', + + + , + '0 0 24 24', +) diff --git a/packages/mask/src/plugins/Avatar/assets/close.tsx b/packages/mask/src/plugins/Avatar/assets/close.tsx new file mode 100644 index 000000000000..cc9f93529008 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/close.tsx @@ -0,0 +1,12 @@ +import { createIcon } from '@masknet/icons' + +export const CloseIcon = createIcon( + 'CloseIcon', + + + , + '0 0 20 20', +) diff --git a/packages/mask/src/plugins/Avatar/assets/copy.tsx b/packages/mask/src/plugins/Avatar/assets/copy.tsx new file mode 100644 index 000000000000..bf8033061abf --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/copy.tsx @@ -0,0 +1,20 @@ +import { createIcon } from '@masknet/icons' + +export const CopyIcon = createIcon( + 'CopyIcon', + + + + , + '0 0 12 12', +) diff --git a/packages/mask/src/plugins/Avatar/assets/frame.tsx b/packages/mask/src/plugins/Avatar/assets/frame.tsx new file mode 100644 index 000000000000..7ea6f3306244 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/frame.tsx @@ -0,0 +1,44 @@ +import { SvgIcon, SvgIconProps } from '@mui/material' + +const svg = ( + + + + + + + + + + + + + + + + + + + +) + +export const FrameIcon = (props: SvgIconProps) => {svg} diff --git a/packages/mask/src/plugins/Avatar/assets/info.tsx b/packages/mask/src/plugins/Avatar/assets/info.tsx new file mode 100644 index 000000000000..d37e4a7b6f4f --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/info.tsx @@ -0,0 +1,26 @@ +import { createIcon } from '@masknet/icons' + +export const InfoIcon = createIcon( + 'InfoIcon', + + + + + , + '0 0 20 21', +) diff --git a/packages/mask/src/plugins/Avatar/assets/link.tsx b/packages/mask/src/plugins/Avatar/assets/link.tsx new file mode 100644 index 000000000000..80e7df2ab6ea --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/link.tsx @@ -0,0 +1,14 @@ +import { createIcon } from '@masknet/icons' + +export const LinkIcon = createIcon( + 'LinkIcon', + + + , + '0 0 16 16', +) diff --git a/packages/mask/src/plugins/Avatar/assets/more.tsx b/packages/mask/src/plugins/Avatar/assets/more.tsx new file mode 100644 index 000000000000..bae220e80a16 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/more.tsx @@ -0,0 +1,14 @@ +import { SvgIcon, SvgIconProps } from '@mui/material' + +const svg = ( + + + +) + +export const MoreIcon = (props: SvgIconProps) => {svg} diff --git a/packages/mask/src/plugins/Avatar/assets/nftavatar.png b/packages/mask/src/plugins/Avatar/assets/nftavatar.png new file mode 100644 index 0000000000000000000000000000000000000000..8ac22a7c4f2f33e781d6361b77fdb13b126d74de GIT binary patch literal 1007 zcmV7NQ%4kszq!749tMX9lci=F z6^Tk95R2^lhg59ImJNjkEU1L4s;bhch#&%#M>7Zs&tUX2Jo~*$po&?l=MWq`CF7+P#gX5`AJA6Ve|)>9)na0P!Q;YFV8~fCvf9?SojA9 z&&dJiry&w@3`)PdGW4zcAQ&!qG6GX$khWwM%sha5H)Xv05d3`)CT@Yd4tkH;>vRmt zF!arz$>7;P^y@R@vhMGY`O{IEf4J9Pr-sUNpUW-%ffJBivH#9fFXQkFDHGmiFx`+^ z)$4Tx%Eqi~S=q9^xK^dII+i0)?}Y{*#KIMTva^)MzjGblYHE;S!r}9P%F0^SF+Glp za(SSv)5qSxi@!A5+!`Gj>l(^2sPeMUqK=Pk)-y7e`*OdjJo}WsSrq7lu1|~0Saao2 zXAYI=zMR2?}2h{3}vx3Tn64iWv_q#jF4T002ovPDHLkV1iKV^P&I% literal 0 HcmV?d00001 diff --git a/packages/mask/src/plugins/Avatar/assets/point.tsx b/packages/mask/src/plugins/Avatar/assets/point.tsx new file mode 100644 index 000000000000..79dc37bd92df --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/point.tsx @@ -0,0 +1,12 @@ +import { createIcon } from '@masknet/icons' +export const PointIcon = createIcon( + 'PointIcon', + + + , + '0 0 9 9', +) diff --git a/packages/mask/src/plugins/Avatar/assets/selected.tsx b/packages/mask/src/plugins/Avatar/assets/selected.tsx new file mode 100644 index 000000000000..d6576f1d8a41 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/selected.tsx @@ -0,0 +1,16 @@ +import { createIcon } from '@masknet/icons' +export const SelectedIcon = createIcon( + 'SelectedIcon', + + + + , + '0 0 24 24', +) diff --git a/packages/mask/src/plugins/Avatar/assets/setting.tsx b/packages/mask/src/plugins/Avatar/assets/setting.tsx new file mode 100644 index 000000000000..25593367bade --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/setting.tsx @@ -0,0 +1,16 @@ +import { createIcon } from '@masknet/icons' + +export const WalletSettingIcon = createIcon( + 'WalletSettingIcon', + + + + , + '0 0 20 20', +) diff --git a/packages/mask/src/plugins/Avatar/assets/twitter.tsx b/packages/mask/src/plugins/Avatar/assets/twitter.tsx new file mode 100644 index 000000000000..a77f6b2beb40 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/twitter.tsx @@ -0,0 +1,20 @@ +import { createIcon } from '@masknet/icons' + +export const TwitterIcon = createIcon( + 'TwitterIcon', + + + + + , + '0 0 15 15', +) diff --git a/packages/mask/src/plugins/Avatar/assets/verify.tsx b/packages/mask/src/plugins/Avatar/assets/verify.tsx new file mode 100644 index 000000000000..d0987974f62d --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/verify.tsx @@ -0,0 +1,17 @@ +import { createIcon } from '@masknet/icons' +export const VerifyIcon = createIcon( + 'VerifyIcon', + + + + , + '0 0 16 16', +) diff --git a/packages/mask/src/plugins/Avatar/assets/wallet.tsx b/packages/mask/src/plugins/Avatar/assets/wallet.tsx new file mode 100644 index 000000000000..181d745050a2 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/assets/wallet.tsx @@ -0,0 +1,32 @@ +import { createIcon } from '@masknet/icons' + +export const WalletIcon = createIcon( + 'WalletIcon', + + + + + + , + '0 0 18 18', +) diff --git a/packages/mask/src/plugins/Avatar/base.ts b/packages/mask/src/plugins/Avatar/base.ts index 68359a709d4f..f75751d6eb86 100644 --- a/packages/mask/src/plugins/Avatar/base.ts +++ b/packages/mask/src/plugins/Avatar/base.ts @@ -1,5 +1,6 @@ import { PLUGIN_ID } from './constants' -import { CurrentSNSNetwork, Plugin } from '@masknet/plugin-infra' +import { languages } from './locales/languages' +import { Plugin, CurrentSNSNetwork } from '@masknet/plugin-infra' export const base: Plugin.Shared.Definition = { ID: PLUGIN_ID, @@ -14,10 +15,12 @@ export const base: Plugin.Shared.Definition = { type: 'opt-in', networks: { [CurrentSNSNetwork.Twitter]: true, - [CurrentSNSNetwork.Facebook]: true, - [CurrentSNSNetwork.Instagram]: true, + [CurrentSNSNetwork.Facebook]: false, + [CurrentSNSNetwork.Instagram]: false, }, }, target: 'stable', }, + + i18n: languages, } diff --git a/packages/mask/src/plugins/Avatar/constants.ts b/packages/mask/src/plugins/Avatar/constants.ts index 7d715a838706..952ee5b534ea 100644 --- a/packages/mask/src/plugins/Avatar/constants.ts +++ b/packages/mask/src/plugins/Avatar/constants.ts @@ -1,10 +1,10 @@ import { PluginId } from '@masknet/plugin-infra' +import { ChainId } from '@masknet/web3-shared-evm' export const NFT_AVATAR_JSON_SERVER = 'https://configuration.r2d2.to/com.maskbook.avatar.json' export const NFT_AVATAR_DB_NAME = 'com.maskbook.user' export const NFT_AVATAR_DB_NAME_STORAGE = 'com.maskbook.user.storage' -export const NFT_CONTRACT_JSON_VERIFIED_SERVER = 'https://configuration.r2d2.to/com.maskbook.verified_nft.json' export const PLUGIN_ID = PluginId.Avatar export const PLUGIN_NAME = 'Avatar' export const PLUGIN_DESCRIPTION = 'NFT Avatar' @@ -14,3 +14,10 @@ export enum RSS3_KEY_SNS { FACEBOOK = '_facebook_nfts', INSTAGRAM = '_instagram_nfts', } + +export enum Application_NFT_LIST_PAGE { + Application_nft_tab_eth_page = 'ETH', + Application_nft_tab_polygon_page = 'Polygon', +} + +export const SUPPORTED_CHAIN_IDS: ChainId[] = [ChainId.Mainnet, ChainId.Matic] diff --git a/packages/mask/src/plugins/Avatar/context.ts b/packages/mask/src/plugins/Avatar/context.ts new file mode 100644 index 000000000000..e6904a0c28f5 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/context.ts @@ -0,0 +1,5 @@ +import type { Plugin } from '@masknet/plugin-infra/content-script' +export let context: Plugin.SNSAdaptor.SNSAdaptorContext +export function setupContext(x: typeof context) { + context = x +} diff --git a/packages/mask/src/plugins/Avatar/hooks/useNFT.ts b/packages/mask/src/plugins/Avatar/hooks/useNFT.ts index c2be4ebcedc1..5e3c0344e83b 100644 --- a/packages/mask/src/plugins/Avatar/hooks/useNFT.ts +++ b/packages/mask/src/plugins/Avatar/hooks/useNFT.ts @@ -1,16 +1,32 @@ +import { ChainId } from '@masknet/web3-shared-evm' import { useAsyncRetry } from 'react-use' import type { NFT } from '../types' -import { getNFT } from '../utils' +import { getNFT, getNFTByChain } from '../utils' const NFTCache = new Map>() -export function useNFT(address: string, tokenId: string) { +export function useNFT(address: string, tokenId: string, chainId?: ChainId) { return useAsyncRetry(async () => { if (!address || !tokenId) return - let f = NFTCache.get(`${address}-${tokenId}`) + let f = NFTCache.get(`${address}-${tokenId}-${chainId ?? ChainId.Mainnet}`) if (!f) { - f = getNFT(address, tokenId) - NFTCache.set(`${address}-${tokenId}`, f) + f = _getNFT(address, tokenId, chainId ?? ChainId.Mainnet) + NFTCache.set(`${address}-${tokenId}-${chainId ?? ChainId.Mainnet}`, f) } return f - }, [address, tokenId, NFTCache, getNFT]) + }, [address, tokenId, NFTCache, getNFT, chainId]) +} + +async function _getNFT(address: string, tokenId: string, chainId: ChainId) { + if (chainId === ChainId.Mainnet) { + return getNFT(address, tokenId) + } + const nft = await getNFTByChain(address, tokenId, chainId) + return { + amount: '0', + name: nft?.contractDetailed.name ?? '', + symbol: nft?.contractDetailed.symbol ?? 'ETH', + image: nft?.info.imageURL ?? '', + owner: nft?.info.owner ?? '', + slug: '', + } } diff --git a/packages/mask/src/plugins/Avatar/hooks/usePersonaNFTAvatar.ts b/packages/mask/src/plugins/Avatar/hooks/usePersonaNFTAvatar.ts new file mode 100644 index 000000000000..73db8002948a --- /dev/null +++ b/packages/mask/src/plugins/Avatar/hooks/usePersonaNFTAvatar.ts @@ -0,0 +1,22 @@ +import { useAsyncRetry } from 'react-use' +import { activatedSocialNetworkUI } from '../../../social-network' +import type { RSS3_KEY_SNS } from '../constants' +import { PluginNFTAvatarRPC } from '../messages' +import { getNFTAvatarByUserId } from '../utils' + +export function usePersonaNFTAvatar(userId: string, avatarId: string, snsKey: RSS3_KEY_SNS) { + return useAsyncRetry(async () => { + const avatarMetaFromPersona = await getNFTAvatarByUserId(userId, avatarId) + if (avatarMetaFromPersona) return avatarMetaFromPersona + + const avatarMeta = await PluginNFTAvatarRPC.getNFTAvatar( + userId, + activatedSocialNetworkUI.networkIdentifier, + snsKey, + ) + + if (!avatarMeta) return + + return { ...avatarMeta, imageUrl: '', nickname: '' } + }, [userId]) +} diff --git a/packages/mask/src/plugins/Avatar/hooks/usePersonaVerified.ts b/packages/mask/src/plugins/Avatar/hooks/usePersonaVerified.ts new file mode 100644 index 000000000000..2df5604f5e0f --- /dev/null +++ b/packages/mask/src/plugins/Avatar/hooks/usePersonaVerified.ts @@ -0,0 +1,23 @@ +import type { NextIDPlatform } from '@masknet/shared-base' +import { NextIDProof } from '@masknet/web3-providers' +import { useAsyncRetry } from 'react-use' +import { useSubscription } from 'use-subscription' +import Services from '../../../extension/service' +import { activatedSocialNetworkUI } from '../../../social-network' +import { context } from '../context' + +export function usePersonaVerify() { + const platform = activatedSocialNetworkUI.configuration.nextIDConfig?.platform as NextIDPlatform + const visitingPersonaIdentifier = useSubscription(context.lastRecognizedProfile) + return useAsyncRetry(async () => { + if (!visitingPersonaIdentifier?.identifier) return + const persona = await Services.Identity.queryPersonaByProfile(visitingPersonaIdentifier.identifier) + if (!persona?.identifier.publicKeyAsHex) return + const isVerified = await NextIDProof.queryIsBound( + persona.identifier.publicKeyAsHex, + platform, + visitingPersonaIdentifier.identifier.userId, + ) + return { isVerified } + }, [platform, visitingPersonaIdentifier]) +} diff --git a/packages/mask/src/plugins/Avatar/hooks/usePersonas.ts b/packages/mask/src/plugins/Avatar/hooks/usePersonas.ts new file mode 100644 index 000000000000..c44a73ddc0b0 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/hooks/usePersonas.ts @@ -0,0 +1,38 @@ +import { NextIDPlatform } from '@masknet/shared-base' +import { NextIDProof } from '@masknet/web3-providers' +import { first } from 'lodash-unified' +import { useAsyncRetry } from 'react-use' +import { useSubscription } from 'use-subscription' +import { usePersonaConnectStatus } from '../../../components/DataSource/usePersonaConnectStatus' +import { activatedSocialNetworkUI } from '../../../social-network' +import { context } from '../context' +import { sortPersonaBindings } from '../utils' + +export function usePersonas(userId?: string) { + const personaConnectStatus = usePersonaConnectStatus() + const currentIdentifier = useSubscription(context.currentVisitingProfile) + const platform = activatedSocialNetworkUI.configuration.nextIDConfig?.platform as NextIDPlatform + const identifier = useSubscription(context.lastRecognizedProfile) + return useAsyncRetry(async () => { + if (!identifier?.identifier?.userId) return + const personaBindings = await NextIDProof.queryExistedBindingByPlatform( + platform, + userId?.toLowerCase() ?? identifier.identifier.userId.toLowerCase(), + ) + + const currentPersonaBinding = first( + personaBindings.sort((a, b) => + sortPersonaBindings(a, b, userId?.toLowerCase() ?? identifier.identifier?.userId.toLowerCase() ?? ''), + ), + ) + if (!currentPersonaBinding) return + + const isOwner = userId + ? currentIdentifier?.identifier?.toText() === userId.toLowerCase() + : currentIdentifier?.identifier && + identifier.identifier && + currentIdentifier?.identifier.toText() === identifier.identifier.toText() + const wallets = currentPersonaBinding?.proofs.filter((proof) => proof.platform === NextIDPlatform.Ethereum) + return { wallets, isOwner, binds: currentPersonaBinding, status: personaConnectStatus } + }, [currentIdentifier, identifier, personaConnectStatus.hasPersona, platform, userId]) +} diff --git a/packages/mask/src/plugins/Avatar/hooks/useTokenOwner.ts b/packages/mask/src/plugins/Avatar/hooks/useTokenOwner.ts new file mode 100644 index 000000000000..878dd96181cd --- /dev/null +++ b/packages/mask/src/plugins/Avatar/hooks/useTokenOwner.ts @@ -0,0 +1,45 @@ +import { + ChainId, + isSameAddress, + safeNonPayableTransactionCall, + useAccount, + useERC721TokenContract, +} from '@masknet/web3-shared-evm' +import { useAsyncRetry } from 'react-use' +import { activatedSocialNetworkUI } from '../../../social-network' +import { PluginNFTAvatarRPC } from '../messages' +import { getNFTByOpensea } from '../utils' +import { usePersonas } from './usePersonas' + +export function useTokenOwner(address: string, tokenId: string, chainId?: ChainId) { + const ERC721Contract = useERC721TokenContract(address, chainId ?? ChainId.Mainnet) + return useAsyncRetry(async () => { + if (!ERC721Contract || !tokenId) return + const nft = await getNFTByOpensea(address, tokenId) + if (nft) return nft + const allSettled = await Promise.allSettled([ + safeNonPayableTransactionCall(ERC721Contract?.methods.ownerOf(tokenId)), + safeNonPayableTransactionCall(ERC721Contract.methods.name()), + safeNonPayableTransactionCall(ERC721Contract.methods.symbol()), + ]) + const result = allSettled.map((x) => (x.status === 'fulfilled' ? x.value : undefined)) + return { owner: result[0], name: result[1], symbol: result[2] } + }, [ERC721Contract, tokenId]) +} + +export function useCheckTokenOwner(userId: string, owner?: string) { + const account = useAccount() + const { value: persona, loading } = usePersonas(userId) + const { value: address, loading: loadingAddress } = useAsyncRetry( + () => PluginNFTAvatarRPC.getAddress(userId, activatedSocialNetworkUI.networkIdentifier), + [userId], + ) + + return { + loading: loading || loadingAddress, + isOwner: Boolean( + (address && owner && isSameAddress(address, owner)) || + persona?.wallets.some((x) => isSameAddress(x.identity, owner)), + ), + } +} diff --git a/packages/mask/src/plugins/Avatar/locales/en-US.json b/packages/mask/src/plugins/Avatar/locales/en-US.json new file mode 100644 index 000000000000..a267c4b7a6bb --- /dev/null +++ b/packages/mask/src/plugins/Avatar/locales/en-US.json @@ -0,0 +1,27 @@ +{ + "application_dialog_title": "NFT PFP", + "application_edit_profile_dialog_title": "Edit Profile", + "persona_set_nft": "Set NFT PFPs", + "persona_verification_failed": "NFT PFP verification failed", + "cancel": "Cancel", + "save": "Save", + "change": "Change", + "connect_your_wallet": "Connect your wallet", + "upload_avatar_failed_message": "Sorry, failed to save NFT Avatar. Please set again.", + "upload_avatar_success_message": "Update NFT Avatar Success!", + "collectible_not_found": "Can' find it.", + "add_collectible": "Add Collectibles", + "set_avatar_title": "Set NFT Avatar", + "set_PFP_title": "Set NFT PFP", + "wallet_settings": "Wallet settings", + "persona_hint": "Customize NFT experience by connecting social accounts. Enjoy Web2 with a whole new Web3 vibe.", + "copy_success_of_wallet_address": "Copy wallet address successfully!", + "copied": "Copied", + "collectible_on_polygon": "Only NFTs on Ethereum are supported to preview. We are currently
working on supporting Polygon NFTs as well.
Please add your collectibles here.", + "collectible_no_eth": "No any collectible is available to preview. Please add your collectible here.", + "no_collectible_found": "No collectible found.", + "retry": "Retry", + "application_hint": "Socialize and show off your NFTs. People can bid,buy, view your valuable NFTs without leaving Twitter.", + "provider_by": "Provided by", + "wallet_non_evm_warning": "The NFT PFP feature currently supports only EVM chains. Support for other
chains will be added in the future." +} diff --git a/packages/mask/src/plugins/Avatar/locales/index.ts b/packages/mask/src/plugins/Avatar/locales/index.ts new file mode 100644 index 000000000000..d6ead60252e4 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/locales/index.ts @@ -0,0 +1,6 @@ +// This file is auto generated. DO NOT EDIT +// Run `npx gulp sync-languages` to regenerate. +// Default fallback language in a family of languages are chosen by the alphabet order +// To overwrite this, please overwrite packages/scripts/src/locale-kit-next/index.ts + +export * from './i18n_generated' diff --git a/packages/mask/src/plugins/Avatar/locales/languages.ts b/packages/mask/src/plugins/Avatar/locales/languages.ts new file mode 100644 index 000000000000..db91c03aa516 --- /dev/null +++ b/packages/mask/src/plugins/Avatar/locales/languages.ts @@ -0,0 +1,19 @@ +// This file is auto generated. DO NOT EDIT +// Run `npx gulp sync-languages` to regenerate. +// Default fallback language in a family of languages are chosen by the alphabet order +// To overwrite this, please overwrite packages/scripts/src/locale-kit-next/index.ts +import en_US from './en-US.json' +export const languages = { + en: en_US, +} +// @ts-ignore +if (import.meta.webpackHot) { + // @ts-ignore + import.meta.webpackHot.accept(['./en-US.json'], () => + globalThis.dispatchEvent?.( + new CustomEvent('MASK_I18N_HMR', { + detail: ['com.maskbook.avatar', { en: en_US }], + }), + ), + ) +} diff --git a/packages/mask/src/plugins/Avatar/types.ts b/packages/mask/src/plugins/Avatar/types.ts index f61a59d91dc9..8fddf38cc416 100644 --- a/packages/mask/src/plugins/Avatar/types.ts +++ b/packages/mask/src/plugins/Avatar/types.ts @@ -1,9 +1,11 @@ +import type { ChainId, ERC721TokenDetailed } from '@masknet/web3-shared-evm' + export interface AvatarMetaDB { userId: string tokenId: string address: string avatarId: string - updateFlag?: boolean + chainId?: ChainId } export interface NFT { @@ -14,3 +16,19 @@ export interface NFT { owner: string slug: string } + +export interface SelectTokenInfo { + account: string + token: ERC721TokenDetailed + image: string +} + +export interface TokenInfo { + address: string + tokenId: string +} + +export interface NextIDAvatarMeta extends AvatarMetaDB { + nickname: string + imageUrl: string +} diff --git a/packages/mask/src/plugins/Avatar/utils/index.ts b/packages/mask/src/plugins/Avatar/utils/index.ts index df7dfe24f71f..3c03939f0808 100644 --- a/packages/mask/src/plugins/Avatar/utils/index.ts +++ b/packages/mask/src/plugins/Avatar/utils/index.ts @@ -1,16 +1,49 @@ -import { isNull } from 'lodash-unified' -import { ChainId, NonFungibleAssetProvider, formatBalance } from '@masknet/web3-shared-evm' +import { first, isNull } from 'lodash-unified' +import { + ChainId, + NonFungibleAssetProvider, + formatBalance, + createContract, + createWeb3, + getERC721ContractDetailed, + getERC721TokenDetailedFromChain, + ERC721TokenDetailed, + getERC721TokenAssetFromChain, +} from '@masknet/web3-shared-evm' import { EVM_RPC } from '../../EVM/messages' import Services from '../../../extension/service' -import { getOrderUnitPrice, NonFungibleTokenAPI } from '@masknet/web3-providers' +import { getOrderUnitPrice, NextIDProof, NextIDStorage, NonFungibleTokenAPI } from '@masknet/web3-providers' import { ZERO } from '@masknet/web3-shared-base' import BigNumber from 'bignumber.js' +import { activatedSocialNetworkUI } from '../../../social-network' +import type { NextIDPersonaBindings, NextIDPlatform } from '@masknet/shared-base' +import type { NextIDAvatarMeta } from '../types' +import { PLUGIN_ID } from '../constants' +import type { ERC721 } from '@masknet/web3-contracts/types/ERC721' +import type { AbiItem } from 'web3-utils' +import ERC721ABI from '@masknet/web3-contracts/abis/ERC721.json' function getLastSalePrice(lastSale?: NonFungibleTokenAPI.AssetEvent | null) { if (!lastSale?.total_price || !lastSale?.payment_token?.decimals) return return formatBalance(lastSale.total_price, lastSale.payment_token.decimals) } +export async function getNFTByOpensea(address: string, tokenId: string) { + const asset = await EVM_RPC.getAsset({ + address, + tokenId, + chainId: ChainId.Mainnet, + provider: NonFungibleAssetProvider.OPENSEA, + }) + + if (!asset) return + return { + name: asset?.name ?? '', + symbol: asset?.desktopOrder?.payment_token_contract?.symbol ?? 'ETH', + owner: asset?.top_ownerships[0].owner.address ?? '', + } +} + export async function getNFT(address: string, tokenId: string) { const asset = await EVM_RPC.getAsset({ address, @@ -31,13 +64,48 @@ export async function getNFT(address: string, tokenId: string) { name: asset?.name ?? '', symbol: asset?.desktopOrder?.payment_token_contract?.symbol ?? 'ETH', image: asset?.image_url ?? '', - owner: asset?.top_ownerships[0].owner.address ?? '', + owner: asset?.top_ownerships?.[0]?.owner.address ?? '', slug: asset?.slug ?? '', } } -export async function createNFT(address: string, tokenId: string) { - return EVM_RPC.getNFT({ address, tokenId, chainId: ChainId.Mainnet, provider: NonFungibleAssetProvider.OPENSEA }) +export async function getNFTByChain( + address: string, + tokenId: string, + chainId: ChainId, +): Promise { + const web3 = createWeb3(Services.Ethereum.request, () => ({ + chainId, + })) + const contract = createContract(web3, address, ERC721ABI as AbiItem[]) + if (!contract) return + + const contractDetailed = await getERC721ContractDetailed(contract, address, chainId) + const tokenDetailedFromChain = await getERC721TokenDetailedFromChain(contractDetailed, contract, tokenId) + if (!tokenDetailedFromChain) return + const info = await getERC721TokenAssetFromChain(tokenDetailedFromChain?.info.tokenURI) + const owner = await contract.methods.ownerOf(tokenId).call() + if (info && tokenDetailedFromChain) { + tokenDetailedFromChain.info = { + ...info, + owner, + ...tokenDetailedFromChain.info, + hasTokenDetailed: true, + name: info?.name ?? tokenDetailedFromChain?.info.name ?? '', + } + } + return tokenDetailedFromChain +} + +export async function createNFT(address: string, tokenId: string, chainId?: ChainId) { + const token = await getNFTByChain(address, tokenId, chainId ?? ChainId.Mainnet) + if (token) return token + return EVM_RPC.getNFT({ + address, + tokenId, + chainId: chainId ?? ChainId.Mainnet, + provider: chainId === ChainId.Matic ? NonFungibleAssetProvider.NFTSCAN : NonFungibleAssetProvider.OPENSEA, + }) } export async function getImage(image: string): Promise { @@ -91,3 +159,39 @@ export function formatText(name: string, tokenId: string) { } return `${_name} #${token}` } + +export function formatTokenId(symbol: string, tokenId: string) { + const name = tokenId + return name.length > 18 ? name.slice(0, 12) + '...' : name +} + +export function formatAddress(address: string, size = 0) { + if (size === 0 || size >= 20) return address + return `${address.slice(0, Math.max(0, 2 + size))}...${address.slice(-size)}` +} + +export const sortPersonaBindings = (a: NextIDPersonaBindings, b: NextIDPersonaBindings, userId: string): number => { + const p_a = first(a.proofs.filter((x) => x.identity === userId.toLowerCase())) + const p_b = first(b.proofs.filter((x) => x.identity === userId.toLowerCase())) + + if (!p_a || !p_b) return 0 + if (p_a.created_at > p_b.created_at) return -1 + return 1 +} + +export async function getNFTAvatarByUserId(userId: string, avatarId: string): Promise { + const platform = activatedSocialNetworkUI.configuration.nextIDConfig?.platform as NextIDPlatform + const bindings = await NextIDProof.queryExistedBindingByPlatform(platform, userId.toLowerCase()) + + for (const binding of bindings.sort((a, b) => sortPersonaBindings(a, b, userId))) { + const response = await NextIDStorage.getByIdentity( + binding.persona, + platform, + userId.toLowerCase(), + PLUGIN_ID, + ) + if (!avatarId && response.ok) return response.val + if (response.ok && response.val.avatarId === avatarId) return response.val + } + return +} diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx index 2d7f34795942..ee079f50d649 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx @@ -92,6 +92,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(251, 49, 32, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent(EntryComponentProps) { @@ -101,6 +102,7 @@ const sns: Plugin.SNSAdaptor.Definition = { setOpen(true))} /> @@ -111,6 +113,7 @@ const sns: Plugin.SNSAdaptor.Definition = { appBoardSortingDefaultPriority: 12, icon, name: , + iconFilterColor, } })(), ], diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx b/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx index a25c322daaf4..defdb691d080 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx @@ -59,6 +59,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(56, 228, 239, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent(EntryComponentProps) { @@ -67,6 +68,7 @@ const sns: Plugin.SNSAdaptor.Definition = { {...EntryComponentProps} title={name} icon={icon} + iconFilterColor={iconFilterColor} onClick={ EntryComponentProps.onClick ?? (() => @@ -84,6 +86,7 @@ const sns: Plugin.SNSAdaptor.Definition = { appBoardSortingDefaultPriority: 3, marketListSortingPriority: 3, icon, + iconFilterColor, description: , category: 'dapp', name, @@ -93,6 +96,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(240, 51, 51, 0.3)' return { ApplicationEntryID: `${base.ID}_claim`, RenderEntryComponent(EntryComponentProps) { @@ -101,6 +105,7 @@ const sns: Plugin.SNSAdaptor.Definition = { <> setOpen(true))} @@ -112,6 +117,7 @@ const sns: Plugin.SNSAdaptor.Definition = { appBoardSortingDefaultPriority: 4, icon, name, + iconFilterColor, } })(), ], diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx index f40ea9b5b7f5..51fec2cdb271 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx @@ -33,6 +33,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(0, 87, 255, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent({ disabled }) { @@ -40,6 +41,7 @@ const sns: Plugin.SNSAdaptor.Definition = { openWindow('https://box.mask.io/#/')} /> @@ -51,6 +53,7 @@ const sns: Plugin.SNSAdaptor.Definition = { tutorialLink: 'https://realmasknetwork.notion.site/d0941687649a4ef7a38d71f23ecbe4da', description: , category: 'dapp', + iconFilterColor, name, } })(), diff --git a/packages/mask/src/plugins/Pets/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Pets/SNSAdaptor/index.tsx index 6ff2c8752464..915e88770a5c 100644 --- a/packages/mask/src/plugins/Pets/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Pets/SNSAdaptor/index.tsx @@ -22,6 +22,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(226, 0, 233, 0.2)' return { ApplicationEntryID: base.ID, RenderEntryComponent(EntryComponentProps) { @@ -32,6 +33,7 @@ const sns: Plugin.SNSAdaptor.Definition = { {...EntryComponentProps} title={name} icon={icon} + iconFilterColor={iconFilterColor} onClick={EntryComponentProps.onClick ?? openDialog} /> ) @@ -42,6 +44,7 @@ const sns: Plugin.SNSAdaptor.Definition = { description: , name, tutorialLink: 'https://twitter.com/NonFFriend', + iconFilterColor, category: 'dapp', } })(), diff --git a/packages/mask/src/plugins/Savings/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Savings/SNSAdaptor/index.tsx index 2683744563f4..2d3693295dac 100644 --- a/packages/mask/src/plugins/Savings/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Savings/SNSAdaptor/index.tsx @@ -13,6 +13,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(255, 83, 146, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent(EntryComponentProps) { @@ -22,6 +23,7 @@ const sns: Plugin.SNSAdaptor.Definition = { setOpen(true))} /> @@ -32,6 +34,7 @@ const sns: Plugin.SNSAdaptor.Definition = { appBoardSortingDefaultPriority: 7, icon, name, + iconFilterColor, } })(), ], diff --git a/packages/mask/src/plugins/Tips/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Tips/SNSAdaptor/index.tsx index 8a6f38fa2d51..8800886982fa 100644 --- a/packages/mask/src/plugins/Tips/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Tips/SNSAdaptor/index.tsx @@ -18,6 +18,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const name = base.name const icon = + const iconFilterColor = 'rgba(247, 147, 30, 0.3)' return { RenderEntryComponent(EntryComponentProps) { const [open, setOpen] = useState(false) @@ -27,6 +28,7 @@ const sns: Plugin.SNSAdaptor.Definition = { } {...EntryComponentProps} + iconFilterColor={iconFilterColor} icon={icon} onClick={EntryComponentProps.onClick ?? (() => setOpen(true))} /> @@ -38,6 +40,7 @@ const sns: Plugin.SNSAdaptor.Definition = { ApplicationEntryID: base.ID, icon, name, + iconFilterColor, appBoardSortingDefaultPriority: 8, nextIdRequired: true, } diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx index 2594adcb01a4..a6f9ab174c5c 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/index.tsx @@ -27,6 +27,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(247, 147, 30, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent(EntryComponentProps) { @@ -37,6 +38,7 @@ const sns: Plugin.SNSAdaptor.Definition = { {...EntryComponentProps} title={name} icon={icon} + iconFilterColor={iconFilterColor} onClick={EntryComponentProps.onClick ?? openDialog} /> ) @@ -48,6 +50,7 @@ const sns: Plugin.SNSAdaptor.Definition = { name, tutorialLink: 'https://realmasknetwork.notion.site/f2e7d081ee38487ca1db958393ac1edc', description: , + iconFilterColor, } })(), ], diff --git a/packages/mask/src/plugins/Transak/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Transak/SNSAdaptor/index.tsx index 17c21b451749..e378b0370b1d 100644 --- a/packages/mask/src/plugins/Transak/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Transak/SNSAdaptor/index.tsx @@ -17,6 +17,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = + const iconFilterColor = 'rgba(69, 110, 255, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent(EntryComponentProps) { @@ -26,6 +27,7 @@ const sns: Plugin.SNSAdaptor.Definition = { @@ -38,6 +40,7 @@ const sns: Plugin.SNSAdaptor.Definition = { description: , name, category: 'dapp', + iconFilterColor, } })(), ], diff --git a/packages/mask/src/resources/NFTAvatar.tsx b/packages/mask/src/resources/NFTAvatar.tsx new file mode 100644 index 000000000000..fd2272b36ca7 --- /dev/null +++ b/packages/mask/src/resources/NFTAvatar.tsx @@ -0,0 +1,28 @@ +import { SvgIconProps, SvgIcon } from '@mui/material' + +const svg = ( + + + + + + + + + + +) + +export const NFTAvatarsIcon = (props: SvgIconProps) => {svg} diff --git a/packages/mask/src/social-network-adaptor/facebook.com/utils/selector.ts b/packages/mask/src/social-network-adaptor/facebook.com/utils/selector.ts index a8db839959cf..4cadcc089825 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/utils/selector.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/utils/selector.ts @@ -71,7 +71,9 @@ export const searchFacebookProfileSettingButtonSelector = () => querySelector('[role="button"] [role="img"]').closest(10).querySelector('input[type="file"] ~ div').closest(2) export const searchFacebookEditProfileSelector = () => - querySelector('[role="button"] [role="img"]').closest(1).querySelector('i[data-visualcompletion="css-img"]') + querySelector('[role="main"] [role="button"] [role="img"]') + .closest(1) + .querySelector('i[data-visualcompletion="css-img"]') export const searchFacebookSaveAvatarButtonSelector = () => new LiveSelector() diff --git a/packages/mask/src/social-network-adaptor/twitter.com/collecting/identity.ts b/packages/mask/src/social-network-adaptor/twitter.com/collecting/identity.ts index 52eb21793cf8..3eca2d3fb5c0 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/collecting/identity.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/collecting/identity.ts @@ -8,6 +8,7 @@ import { searchSelfHandleSelector, searchSelfNicknameSelector, searchSelfAvatarSelector, + searchWatcherAvatarSelector, selfInfoSelectors, } from '../utils/selector' import { creator, SocialNetworkUI as Next } from '../../../social-network' @@ -48,9 +49,11 @@ function resolveLastRecognizedIdentityInner( ref: Next.CollectingCapabilities.IdentityResolveProvider['recognized'], cancel: AbortSignal, ) { - const task = isMobileTwitter ? recognizeMobile() : recognizeDesktop() - const assign = () => { - const { handle, nickname, avatar } = task.collect() + const assign = async () => { + await delay(5000) + const avatar = searchSelfAvatarSelector().evaluate()?.getAttribute('src') ?? '' + const handle = searchSelfHandleSelector().evaluate()?.textContent?.trim()?.replace(/^@/, '') + const nickname = searchSelfNicknameSelector().evaluate()?.textContent?.trim() ?? '' if (handle) { ref.value = { @@ -60,14 +63,29 @@ function resolveLastRecognizedIdentityInner( } } } - const watcher = task.watcher - .addListener('onAdd', () => assign()) - .addListener('onChange', () => assign()) - .startWatch({ - childList: true, - subtree: true, + + const createWatcher = (selector: LiveSelector) => { + const watcher = new MutationObserverWatcher(selector) + .addListener('onAdd', () => assign()) + .addListener('onChange', () => assign()) + .startWatch({ + childList: true, + subtree: true, + attributes: true, + attributeFilter: ['src'], + }) + + window.addEventListener('locationchange', assign) + cancel.addEventListener('abort', () => { + window.removeEventListener('locationchange', assign) + watcher.stopWatch() }) - cancel.addEventListener('abort', () => watcher.stopWatch()) + } + + assign() + + createWatcher(searchSelfHandleSelector()) + createWatcher(searchWatcherAvatarSelector()) } function resolveLastRecognizedIdentityMobileInner( @@ -99,7 +117,7 @@ function resolveCurrentVisitingIdentityInner( const avatarSelector = searchAvatarSelector() const avatarMetaSelector = searchAvatarMetaSelector() const assign = async () => { - await delay(500) + await delay(5000) const bio = getBio() const homepage = getPersonalHomepage() const nickname = getNickname() diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarEditProfile.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarEditProfile.tsx index a13a3ebff6f7..b74ec72baf40 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarEditProfile.tsx +++ b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarEditProfile.tsx @@ -1,6 +1,9 @@ import { MutationObserverWatcher } from '@dimensiondev/holoflows-kit' +import { CrossIsolationMessages } from '@masknet/shared-base' import { makeStyles } from '@masknet/theme' -import { useState, useEffect } from 'react' +import { useState, useEffect, useCallback } from 'react' +import { usePersonaConnectStatus } from '../../../../components/DataSource/usePersonaConnectStatus' +import { NFTAvatarDialog } from '../../../../plugins/Avatar/Application/NFTAvatarsDialog' import { NFTAvatarButton } from '../../../../plugins/Avatar/SNSAdaptor/NFTAvatarButton' import { startWatch, createReactRootShadowed, useLocationChange } from '../../../../utils' import { searchEditProfileSelector } from '../../utils/selector' @@ -17,6 +20,8 @@ interface StyleProps { minHeight: number fontSize: number marginBottom: number + border: string + color: string } const useStyles = makeStyles()((theme, props) => ({ root: { @@ -24,7 +29,11 @@ const useStyles = makeStyles()((theme, props) => ({ fontSize: props.fontSize, marginBottom: props.marginBottom, marginTop: 1, - marginRight: theme.spacing(0.5), + marginRight: theme.spacing(2), + border: props.border, + }, + text: { + color: props.color, }, })) @@ -34,16 +43,43 @@ export function openNFTAvatarSettingDialog() { } function OpenNFTAvatarEditProfileButtonInTwitter() { - const [style, setStyle] = useState({ minHeight: 32, fontSize: 14, marginBottom: 11 }) + const [style, setStyle] = useState({ + minHeight: 32, + fontSize: 14, + marginBottom: 11, + border: 'none', + color: '', + }) + const [open, setOpen] = useState(false) + + const personaConnectStatus = usePersonaConnectStatus() + + const createOrConnectPersona = useCallback(() => { + personaConnectStatus.action?.() + }, [personaConnectStatus]) + + const verifyPersona = useCallback(() => { + CrossIsolationMessages.events.verifyNextID.sendToAll(undefined) + }, []) + + const clickHandler = (() => { + if (personaConnectStatus.hasPersona === false) return createOrConnectPersona + if (personaConnectStatus.connected === false) return verifyPersona + return + })() const setStyleFromEditProfileSelector = () => { const editDom = searchEditProfileSelector().evaluate() if (!editDom) return + const css = window.getComputedStyle(editDom) + const spanCss = window.getComputedStyle(editDom.querySelector('span')!) setStyle({ minHeight: Number(css.minHeight.replace('px', '')), fontSize: Number(css.fontSize.replace('px', '')), marginBottom: Number(css.marginBottom.replace('px', '')), + border: css.border, + color: spanCss.color, }) } @@ -52,5 +88,13 @@ function OpenNFTAvatarEditProfileButtonInTwitter() { useLocationChange(() => setStyleFromEditProfileSelector()) const { classes } = useStyles(style) - return + return ( + <> + setOpen(true))} + /> + setOpen(false)} /> + + ) } diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx index cefd28736ec5..1fb279a56651 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx +++ b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/NFTAvatarInTwitter.tsx @@ -6,7 +6,6 @@ import { useEffect, useMemo, useRef, useState } from 'react' import { useCurrentVisitingIdentity } from '../../../../components/DataSource/useActivatedUI' import { resolveOpenSeaLink, useWallet } from '@masknet/web3-shared-evm' import type { AvatarMetaDB } from '../../../../plugins/Avatar/types' -import { useNFTAvatar } from '../../../../plugins/Avatar/hooks' import { getAvatarId } from '../../utils/user' import { PluginNFTAvatarRPC } from '../../../../plugins/Avatar/messages' import { NFTBadge } from '../../../../plugins/Avatar/SNSAdaptor/NFTBadge' @@ -16,6 +15,7 @@ import { rainbowBorderKeyFrames } from '../../../../plugins/Avatar/SNSAdaptor/Ra import { trim } from 'lodash-unified' import { RSS3_KEY_SNS } from '../../../../plugins/Avatar/constants' import { openWindow } from '@masknet/shared-base-ui' +import { usePersonaNFTAvatar } from '../../../../plugins/Avatar/hooks/usePersonaNFTAvatar' export function injectNFTAvatarInTwitter(signal: AbortSignal) { const watcher = new MutationObserverWatcher(searchTwitterAvatarSelector()) @@ -52,7 +52,11 @@ function NFTAvatarInTwitter() { const borderElement = useRef() const identity = useCurrentVisitingIdentity() const wallet = useWallet() - const { value: _avatar } = useNFTAvatar(identity.identifier?.userId, RSS3_KEY_SNS.TWITTER) + const { value: _avatar } = usePersonaNFTAvatar( + identity.identifier?.userId ?? '', + getAvatarId(identity.avatar ?? ''), + RSS3_KEY_SNS.TWITTER, + ) const [avatar, setAvatar] = useState() const windowSize = useWindowSize() const location = useLocation() @@ -196,7 +200,7 @@ function NFTAvatarInTwitter() { if (!avatar || !linkParentDom || !showAvatar) return const handler = () => { - openWindow(resolveOpenSeaLink(avatar.address, avatar.tokenId)) + openWindow(resolveOpenSeaLink(avatar.address, avatar.tokenId, avatar.chainId)) } linkParentDom.addEventListener('click', handler) diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/ProfileNFTAvatar.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/ProfileNFTAvatar.tsx deleted file mode 100644 index d5f59f5f0b5c..000000000000 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/NFT/ProfileNFTAvatar.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { MutationObserverWatcher } from '@dimensiondev/holoflows-kit' -import { makeStyles } from '@masknet/theme' -import { useEffect, useState } from 'react' -import { createReactRootShadowed, MaskMessages, NFTAvatarEvent, startWatch } from '../../../../utils' -import { - searchTwitterAvatarOpenFilesSelector, - searchProfessionalButtonSelector, - searchProfileSaveSelector, - searchProfileSetAvatarSelector, -} from '../../utils/selector' -import { useCurrentVisitingIdentity } from '../../../../components/DataSource/useActivatedUI' -import { getAvatarId } from '../../utils/user' -import { toPNG } from '../../../../plugins/Avatar/utils' -import type { ERC721TokenDetailed } from '@masknet/web3-shared-evm' -import { NFTAvatar } from '../../../../plugins/Avatar/SNSAdaptor/NFTAvatar' -import { hookInputUploadOnce } from '@masknet/injected-script' - -export async function injectProfileNFTAvatarInTwitter(signal: AbortSignal) { - const watcher = new MutationObserverWatcher(searchProfileSetAvatarSelector()) - startWatch(watcher, signal) - createReactRootShadowed(watcher.firstDOMProxy.afterShadow, { signal }).render() -} - -const useStyles = makeStyles<{ - paddingTop: string - paddingLeft: string - paddingRight: string - paddingBottom: string -}>()((theme, props) => ({ - root: { - paddingLeft: props.paddingLeft, - paddingTop: props.paddingTop, - paddingRight: props.paddingRight, - paddingBottom: props.paddingBottom, - }, -})) - -function getStyles() { - const ele = searchProfessionalButtonSelector().evaluate() - - if (!ele) - return { - paddingTop: '11px', - paddingLeft: '14px', - paddingRight: '14px', - paddingBottom: '14px', - } - const style = window.getComputedStyle(ele) - return { - paddingTop: style.paddingTop, - paddingLeft: style.paddingLeft, - paddingRight: style.paddingRight, - paddingBottom: style.paddingBottom, - } -} - -async function changeImageToActiveElements(image: File | Blob): Promise { - const imageBuffer = await image.arrayBuffer() - hookInputUploadOnce('image/png', 'avatar.png', new Uint8Array(imageBuffer)) - ;(searchTwitterAvatarOpenFilesSelector().evaluate()[0]?.parentElement?.children[0] as HTMLElement)?.click() -} - -function NFTAvatarInTwitter() { - const { classes } = useStyles(getStyles()) - const identity = useCurrentVisitingIdentity() - - const [avatarEvent, setAvatarEvent] = useState() - - const onChange = async (token: ERC721TokenDetailed) => { - if (!token.info.imageURL) return - const image = await toPNG(token.info.imageURL) - if (!image) return - if (!identity.identifier) return - changeImageToActiveElements(image) - - setAvatarEvent({ - userId: identity.identifier.userId, - avatarId: getAvatarId(identity.avatar ?? ''), - address: token.contractDetailed.address, - tokenId: token.tokenId, - }) - } - - const handler = () => { - if (!identity.identifier) return - MaskMessages.events.NFTAvatarUpdated.sendToLocal( - avatarEvent ?? { - userId: identity.identifier.userId, - avatarId: getAvatarId(identity.avatar ?? ''), - address: '', - tokenId: '', - }, - ) - setAvatarEvent(undefined) - } - - useEffect(() => { - const profileSave = searchProfileSaveSelector().evaluate() - if (!profileSave) return - profileSave.addEventListener('click', handler) - return () => profileSave.removeEventListener('click', handler) - }, [handler]) - - return -} diff --git a/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts b/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts index f7cd82bef7eb..a51c4e3bcb8a 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts @@ -29,7 +29,6 @@ import { EnhanceableSite, NextIDPlatform, ProfileIdentifier } from '@masknet/sha import { makeStyles } from '@masknet/theme' import { injectNFTAvatarInTwitter } from './injection/NFT/NFTAvatarInTwitter' import { injectOpenTipButtonOnProfile } from './injection/Tip/index' -import { injectProfileNFTAvatarInTwitter } from './injection/NFT/ProfileNFTAvatar' import { injectUserNFTAvatarAtTwitter } from './injection/NFT/Avatar' import { injectOpenNFTAvatarEditProfileButton, openNFTAvatarSettingDialog } from './injection/NFT/NFTAvatarEditProfile' import { injectUserNFTAvatarAtTweet } from './injection/NFT/TweetNFTAvatar' @@ -51,7 +50,7 @@ const useInjectedDialogClassesOverwriteTwitter = makeStyles()((theme) => { alignItems: 'center', }, paper: { - width: '600px !important', + width: '612px !important', maxWidth: 'none', boxShadow: 'none', backgroundImage: 'none', @@ -179,7 +178,6 @@ const twitterUI: SocialNetworkUI.Definition = { userBadge: injectMaskUserBadgeAtTwitter, commentComposition: undefined, userAvatar: injectUserNFTAvatarAtTwitter, - enhancedProfileNFTAvatar: injectProfileNFTAvatarInTwitter, profileAvatar: injectNFTAvatarInTwitter, profileTip: injectOpenTipButtonOnProfile, openNFTAvatar: injectOpenNFTAvatarEditProfileButton, diff --git a/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts b/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts index 9ef0a8486c87..197b49efeb03 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts @@ -255,6 +255,9 @@ export const searchSelfNicknameSelector = () => { ) } +export const searchWatcherAvatarSelector = () => + querySelector('[data-testid="SideNav_AccountSwitcher_Button"] img') + export const searchSelfAvatarSelector = () => { return querySelector( [ diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 6c2f87585320..15aa383c7e6b 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -335,6 +335,8 @@ export namespace Plugin.SNSAdaptor { description?: I18NFieldOrReactNode + iconFilterColor?: string + tutorialLink?: string /** * Does the application listed in the DAPP list diff --git a/packages/plugins/CrossChainBridge/src/SNSAdaptor/index.tsx b/packages/plugins/CrossChainBridge/src/SNSAdaptor/index.tsx index 09511e7f3052..d0fb13072772 100644 --- a/packages/plugins/CrossChainBridge/src/SNSAdaptor/index.tsx +++ b/packages/plugins/CrossChainBridge/src/SNSAdaptor/index.tsx @@ -13,6 +13,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = { i18nKey: '__plugin_name', fallback: 'Cross-chain' } + const iconFilterColor = 'rgba(183, 212, 255, 0.3)' return { ApplicationEntryID: base.ID, RenderEntryComponent({ disabled }) { @@ -22,6 +23,7 @@ const sns: Plugin.SNSAdaptor.Definition = { } disabled={disabled} + iconFilterColor={iconFilterColor} icon={icon} onClick={() => setOpen(true)} /> @@ -32,6 +34,7 @@ const sns: Plugin.SNSAdaptor.Definition = { appBoardSortingDefaultPriority: 5, name, icon, + iconFilterColor, } })(), ], diff --git a/packages/plugins/FileService/src/SNSAdaptor/index.tsx b/packages/plugins/FileService/src/SNSAdaptor/index.tsx index 94d5a656f151..5a6fd71d8c6f 100644 --- a/packages/plugins/FileService/src/SNSAdaptor/index.tsx +++ b/packages/plugins/FileService/src/SNSAdaptor/index.tsx @@ -37,22 +37,26 @@ const definition: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = { i18nKey: '__plugin_name', fallback: 'File Service' } + const iconFilterColor = 'rgba(247, 147, 30, 0.3)' return { ApplicationEntryID: base.ID, - RenderEntryComponent({ disabled }) { + RenderEntryComponent(EntryComponentProps) { return ( } - disabled={disabled} + {...EntryComponentProps} icon={icon} - onClick={() => - CrossIsolationMessages.events.requestComposition.sendToLocal({ - reason: 'timeline', - open: true, - options: { - startupPlugin: base.ID, - }, - }) + iconFilterColor={iconFilterColor} + onClick={ + EntryComponentProps.onClick ?? + (() => + CrossIsolationMessages.events.requestComposition.sendToLocal({ + reason: 'timeline', + open: true, + options: { + startupPlugin: base.ID, + }, + })) } /> ) @@ -67,6 +71,7 @@ const definition: Plugin.SNSAdaptor.Definition = { 'Decentralized file storage, permanently. Upload and share files to your Mask friends on top of Arweave Network.', }, name, + iconFilterColor, tutorialLink: 'https://realmasknetwork.notion.site/8c8fe1efce5a48b49739a38f4ea8c60f', } })(), diff --git a/packages/plugins/GoPlusSecurity/src/SNSAdaptor/index.tsx b/packages/plugins/GoPlusSecurity/src/SNSAdaptor/index.tsx index 1a7a963e487b..f4ce3d0d3d84 100644 --- a/packages/plugins/GoPlusSecurity/src/SNSAdaptor/index.tsx +++ b/packages/plugins/GoPlusSecurity/src/SNSAdaptor/index.tsx @@ -13,6 +13,7 @@ const sns: Plugin.SNSAdaptor.Definition = { (() => { const icon = const name = { i18nKey: '__plugin_name', fallback: 'Check Security' } + const iconFilterColor = 'rgba(69, 110, 255, 0.3)' return { ApplicationEntryID: base.ID, @@ -23,6 +24,7 @@ const sns: Plugin.SNSAdaptor.Definition = { } disabled={disabled} + iconFilterColor={iconFilterColor} icon={icon} onClick={() => setOpen(true)} /> @@ -32,6 +34,7 @@ const sns: Plugin.SNSAdaptor.Definition = { }, name, icon, + iconFilterColor, appBoardSortingDefaultPriority: 13, marketListSortingPriority: 16, } diff --git a/packages/shared/src/UI/components/ApplicationEntry/index.tsx b/packages/shared/src/UI/components/ApplicationEntry/index.tsx index 56a241599d1b..96192f8a466d 100644 --- a/packages/shared/src/UI/components/ApplicationEntry/index.tsx +++ b/packages/shared/src/UI/components/ApplicationEntry/index.tsx @@ -3,89 +3,105 @@ import type { Plugin } from '@masknet/plugin-infra' import { makeStyles, ShadowRootTooltip } from '@masknet/theme' import { Typography } from '@mui/material' -const useStyles = makeStyles<{ disabled: boolean }>()((theme, { disabled }) => ({ - applicationBox: { - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - backgroundColor: theme.palette.background.default, - borderRadius: '8px', - height: 100, - }, - applicationBoxHover: { - cursor: 'pointer', - '&:hover': { - transform: 'scale(1.02) translateY(-2px)', - background: theme.palette.mode === 'light' ? theme.palette.common.white : theme.palette.common.black, - boxShadow: theme.palette.mode === 'light' ? '0 5px 8px rgba(0, 0, 0, 0.05)' : 'none', +const useStyles = makeStyles<{ disabled: boolean; iconFilterColor?: string }>()( + (theme, { disabled, iconFilterColor }) => ({ + applicationBox: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: theme.palette.background.default, + borderRadius: '8px', + height: 100, }, - }, - applicationImg: { - width: 36, - height: 36, - marginBottom: 10, - }, - title: { - fontSize: 15, - }, - disabled: { - opacity: 0.4, - cursor: 'default !important', - pointerEvent: 'none', - }, - iconWrapper: { - '> *': { + applicationBoxHover: { + cursor: 'pointer', + '&:hover': { + transform: 'scale(1.02) translateY(-2px)', + background: theme.palette.mode === 'light' ? theme.palette.common.white : theme.palette.common.black, + boxShadow: theme.palette.mode === 'light' ? '0px 5px 8px rgba(0, 0, 0, 0.05)' : 'none', + }, + }, + applicationImg: { width: 36, height: 36, + marginBottom: 10, + }, + title: { + fontSize: 15, + }, + disabled: { + opacity: 0.4, + cursor: 'default !important', + pointerEvent: 'none', + }, + iconWrapper: { + '> *': { + width: 36, + height: 36, + }, + ...(iconFilterColor + ? { filter: `drop-shadow(0px 6px 12px ${iconFilterColor})`, backdropFilter: 'blur(16px)' } + : {}), + }, + tooltip: { + backgroundColor: theme.palette.mode === 'light' ? theme.palette.common.black : theme.palette.common.white, + }, + tooltipHint: { + fontSize: 14, + color: theme.palette.mode === 'light' ? theme.palette.common.white : theme.palette.common.black, + }, + arrow: { + color: theme.palette.mode === 'light' ? theme.palette.common.black : theme.palette.common.white, + }, + recommendFeatureApplicationBox: { + width: 260, + minWidth: 260, + height: 97, + marginRight: 12, + cursor: 'pointer', + display: 'inline-flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + padding: 10, + borderRadius: 8, + }, + recommendFeatureAppIconWrapper: { + marginRight: 12, + '> *': { + width: 48, + height: 48, + }, + }, + recommendFeatureAppListItemName: { + fontSize: 14, + fontWeight: 500, + cursor: disabled ? 'default' : 'pointer', + color: theme.palette.common.white, }, - }, - recommendFeatureApplicationBox: { - width: 225, - minWidth: 225, - height: 97, - marginRight: 12, - cursor: 'pointer', - display: 'inline-flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - padding: 10, - borderRadius: 8, - }, - recommendFeatureAppIconWrapper: { - marginRight: 12, - '> *': { - width: 48, - height: 48, + recommendFeatureAppListItemDescription: { + fontSize: 12, + fontWeight: 500, + cursor: disabled ? 'default' : 'pointer', + color: theme.palette.common.white, }, - }, - recommendFeatureAppListItemName: { - fontSize: 14, - fontWeight: 500, - cursor: disabled ? 'default' : 'pointer', - color: theme.palette.common.white, - }, - recommendFeatureAppListItemDescription: { - fontSize: 12, - fontWeight: 500, - cursor: disabled ? 'default' : 'pointer', - color: theme.palette.common.white, - }, -})) + }), +) interface ApplicationEntryProps { icon: React.ReactNode title: React.ReactNode disabled?: boolean recommendFeature?: Plugin.SNSAdaptor.ApplicationEntry['recommendFeature'] - tooltipHint?: string + iconFilterColor?: string + tooltipHint?: string | React.ReactElement onClick: () => void } export function ApplicationEntry(props: ApplicationEntryProps) { - const { title, onClick, disabled = false, icon, tooltipHint, recommendFeature } = props - const { classes } = useStyles({ disabled }) + const { title, onClick, disabled = false, icon, tooltipHint, recommendFeature, iconFilterColor } = props + const { classes } = useStyles({ disabled, iconFilterColor }) const jsx = recommendFeature ? (
{tooltipHint}}> + title={{tooltipHint}}> {jsx} ) : ( diff --git a/packages/shared/src/contexts/components/InjectedDialog.tsx b/packages/shared/src/contexts/components/InjectedDialog.tsx index f62c51d8da29..a81a51cf4ea5 100644 --- a/packages/shared/src/contexts/components/InjectedDialog.tsx +++ b/packages/shared/src/contexts/components/InjectedDialog.tsx @@ -152,7 +152,11 @@ export function InjectedDialog(props: InjectedDialogProps) { aria-label={t.dialog_dismiss()} onClick={onClose}> diff --git a/packages/web3-providers/src/NextID/kv.ts b/packages/web3-providers/src/NextID/kv.ts index d9dcaefcaf4f..08e323a8f23f 100644 --- a/packages/web3-providers/src/NextID/kv.ts +++ b/packages/web3-providers/src/NextID/kv.ts @@ -4,7 +4,7 @@ import urlcat from 'urlcat' import type { NextIDStoragePayload, NextIDPlatform } from '@masknet/shared-base' import { fetchJSON } from './helper' -import type { Result } from 'ts-results' +import { Err, Ok, Result } from 'ts-results' import type { NextIDBaseAPI } from '../types' import { KV_BASE_URL_DEV, KV_BASE_URL_PROD } from './constants' @@ -29,10 +29,30 @@ export class NextIDStorageAPI implements NextIDBaseAPI.Storage { * @param personaPublicKey * */ + async getByIdentity( + personaPublicKey: string, + platform: NextIDPlatform, + identity: string, + pluginId: string, + ): Promise> { + const response = await fetchJSON<{ + persona: string + proofs: { + platform: NextIDPlatform + identity: string + content: Record + }[] + }>(urlcat(BASE_URL, '/v1/kv', { persona: personaPublicKey })) + if (!response.ok) return Err('User not found') + + const data = + response.val.proofs?.filter((x) => x.identity === identity.toLowerCase() && x.platform === platform) ?? [] + if (!data.length) return Err('Not found') + return Ok(data[0].content[pluginId]) + } async get(personaPublicKey: string): Promise> { return fetchJSON(urlcat(BASE_URL, '/v1/kv', { persona: personaPublicKey })) } - /** * Get signature payload for updating * @param personaPublicKey diff --git a/packages/web3-providers/src/twitter/index.ts b/packages/web3-providers/src/twitter/index.ts index 8b38595f9116..83533ae075ea 100644 --- a/packages/web3-providers/src/twitter/index.ts +++ b/packages/web3-providers/src/twitter/index.ts @@ -128,7 +128,7 @@ export class TwitterAPI implements TwitterBaseAPI.Provider { } } - async uploadUserAvatar(image: File | Blob) { + async uploadUserAvatar(screenName: string, image: File | Blob): Promise { // INIT const initURL = `${UPLOAD_AVATAR_URL}?command=INIT&total_bytes=${image.size}&media_type=${encodeURIComponent( image.type, @@ -151,21 +151,43 @@ export class TwitterAPI implements TwitterBaseAPI.Provider { // FINALIZE const finalizeURL = `${UPLOAD_AVATAR_URL}?command=FINALIZE&media_id=${mediaId}` - const data = await request<{ - media_id: number - media_id_string: string - size: number - image: { - image_type: string - w: number - h: number - } - }>(finalizeURL, { + return request(finalizeURL, { method: 'POST', credentials: 'include', }) + } + async updateProfileImage(screenName: string, media_id_str: string): Promise { + const { bearerToken, queryToken, csrfToken } = await getTokens() + const headers = { + authorization: `Bearer ${bearerToken}`, + 'x-csrf-token': csrfToken, + 'content-type': 'application/json', + 'x-twitter-auth-type': 'OAuth2Session', + 'x-twitter-active-user': 'yes', + referer: `https://twitter.com/${screenName}`, + } + const updateProfileImageURL = 'https://twitter.com/i/api/1.1/account/update_profile_image.json' + if (!bearerToken || !queryToken || !csrfToken) return + const response = await fetch( + urlcat(updateProfileImageURL, { + media_id: media_id_str, + skip_status: 1, + return_user: true, + }), + { + method: 'POST', + credentials: 'include', + headers, + }, + ) - return data + const updateInfo = await response.json() + return { + imageUrl: updateInfo.profile_image_url_https, + mediaId: updateInfo.id_str, + nickname: updateInfo.name, + userId: updateInfo.screen_name, + } } } diff --git a/packages/web3-providers/src/types.ts b/packages/web3-providers/src/types.ts index 124a9110374d..e33ba8eed336 100644 --- a/packages/web3-providers/src/types.ts +++ b/packages/web3-providers/src/types.ts @@ -9,13 +9,7 @@ import type { } from '@masknet/web3-shared-evm' import type { CurrencyType } from '@masknet/plugin-infra/web3' import type { Result } from 'ts-results' -import type { - NextIDAction, - NextIDStoragePayload, - NextIDPayload, - NextIDPlatform, - NextIDStorageInfo, -} from '@masknet/shared-base' +import type { NextIDAction, NextIDStoragePayload, NextIDPayload, NextIDPlatform } from '@masknet/shared-base' export namespace ExplorerAPI { export type Transaction = Web3Transaction & { @@ -328,7 +322,13 @@ export namespace NextIDBaseAPI { patchData: unknown, pluginId: string, ): Promise> - get(key: string): Promise> + getByIdentity( + key: string, + platform: NextIDPlatform, + identity: string, + pluginId: string, + ): Promise> + get(key: string): Promise> getPayload( personaPublicKey: string, platform: NextIDPlatform, @@ -470,11 +470,28 @@ export namespace TwitterBaseAPI { }[] } } + export interface AvatarInfo { + nickname: string + userId: string + imageUrl: string + mediaId: string + } export interface Settings { screen_name: string } + export interface TwitterResult { + media_id: number + media_id_string: string + size: number + image: { + image_type: string + w: number + h: number + } + } + export interface Provider { getSettings: () => Promise getUserNftContainer: (screenName: string) => Promise< @@ -485,6 +502,8 @@ export namespace TwitterBaseAPI { } | undefined > + uploadUserAvatar: (screenName: string, image: Blob | File) => Promise + updateProfileImage: (screenName: string, media_id_str: string) => Promise } } diff --git a/packages/web3-shared/evm/contracts/useERC721TokenContract.ts b/packages/web3-shared/evm/contracts/useERC721TokenContract.ts index 49e4e3d2c548..75a1c81d892d 100644 --- a/packages/web3-shared/evm/contracts/useERC721TokenContract.ts +++ b/packages/web3-shared/evm/contracts/useERC721TokenContract.ts @@ -2,7 +2,8 @@ import type { AbiItem } from 'web3-utils' import ERC721ABI from '@masknet/web3-contracts/abis/ERC721.json' import type { ERC721 } from '@masknet/web3-contracts/types/ERC721' import { useContract } from '../hooks/useContract' +import type { ChainId } from '../types' -export function useERC721TokenContract(address?: string) { - return useContract(address, ERC721ABI as AbiItem[]) +export function useERC721TokenContract(address?: string, chainId?: ChainId) { + return useContract(address, ERC721ABI as AbiItem[], chainId) } diff --git a/packages/web3-shared/evm/hooks/useCollectibles.ts b/packages/web3-shared/evm/hooks/useCollectibles.ts index 57f342812b1b..89e9f992cb60 100644 --- a/packages/web3-shared/evm/hooks/useCollectibles.ts +++ b/packages/web3-shared/evm/hooks/useCollectibles.ts @@ -1,6 +1,6 @@ -import type { ChainId, ERC721TokenCollectionInfo, ERC721TokenDetailed } from '../types' +import { ChainId, ERC721TokenCollectionInfo, ERC721TokenDetailed } from '../types' import { useWeb3Context } from '../context' -import { uniqWith } from 'lodash-unified' +import { noop, uniqWith } from 'lodash-unified' import { isSameAddress } from '../utils' import { useSocket } from './useSocket' import { useMemo } from 'react' @@ -54,9 +54,9 @@ export function useCollectibles(address: string, chainId: ChainId | null, depend (a, b) => isSameAddress(a.contractDetailed.address, b.contractDetailed.address) && a.tokenId === b.tokenId, ) return { - data: all as ERC721TokenDetailed[], + data: chainId === ChainId.Mainnet ? (all as ERC721TokenDetailed[]) : [], state, - error, - retry, + error: chainId === ChainId.Mainnet ? error : undefined, + retry: chainId === ChainId.Mainnet ? retry : noop, } } diff --git a/packages/web3-shared/evm/hooks/useERC721TokenDetailed.ts b/packages/web3-shared/evm/hooks/useERC721TokenDetailed.ts index 6dd2eb3d033f..cc9397ca4313 100644 --- a/packages/web3-shared/evm/hooks/useERC721TokenDetailed.ts +++ b/packages/web3-shared/evm/hooks/useERC721TokenDetailed.ts @@ -117,6 +117,7 @@ export async function getERC721TokenAssetFromChain(tokenURI?: string): Promise=6.12'} dependencies: '@0xproject/typescript-typings': 0.3.2 @@ -1519,7 +1523,7 @@ packages: dev: false /@0xproject/types/0.7.0: - resolution: {integrity: sha1-+tE5Je6SrU7hmAZopcsr7U3Kq48=} + resolution: {integrity: sha512-LlTnq7raPnCioCokNy5CLDxZJeg3KtcHT4PBJD6BDiXYtNJxBWvL7/jr6JiwdjReNg7ihGi1265VKfFX7qukRw==} engines: {node: '>=6.12'} dependencies: '@types/node': 17.0.31 @@ -1527,7 +1531,7 @@ packages: dev: false /@0xproject/typescript-typings/0.3.2: - resolution: {integrity: sha1-q8NgtEGv2pkxAEUMqDad+r91k2s=} + resolution: {integrity: sha512-sHwGTxerREyQhyXFHhZRHvy7PlbBUjsoVbxhf5f+9JasC+IhQ2Nv4uJFjOo16uUPPp7l+lsRUvK/ZwrdGRbFBA==} engines: {node: '>=6.12'} dependencies: '@0xproject/types': 0.7.0 @@ -1761,9 +1765,24 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-explode-assignable-expression': 7.16.7 - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 dev: true + /@babel/helper-compilation-targets/7.16.7: + resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/compat-data': 7.17.0 + '@babel/helper-validator-option': 7.16.7 + browserslist: 4.20.3 + semver: 6.3.0 + dev: false + /@babel/helper-compilation-targets/7.16.7_@babel+core@7.17.10: resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} engines: {node: '>=6.9.0'} @@ -1796,6 +1815,22 @@ packages: semver: 6.3.0 dev: true + /@babel/helper-compilation-targets/7.17.10_@babel+core@7.17.9: + resolution: {integrity: sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/compat-data': 7.17.10 + '@babel/core': 7.17.9 + '@babel/helper-validator-option': 7.16.7 + browserslist: 4.20.3 + semver: 6.3.0 + dev: true + /@babel/helper-compilation-targets/7.17.7_@babel+core@7.17.10: resolution: {integrity: sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==} engines: {node: '>=6.9.0'} @@ -1907,10 +1942,10 @@ packages: optional: true dependencies: '@babel/core': 7.17.10 - '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.10 + '@babel/helper-compilation-targets': 7.17.10_@babel+core@7.17.10 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/traverse': 7.17.9 + '@babel/traverse': 7.17.10 debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.22.0 @@ -1928,10 +1963,10 @@ packages: optional: true dependencies: '@babel/core': 7.17.9 - '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.9 + '@babel/helper-compilation-targets': 7.17.10_@babel+core@7.17.9 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/traverse': 7.17.9 + '@babel/traverse': 7.17.10 debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.22.0 @@ -1940,6 +1975,26 @@ packages: - supports-color dev: true + /@babel/helper-define-polyfill-provider/0.2.4: + resolution: {integrity: sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==} + peerDependencies: + '@babel/core': ^7.4.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/helper-compilation-targets': 7.16.7 + '@babel/helper-module-imports': 7.16.0 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/traverse': 7.16.10 + debug: 4.3.3 + lodash.debounce: 4.0.8 + resolve: 1.22.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/helper-define-polyfill-provider/0.2.4_@babel+core@7.17.10: resolution: {integrity: sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==} peerDependencies: @@ -2013,7 +2068,7 @@ packages: resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 dev: true /@babel/helper-function-name/7.16.7: @@ -2037,7 +2092,7 @@ packages: resolution: {integrity: sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.8 + '@babel/types': 7.17.10 dev: false /@babel/helper-hoist-variables/7.16.7: @@ -2064,7 +2119,7 @@ packages: resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 /@babel/helper-module-transforms/7.17.7: resolution: {integrity: sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==} @@ -2108,7 +2163,7 @@ packages: dependencies: '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-wrap-function': 7.16.8 - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 transitivePeerDependencies: - supports-color dev: true @@ -2130,7 +2185,7 @@ packages: resolution: {integrity: sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 dev: true /@babel/helper-skip-transparent-expression-wrappers/7.16.0: @@ -2165,8 +2220,8 @@ packages: dependencies: '@babel/helper-function-name': 7.17.9 '@babel/template': 7.16.7 - '@babel/traverse': 7.17.9 - '@babel/types': 7.17.0 + '@babel/traverse': 7.17.10 + '@babel/types': 7.17.10 transitivePeerDependencies: - supports-color dev: true @@ -2203,6 +2258,8 @@ packages: resolution: {integrity: sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==} engines: {node: '>=6.0.0'} hasBin: true + dependencies: + '@babel/types': 7.17.10 dev: false /@babel/parser/7.17.10: @@ -4203,6 +4260,8 @@ packages: dependencies: '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 + '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.10 + '@babel/types': 7.17.10 dev: true /@babel/plugin-transform-react-pure-annotations/7.16.7_@babel+core@7.17.10: @@ -4285,6 +4344,25 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true + /@babel/plugin-transform-runtime/7.15.0: + resolution: {integrity: sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/helper-module-imports': 7.16.0 + '@babel/helper-plugin-utils': 7.16.5 + babel-plugin-polyfill-corejs2: 0.2.3 + babel-plugin-polyfill-corejs3: 0.2.4 + babel-plugin-polyfill-regenerator: 0.2.3 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/plugin-transform-runtime/7.15.0_@babel+core@7.17.10: resolution: {integrity: sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==} engines: {node: '>=6.9.0'} @@ -4742,7 +4820,7 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.10 '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.10 - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 esutils: 2.0.3 dev: true @@ -4758,7 +4836,7 @@ packages: '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.9 '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.9 - '@babel/types': 7.17.0 + '@babel/types': 7.17.10 esutils: 2.0.3 dev: true @@ -4898,7 +4976,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/parser': 7.17.3 + '@babel/parser': 7.17.10 '@babel/types': 7.17.0 /@babel/traverse/7.16.10: @@ -10822,6 +10900,12 @@ packages: resolution: {integrity: sha1-7ihweulOEdK4J7y+UnC86n8+ce4=} dev: true + /@types/keyv/3.1.4: + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + dependencies: + '@types/node': 17.0.31 + dev: false + /@types/lodash-es/4.17.6: resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} dependencies: @@ -10932,6 +11016,12 @@ packages: /@types/range-parser/1.2.4: resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} + /@types/react-avatar-editor/10.3.6: + resolution: {integrity: sha512-2r9+WYriqXIyjOTxy/DSiCUhr2TBiYD4Gzbyych1WUEwdPboNj0JRz9B5868TwiGgKD61jdWYyKy/OutHs7L6A==} + dependencies: + '@types/react': 18.0.9 + dev: false + /@types/react-avatar-editor/12.0.0: resolution: {integrity: sha512-835jSnCdQ2Kgrtz2sTYKMv9YSGJG0j2vd8C0sxWtYJoYOmYPs8nt25rTsbCOha3SVzWNiuw1TOQCVqN0iBQgrw==} dependencies: @@ -11021,6 +11111,12 @@ packages: '@types/node': 17.0.31 dev: true + /@types/responselike/1.0.0: + resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} + dependencies: + '@types/node': 17.0.31 + dev: false + /@types/retry/0.12.1: resolution: {integrity: sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==} dev: true @@ -12913,6 +13009,21 @@ packages: '@babel/core': 7.17.10 dev: true + /babel-plugin-polyfill-corejs2/0.2.3: + resolution: {integrity: sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/compat-data': 7.16.8 + '@babel/helper-define-polyfill-provider': 0.2.4 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: false + /babel-plugin-polyfill-corejs2/0.2.3_@babel+core@7.17.10: resolution: {integrity: sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==} peerDependencies: @@ -12971,7 +13082,7 @@ packages: dependencies: '@babel/core': 7.17.10 '@babel/helper-define-polyfill-provider': 0.1.5_@babel+core@7.17.10 - core-js-compat: 3.22.2 + core-js-compat: 3.22.4 transitivePeerDependencies: - supports-color dev: true @@ -12986,11 +13097,25 @@ packages: dependencies: '@babel/core': 7.17.9 '@babel/helper-define-polyfill-provider': 0.1.5_@babel+core@7.17.9 - core-js-compat: 3.22.2 + core-js-compat: 3.22.4 transitivePeerDependencies: - supports-color dev: true + /babel-plugin-polyfill-corejs3/0.2.4: + resolution: {integrity: sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/helper-define-polyfill-provider': 0.2.4 + core-js-compat: 3.20.1 + transitivePeerDependencies: + - supports-color + dev: false + /babel-plugin-polyfill-corejs3/0.2.4_@babel+core@7.17.10: resolution: {integrity: sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==} peerDependencies: @@ -13036,6 +13161,19 @@ packages: - supports-color dev: true + /babel-plugin-polyfill-regenerator/0.2.3: + resolution: {integrity: sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/helper-define-polyfill-provider': 0.2.4 + transitivePeerDependencies: + - supports-color + dev: false + /babel-plugin-polyfill-regenerator/0.2.3_@babel+core@7.17.10: resolution: {integrity: sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==} peerDependencies: @@ -17048,7 +17186,7 @@ packages: resolution: {integrity: sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==} engines: {node: '>=8.3.0'} dependencies: - '@babel/traverse': 7.17.9 + '@babel/traverse': 7.17.10 '@babel/types': 7.17.0 c8: 7.11.2 transitivePeerDependencies: @@ -18718,6 +18856,8 @@ packages: resolution: {integrity: sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==} engines: {node: '>=4'} dependencies: + '@types/keyv': 3.1.4 + '@types/responselike': 1.0.0 decompress-response: 3.3.0 duplexer3: 0.1.4 get-stream: 3.0.0 @@ -18740,6 +18880,8 @@ packages: dependencies: '@sindresorhus/is': 0.14.0 '@szmarczak/http-timer': 1.1.2 + '@types/keyv': 3.1.4 + '@types/responselike': 1.0.0 cacheable-request: 6.1.0 decompress-response: 3.3.0 duplexer3: 0.1.4 @@ -24309,6 +24451,25 @@ packages: webpack: 4.46.0 dev: true + /react-avatar-editor/12.0.0: + resolution: {integrity: sha512-l7NrN8CXlUXbMhnbkuduAtR3+AlDz+DzYWlYBNr7q+rNeJMZlv26ap3Dk/D1WK/MPlnoS33iITlhLkuDsYQpug==} + peerDependencies: + react: ^0.14.0 || ^17.0.0 || 18 + react-dom: '>=0.14.0 || 18' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + '@babel/plugin-transform-runtime': 7.15.0 + '@babel/runtime': 7.16.5 + prop-types: 15.8.0 + transitivePeerDependencies: + - '@babel/core' + - supports-color + dev: false + /react-avatar-editor/12.0.0_@babel+core@7.17.10: resolution: {integrity: sha512-l7NrN8CXlUXbMhnbkuduAtR3+AlDz+DzYWlYBNr7q+rNeJMZlv26ap3Dk/D1WK/MPlnoS33iITlhLkuDsYQpug==} peerDependencies: @@ -27050,6 +27211,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: + acorn: 8.7.1 commander: 2.20.3 source-map: 0.6.1 source-map-support: 0.5.21 @@ -27065,6 +27227,7 @@ packages: acorn: optional: true dependencies: + acorn: 8.7.1 commander: 2.20.3 source-map: 0.7.3 source-map-support: 0.5.21 From 9cbd36f4ed94b440c2b0a1c998a6a24c35b6f05b Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Wed, 18 May 2022 13:53:03 +0800 Subject: [PATCH 9/9] fix: build errors --- cspell.json | 2 - .../InjectedComponents/ProfileTabContent.tsx | 1 - .../Avatar/Application/NFTAvatarsDialog.tsx | 2 +- .../Avatar/Application/NFTListDialog.tsx | 354 ++-- .../Avatar/Application/NFTListPage.tsx | 35 +- .../Avatar/Application/WalletConnect.tsx | 27 +- .../plugins/Avatar/Application/WalletList.tsx | 16 +- .../src/plugins/Avatar/SNSAdaptor/AddNFT.tsx | 2 +- .../plugins/Avatar/SNSAdaptor/NFTImage.tsx | 8 +- .../src/plugins/Avatar/hooks/useTokenOwner.ts | 13 +- .../src/plugins/Avatar/locales/en-US.json | 2 +- .../mask/src/plugins/Avatar/utils/index.ts | 14 +- .../Collectible/SNSAdaptor/ActionBar.tsx | 5 +- .../FindTruman/SNSAdaptor/FindTruman.tsx | 5 +- .../src/plugins/Furucombo/UI/PoolView.tsx | 7 +- .../ITO/SNSAdaptor/hooks/useAvailability.ts | 6 +- .../hooks/useAvailabilityComputed.ts | 12 +- .../SNSAdaptor/components/PreviewCard.tsx | 2 +- .../mask/src/plugins/PoolTogether/base.tsx | 2 +- .../RedPacket/SNSAdaptor/RedPacket/index.tsx | 8 +- .../SNSAdaptor/hooks/useAvailability.ts | 8 +- .../hooks/useAvailabilityComputed.ts | 2 +- .../Savings/SNSAdaptor/SavingsDialog.tsx | 3 +- .../plugins/Snapshot/SNSAdaptor/Snapshot.tsx | 5 +- .../Transak/hooks/useTransakAllowanceCoin.ts | 4 +- .../GasSettingDialog/GasSetting1559.tsx | 19 +- .../GasSettingDialog/Prior1559GasSetting.tsx | 8 +- .../Wallet/SNSAdaptor/RenameWalletDialog.tsx | 78 - .../Wallet/SNSAdaptor/SelectWalletDialog.tsx | 83 - .../WalletConnectQRCodeDialog/index.tsx | 106 - .../TransactionDescription.tsx | 167 -- .../SNSAdaptor/WalletStatusDialog/index.tsx | 4 +- .../src/web3/UI/EthereumChainBoundary.tsx | 9 +- .../UI/EthereumWalletConnectedBoundary.tsx | 30 +- .../src/hooks/useActivatedPluginWeb3State.ts | 2 +- .../src/hooks/useAvailablePlugins.ts | 3 +- .../plugin-infra/src/web3-helpers/index.ts | 2 +- .../plugin-infra/src/web3-state/Identity.ts | 1 + packages/plugin-infra/src/web3/Context.tsx | 4 +- .../src/web3/useFungibleTokenPrice.ts | 2 +- .../src/web3/useNativeTokenBalance.ts | 5 +- .../plugin-infra/src/web3/useSocketOnce.ts | 2 +- .../src/web3/useWeb3Connection.ts | 2 +- .../plugins/EVM/src/state/IdentityService.ts | 2 +- packages/web3-providers/src/types.ts | 7 +- packages/web3-shared/base/src/specs/index.ts | 2 +- pnpm-lock.yaml | 1843 ++++++++++++++--- 47 files changed, 1881 insertions(+), 1045 deletions(-) delete mode 100644 packages/mask/src/plugins/Wallet/SNSAdaptor/RenameWalletDialog.tsx delete mode 100644 packages/mask/src/plugins/Wallet/SNSAdaptor/SelectWalletDialog.tsx delete mode 100644 packages/mask/src/plugins/Wallet/SNSAdaptor/WalletConnectQRCodeDialog/index.tsx delete mode 100644 packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/TransactionDescription.tsx diff --git a/cspell.json b/cspell.json index b26de3d954c0..32a4da52a8d3 100644 --- a/cspell.json +++ b/cspell.json @@ -120,8 +120,6 @@ "multicall", "multihop", "newsfeed", - "nftavatar", - "nftrss", "nftscan", "nums", "openswap", diff --git a/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx b/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx index 33a19efd8fbd..2d27ba3a6b20 100644 --- a/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx +++ b/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx @@ -9,7 +9,6 @@ import { ConcealableTabs } from '@masknet/shared' import { EMPTY_LIST, NextIDPlatform } from '@masknet/shared-base' import { makeStyles, useStylesExtends } from '@masknet/theme' import { NetworkPluginID } from '@masknet/web3-shared-base' -import type { ChainId } from '@masknet/web3-shared-evm' import { Box, CircularProgress, Typography } from '@mui/material' import { first } from 'lodash-unified' import { useEffect, useMemo, useState } from 'react' diff --git a/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx b/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx index d76817e316b6..68967394799d 100644 --- a/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx +++ b/packages/mask/src/plugins/Avatar/Application/NFTAvatarsDialog.tsx @@ -3,11 +3,11 @@ import { NFTListDialog } from './NFTListDialog' import { InjectedDialog } from '@masknet/shared' import { UploadAvatarDialog } from './UploadAvatarDialog' import type { BindingProof } from '@masknet/shared-base' +import { isSameAddress } from '@masknet/web3-shared-base' import type { SelectTokenInfo, TokenInfo } from '../types' import { PersonaPage } from './PersonaPage' import { DialogContent } from '@mui/material' import { useI18N } from '../locales/i18n_generated' -import { isSameAddress } from '@masknet/web3-shared-evm' import { makeStyles } from '@masknet/theme' const useStyles = makeStyles()((theme) => ({ diff --git a/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx b/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx index 1488f4fc3deb..b56dc0df2e86 100644 --- a/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx +++ b/packages/mask/src/plugins/Avatar/Application/NFTListDialog.tsx @@ -1,5 +1,5 @@ import { makeStyles, useCustomSnackbar } from '@masknet/theme' -import { ChainId, ERC721TokenDetailed, isSameAddress, SocketState, useCollectibles } from '@masknet/web3-shared-evm' +import type { ChainId, SchemaType } from '@masknet/web3-shared-evm' import { Box, Button, DialogActions, DialogContent, Skeleton, Stack, Typography } from '@mui/material' import { useCallback, useState, useEffect } from 'react' import { downloadUrl } from '../../../utils' @@ -11,8 +11,9 @@ import { Translate, useI18N } from '../locales' import { AddressNames } from './WalletList' import { NFTList } from './NFTList' import { Application_NFT_LIST_PAGE } from '../constants' -import { NetworkPluginID, useAccount, useCurrentWeb3NetworkPluginID } from '@masknet/plugin-infra/web3' +import { useAccount, useCurrentWeb3NetworkPluginID } from '@masknet/plugin-infra/web3' import { NFTWalletConnect } from './WalletConnect' +import { isSameAddress, NetworkPluginID, NonFungibleToken } from '@masknet/web3-shared-base' const useStyles = makeStyles()((theme) => ({ AddressNames: { @@ -73,9 +74,9 @@ const useStyles = makeStyles()((theme) => ({ }, })) -function isSameToken(token?: ERC721TokenDetailed, tokenInfo?: TokenInfo) { +function isSameToken(token?: NonFungibleToken, tokenInfo?: TokenInfo) { if (!token && !tokenInfo) return false - return isSameAddress(token?.contractDetailed.address, tokenInfo?.address) && token?.tokenId === tokenInfo?.tokenId + return isSameAddress(token?.address, tokenInfo?.address) && token?.tokenId === tokenInfo?.tokenId } interface NFTListDialogProps { onNext: () => void @@ -85,195 +86,196 @@ interface NFTListDialogProps { } export function NFTListDialog(props: NFTListDialogProps) { - const { onNext, wallets, onSelected, tokenInfo } = props - const { classes } = useStyles() + return null + // const { onNext, wallets, onSelected, tokenInfo } = props + // const { classes } = useStyles() - const account = useAccount() - const [open_, setOpen_] = useState(false) - const [selectedAccount, setSelectedAccount] = useState('') - const [selectedToken, setSelectedToken] = useState() - const [disabled, setDisabled] = useState(false) - const t = useI18N() - const [tokens, setTokens] = useState([]) - const [currentPage, setCurrentPage] = useState( - Application_NFT_LIST_PAGE.Application_nft_tab_eth_page, - ) + // const account = useAccount() + // const [open_, setOpen_] = useState(false) + // const [selectedAccount, setSelectedAccount] = useState('') + // const [selectedToken, setSelectedToken] = useState>() + // const [disabled, setDisabled] = useState(false) + // const t = useI18N() + // const [tokens, setTokens] = useState[]>([]) + // const [currentPage, setCurrentPage] = useState( + // Application_NFT_LIST_PAGE.Application_nft_tab_eth_page, + // ) - const POLYGON_PAGE = Application_NFT_LIST_PAGE.Application_nft_tab_polygon_page + // const POLYGON_PAGE = Application_NFT_LIST_PAGE.Application_nft_tab_polygon_page - const currentPluginId = useCurrentWeb3NetworkPluginID() - const { - data: collectibles, - error, - retry, - state, - } = useCollectibles(selectedAccount, currentPage !== POLYGON_PAGE ? ChainId.Mainnet : ChainId.Matic) + // const currentPluginId = useCurrentWeb3NetworkPluginID() + // const { + // data: collectibles, + // error, + // retry, + // state, + // } = useCollectibles(selectedAccount, currentPage !== POLYGON_PAGE ? ChainId.Mainnet : ChainId.Matic) - const { showSnackbar } = useCustomSnackbar() - const onChange = useCallback((address: string) => { - setSelectedAccount(address) - }, []) + // const { showSnackbar } = useCustomSnackbar() + // const onChange = useCallback((address: string) => { + // setSelectedAccount(address) + // }, []) - const onSelect = (token: ERC721TokenDetailed) => { - setSelectedToken(token) - } + // const onSelect = (token: NonFungibleToken) => { + // setSelectedToken(token) + // } - const onSave = useCallback(async () => { - if (!selectedToken?.info?.imageURL) return - setDisabled(true) - try { - const image = await downloadUrl(selectedToken.info.imageURL) - onSelected({ image: URL.createObjectURL(image), account: selectedAccount, token: selectedToken }) - onNext() - setDisabled(false) - } catch (error) { - console.log(error) - } - setDisabled(false) - }, [selectedToken, selectedAccount]) + // const onSave = useCallback(async () => { + // if (!selectedToken?.metadata?.imageURL) return + // setDisabled(true) + // try { + // const image = await downloadUrl(selectedToken.metadata.imageURL) + // onSelected({ image: URL.createObjectURL(image), account: selectedAccount, token: selectedToken }) + // onNext() + // setDisabled(false) + // } catch (error) { + // console.log(error) + // } + // setDisabled(false) + // }, [selectedToken, selectedAccount]) - const onClick = useCallback(() => { - if (!account && !wallets?.length) { - showSnackbar('Please connect your wallet!', { variant: 'error' }) - return - } - setOpen_(true) - }, [account, wallets, showSnackbar]) + // const onClick = useCallback(() => { + // if (!account && !wallets?.length) { + // showSnackbar('Please connect your wallet!', { variant: 'error' }) + // return + // } + // setOpen_(true) + // }, [account, wallets, showSnackbar]) - useEffect(() => { - setDisabled(!selectedToken || isSameToken(selectedToken, tokenInfo)) - }, [selectedToken, tokenInfo]) + // useEffect(() => { + // setDisabled(!selectedToken || isSameToken(selectedToken, tokenInfo)) + // }, [selectedToken, tokenInfo]) - useEffect(() => setSelectedAccount(account || wallets?.[0]?.identity || ''), [account, wallets]) + // useEffect(() => setSelectedAccount(account || wallets?.[0]?.identity || ''), [account, wallets]) - const onAddClick = (token: ERC721TokenDetailed) => { - setTokens((_tokens) => uniqBy([..._tokens, token], (x) => x.contractDetailed.address && x.tokenId)) - } + // const onAddClick = (token: NonFungibleToken) => { + // setTokens((_tokens) => uniqBy([..._tokens, token], (x) => x.contractDetailed.address && x.tokenId)) + // } - const onChangePage = (name: Application_NFT_LIST_PAGE) => { - setCurrentPage(name) - setSelectedToken(undefined) - } + // const onChangePage = (name: Application_NFT_LIST_PAGE) => { + // setCurrentPage(name) + // setSelectedToken(undefined) + // } - const AddCollectible = ( - - - {currentPluginId !== NetworkPluginID.PLUGIN_EVM ? ( - , - }} - /> - ) : currentPage === POLYGON_PAGE ? ( - , - }} - /> - ) : ( - t.collectible_no_eth() - )} - - {currentPluginId === NetworkPluginID.PLUGIN_EVM ? ( - - ) : null} - - ) + // const AddCollectible = ( + // + // + // {currentPluginId !== NetworkPluginID.PLUGIN_EVM ? ( + // , + // }} + // /> + // ) : currentPage === POLYGON_PAGE ? ( + // , + // }} + // /> + // ) : ( + // t.collectible_no_eth() + // )} + // + // {currentPluginId === NetworkPluginID.PLUGIN_EVM ? ( + // + // ) : null} + // + // ) - const LoadStatus = ( -
- {range(8).map((i) => ( - - ))} -
- ) + // const LoadStatus = ( + //
+ // {range(8).map((i) => ( + // + // ))} + //
+ // ) - const Retry = ( - - {t.no_collectible_found()} - - - ) + // const Retry = ( + // + // {t.no_collectible_found()} + // + // + // ) - const NoNFTList = () => { - if (currentPage === POLYGON_PAGE && tokens.length === 0) return AddCollectible - else if (currentPage === POLYGON_PAGE && tokens.length) return - if (state !== SocketState.done) { - return LoadStatus - } - if (error) { - return Retry - } - if (tokens.length === 0 && collectibles.length === 0) { - return AddCollectible - } + // const NoNFTList = () => { + // if (currentPage === POLYGON_PAGE && tokens.length === 0) return AddCollectible + // else if (currentPage === POLYGON_PAGE && tokens.length) return + // if (state !== SocketState.done) { + // return LoadStatus + // } + // if (error) { + // return Retry + // } + // if (tokens.length === 0 && collectibles.length === 0) { + // return AddCollectible + // } - return - } + // return + // } - if (!wallets?.length && (currentPluginId !== NetworkPluginID.PLUGIN_EVM || !account)) - return ( - - - - ) + // if (!wallets?.length && (currentPluginId !== NetworkPluginID.PLUGIN_EVM || !account)) + // return ( + // + // + // + // ) - return ( - <> - - - {((account && currentPluginId === NetworkPluginID.PLUGIN_EVM) || Boolean(wallets?.length)) && ( - x.contractDetailed.address && x.tokenId)} - children={NoNFTList()} - /> - )} - - - {tokens.length || collectibles.length ? ( - - - {t.collectible_not_found()} - - - {t.add_collectible()} - - - ) : null} + // return ( + // <> + // + // + // {((account && currentPluginId === NetworkPluginID.PLUGIN_EVM) || Boolean(wallets?.length)) && ( + // x.contractDetailed.address && x.tokenId)} + // children={NoNFTList()} + // /> + // )} + // + // + // {tokens.length || collectibles.length ? ( + // + // + // {t.collectible_not_found()} + // + // + // {t.add_collectible()} + // + // + // ) : null} - - - setOpen_(false)} - onAddClick={onAddClick} - /> - - ) + // + // + // setOpen_(false)} + // onAddClick={onAddClick} + // /> + // + // ) } diff --git a/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx b/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx index 065ead46a817..5f2f89f8712f 100644 --- a/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx +++ b/packages/mask/src/plugins/Avatar/Application/NFTListPage.tsx @@ -1,11 +1,7 @@ +import { useImageChecker } from '@masknet/plugin-infra/web3' import { makeStyles } from '@masknet/theme' -import { - ChainId, - createERC721Token, - ERC721TokenDetailed, - EthereumTokenType, - useImageChecker, -} from '@masknet/web3-shared-evm' +import type { NonFungibleToken } from '@masknet/web3-shared-base' +import { ChainId, createERC721Token, SchemaType } from '@masknet/web3-shared-evm' import { Box, Skeleton } from '@mui/material' import { useState } from 'react' import { NFTImage } from '../SNSAdaptor/NFTImage' @@ -49,23 +45,24 @@ interface NFTListPageProps { chainId: ChainId address: string tokenInfo?: TokenInfo - tokens: ERC721TokenDetailed[] - onSelect?: (token: ERC721TokenDetailed) => void + tokens: NonFungibleToken[] + onSelect?: (token: NonFungibleToken) => void children?: React.ReactElement } export function NFTListPage(props: NFTListPageProps) { const { classes } = useStyles() const { onSelect, chainId, tokenInfo, tokens, children } = props - const [selectedToken, setSelectedToken] = useState( + const [selectedToken, setSelectedToken] = useState | undefined>( tokenInfo ? createERC721Token( + chainId, + tokenInfo.address, + tokenInfo.tokenId, { - name: '', - address: tokenInfo.address, chainId, + name: '', symbol: '', - type: EthereumTokenType.ERC721, }, {}, tokenInfo.tokenId, @@ -73,7 +70,7 @@ export function NFTListPage(props: NFTListPageProps) { : undefined, ) - const onChange = (token: ERC721TokenDetailed) => { + const onChange = (token: NonFungibleToken) => { if (!token) return setSelectedToken(token) onSelect?.(token) @@ -84,7 +81,7 @@ export function NFTListPage(props: NFTListPageProps) { {children ?? - tokens.map((token: ERC721TokenDetailed, i) => ( + tokens.map((token: NonFungibleToken, i) => ( void - selectedToken?: ERC721TokenDetailed + token: NonFungibleToken + onChange: (token: NonFungibleToken) => void + selectedToken?: NonFungibleToken } function NFTImageCollectibleAvatar({ token, onChange, selectedToken }: NFTImageCollectibleAvatarProps) { const { classes } = useStyles() - const { value: isImageToken, loading } = useImageChecker(token.info?.imageURL) + const { value: isImageToken, loading } = useImageChecker(token.metadata?.imageURL) if (loading) return ( diff --git a/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx b/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx index 14f261fad9cd..888ed61e31cf 100644 --- a/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx +++ b/packages/mask/src/plugins/Avatar/Application/WalletConnect.tsx @@ -1,14 +1,15 @@ import { WalletMessages } from '@masknet/plugin-wallet' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' import { makeStyles, useStylesExtends } from '@masknet/theme' -import { resolveProviderHomeLink, useProviderType } from '@masknet/web3-shared-evm' import { Box, Button, Link, Typography } from '@mui/material' import { WalletIcon } from '../assets/wallet' import LaunchIcon from '@mui/icons-material/Launch' import { useI18N } from '../locales/i18n_generated' import type { HTMLProps } from 'react' import { ApplicationSmallIcon } from '../assets/application' -import { NetworkPluginID } from '@masknet/plugin-infra/web3' +import { providerResolver } from '@masknet/web3-shared-evm' +import { NetworkPluginID } from '@masknet/web3-shared-base' +import { useProviderType } from '@masknet/plugin-infra/web3' const useStyles = makeStyles()((theme) => ({ root: { @@ -47,8 +48,8 @@ interface NFTWalletConnectProps extends withClasses<'root'> {} export function NFTWalletConnect(props: NFTWalletConnectProps) { const classes = useStylesExtends(useStyles(), props) - const providerType = useProviderType() const t = useI18N() + const providerType = useProviderType(NetworkPluginID.PLUGIN_EVM) const { setDialog: openSelectProviderDialog } = useRemoteControlledDialog( WalletMessages.events.selectProviderDialogUpdated, @@ -71,19 +72,21 @@ export function NFTWalletConnect(props: NFTWalletConnectProps) { Mask Network - - - + {providerType ? ( + + + + ) : null} - - - - ) -} diff --git a/packages/mask/src/plugins/Wallet/SNSAdaptor/SelectWalletDialog.tsx b/packages/mask/src/plugins/Wallet/SNSAdaptor/SelectWalletDialog.tsx deleted file mode 100644 index a283ba043d4c..000000000000 --- a/packages/mask/src/plugins/Wallet/SNSAdaptor/SelectWalletDialog.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { useState, useCallback } from 'react' -import { Button, DialogActions, DialogContent } from '@mui/material' -import { makeStyles, useStylesExtends } from '@masknet/theme' -import { ProviderType, useWallets, useWallet, NetworkType } from '@masknet/web3-shared-evm' -import { useRemoteControlledDialog } from '@masknet/shared-base-ui' -import { InjectedDialog } from '@masknet/shared' -import { DashboardRoutes } from '@masknet/shared-base' -import { delay } from '@dimensiondev/kit' -import { useI18N } from '../../../utils' -import { WalletMessages, WalletRPC } from '../messages' -import { WalletInList } from '../../../components/shared/SelectWallet/WalletInList' -import Services from '../../../extension/service' - -const useStyles = makeStyles()({ - content: { - padding: 0, - minHeight: 300, - }, -}) - -interface SelectWalletDialogUIProps extends withClasses {} - -function SelectWalletDialogUI(props: SelectWalletDialogUIProps) { - const { t } = useI18N() - const classes = useStylesExtends(useStyles(), props) - - const wallets = useWallets(ProviderType.MaskWallet) - const selectedWallet = useWallet() - - // #region remote controlled dialog logic - const [networkType, setNetworkType] = useState() - const { open, closeDialog } = useRemoteControlledDialog(WalletMessages.events.selectWalletDialogUpdated, (ev) => { - if (!ev.open) return - setNetworkType(ev.networkType) - }) - // #endregion - - const onSelect = useCallback( - async (address: string) => { - closeDialog() - await WalletRPC.updateAccount({ - account: address, - providerType: ProviderType.MaskWallet, - networkType, - }) - }, - [networkType, closeDialog], - ) - - // #region create new wallet - const onCreate = useCallback(async () => { - closeDialog() - await delay(100) - await Services.Helper.openDashboard(DashboardRoutes.CreateMaskWallet, `create=${Date.now()}`) - }, [history, closeDialog]) - // #endregion - - return ( - - - {wallets.map((wallet) => ( - onSelect(wallet.address)} - /> - ))} - - - - - - ) -} - -export interface SelectWalletDialogProps extends SelectWalletDialogUIProps {} - -export function SelectWalletDialog(props: SelectWalletDialogProps) { - return -} diff --git a/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletConnectQRCodeDialog/index.tsx b/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletConnectQRCodeDialog/index.tsx deleted file mode 100644 index 29f60f158d17..000000000000 --- a/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletConnectQRCodeDialog/index.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { useState } from 'react' -import { useAsync } from 'react-use' -import { Button, DialogActions, DialogContent } from '@mui/material' -import { makeStyles } from '@masknet/theme' -import { useRemoteControlledDialog } from '@masknet/shared-base-ui' -import { InjectedDialog } from '@masknet/shared' -import { useI18N } from '../../../../utils' -import { WalletMessages } from '../../messages' -import Services from '../../../../extension/service' -import { SafariPlatform } from './SafariPlatform' -import { FirefoxPlatform } from './FirefoxPlatform' -import { QRCodeModel } from './QRCodeModel' - -const useStyles = makeStyles()({ - container: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, - actions: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - height: '30%', - }, -}) -export const WalletConnectQRCodeDialog: React.FC = () => { - const [uri, setURI] = useState('') - - // #region remote controlled dialog logic - const { open, closeDialog } = useRemoteControlledDialog( - WalletMessages.events.walletConnectQRCodeDialogUpdated, - (ev) => ev.open && setURI(ev.uri), - ) - // #endregion - - useAsync(async () => { - if (!open) return - try { - await Services.Ethereum.untilWalletConnect() - } catch { - // do nothing - } finally { - closeDialog() - } - }, [open]) - - let mode: QRCodeDialogProps['mode'] = 'qrcode' - if (process.env.architecture === 'app' && process.env.engine === 'firefox') { - mode = 'firefox' - } else if (process.env.architecture === 'app' && process.env.engine === 'safari') { - mode = 'safari' - } - return ( - { - await Services.Ethereum.cancelWalletConnect() - closeDialog() - }} - /> - ) -} - -export interface QRCodeDialogProps { - uri: string - open: boolean - onClose(): void - mode?: 'qrcode' | 'firefox' | 'safari' -} - -export const QRCodeDialog: React.FC = ({ uri, open, onClose, mode }) => { - const { t } = useI18N() - const { classes } = useStyles() - const [qrMode, setQRMode] = useState(false) - const PlatformSelector: React.FC = () => { - if (!uri) { - return null - } else if (qrMode || mode === 'qrcode') { - return - } else if (mode === 'firefox') { - return - } else if (mode === 'safari') { - return - } - return - } - return ( - - - - - - {mode !== 'qrcode' && ( - - )} - - - ) -} diff --git a/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/TransactionDescription.tsx b/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/TransactionDescription.tsx deleted file mode 100644 index 876f383f8569..000000000000 --- a/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/TransactionDescription.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import type { TransactionReceipt } from 'web3-core' -import { first, last } from 'lodash-unified' -import { - ChainId, - useNativeTokenDetailed, - EthereumRpcType, - useChainId, - formatBalance, - NativeTokenDetailed, - ERC20TokenDetailed, - FungibleTokenDetailed, - useERC20TokenDetailed, -} from '@masknet/web3-shared-evm' -import { pow10 } from '@masknet/web3-shared-base' -import { getContractMethodDescription } from './contractMethodDescription' -import type { ComputedPayload } from '../../../../extension/background-script/EthereumServices/rpc' - -function getTokenAmountDescription(amount = '0', tokenDetailed?: FungibleTokenDetailed, negative?: boolean) { - const symbol = negative ? '- ' : '' - const value = pow10(9 + (tokenDetailed?.decimals ?? 18)).isGreaterThanOrEqualTo(amount) - ? formatBalance(amount, tokenDetailed?.decimals ?? 0, 4) - : 'infinite' - const token = tokenDetailed?.symbol?.trim() - return `${symbol}${value} ${token ?? ''}` -} - -function getTransactionDescription( - chainId: ChainId, - nativeTokenDetailed?: NativeTokenDetailed | ERC20TokenDetailed, - tokenDetailed?: ERC20TokenDetailed, - computedPayload?: ComputedPayload | null, -) { - if (!computedPayload) return - const type = computedPayload.type - - switch (type) { - case EthereumRpcType.SEND_ETHER: - return `Send token -${getTokenAmountDescription( - computedPayload._tx.value as string | undefined, - nativeTokenDetailed, - )}` - case EthereumRpcType.CONTRACT_INTERACTION: - switch (computedPayload.name) { - case 'approve': - return `Approve spend ${getTokenAmountDescription( - computedPayload.parameters?.value, - tokenDetailed, - )}` - case 'transfer': - case 'transferFrom': - return `Transfer token ${getTokenAmountDescription( - computedPayload.parameters?.value, - tokenDetailed, - true, - )}` - case 'swapExactETHForTokens': - const inputAmount = formatBalance(computedPayload._tx.value, nativeTokenDetailed?.decimals, 2) - const outputAmount = formatBalance( - computedPayload.parameters!.amountOutMin, - tokenDetailed?.decimals, - 2, - ) - return `Swap ${inputAmount} ${nativeTokenDetailed?.symbol} for ${outputAmount} ${tokenDetailed?.symbol}` - case 'swapExactTokensForETH': - const inAmount = formatBalance(computedPayload.parameters!.amountIn, tokenDetailed?.decimals, 2) - const outAmount = formatBalance( - computedPayload.parameters!.amountOutMin, - nativeTokenDetailed?.decimals, - 2, - ) - return `Swap ${inAmount} ${tokenDetailed?.symbol} for ${outAmount} ${nativeTokenDetailed?.symbol}` - case 'swapExactTokensForTokens': - const amountIn = formatBalance( - computedPayload.parameters!.amountIn, - nativeTokenDetailed?.decimals, - 2, - ) - const amountOut = formatBalance( - computedPayload.parameters!.amountOutMin, - tokenDetailed?.decimals, - 2, - ) - return `Swap ${amountIn} ${nativeTokenDetailed?.symbol} for ${amountOut} ${tokenDetailed?.symbol}` - default: - const description = getContractMethodDescription( - { name: computedPayload.name ?? '', chainId, address: computedPayload._tx.to ?? '' }, - computedPayload, - ) - return ( - description ?? - `${computedPayload.name ?? 'Contract Interaction'} ${ - computedPayload._tx.value - ? getTokenAmountDescription( - computedPayload._tx.value as string | undefined, - nativeTokenDetailed, - true, - ) - : '' - }` - ) - } - case EthereumRpcType.CONTRACT_DEPLOYMENT: - return `Contract Deployment ${getTokenAmountDescription( - computedPayload._tx.value as string | undefined, - nativeTokenDetailed, - true, - )}` - case EthereumRpcType.CANCEL: - return 'Cancel Transaction' - default: - return - } -} - -export interface RecentTransactionDescriptionProps { - hash: string - receipt?: TransactionReceipt | null - computedPayload?: ComputedPayload | null -} - -export function RecentTransactionDescription(props: RecentTransactionDescriptionProps) { - const chainId = useChainId() - const { hash, computedPayload } = props - const { loading: getNativeTokenLoading, value: nativeTokenDetailed } = useNativeTokenDetailed() - let inputTokenAddress: string | undefined = '' - let tokenAddress: string | undefined = '' - - if (computedPayload?.type === EthereumRpcType.CONTRACT_INTERACTION) { - switch (computedPayload.name) { - case 'approve': - case 'transfer': - case 'transferFrom': - tokenAddress = computedPayload._tx.to - break - case 'swapExactETHForTokens': - tokenAddress = last(computedPayload.parameters!.path) - break - case 'swapExactTokensForETH': - tokenAddress = first(computedPayload.parameters!.path) - break - case 'swapExactTokensForTokens': - inputTokenAddress = first(computedPayload.parameters!.path) - tokenAddress = last(computedPayload.parameters!.path) - break - case 'create_red_packet': - tokenAddress = computedPayload.parameters!._token_addr - break - default: - tokenAddress = '' - } - } - - const { loading: getInputERC20TokenLoading, value: inputTokenDetailed } = useERC20TokenDetailed(inputTokenAddress) - - const { loading: getERC20TokenLoading, value: tokenDetailed } = useERC20TokenDetailed(tokenAddress) - - return !getNativeTokenLoading && !getERC20TokenLoading && !getInputERC20TokenLoading ? ( - - {getTransactionDescription( - chainId, - inputTokenAddress ? inputTokenDetailed : nativeTokenDetailed, - tokenDetailed, - computedPayload, - ) ?? hash} - - ) : null -} diff --git a/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/index.tsx b/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/index.tsx index 585a02e51f4f..d278b2b249a4 100644 --- a/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/index.tsx +++ b/packages/mask/src/plugins/Wallet/SNSAdaptor/WalletStatusDialog/index.tsx @@ -4,7 +4,7 @@ import ErrorIcon from '@mui/icons-material/Error' import { makeStyles } from '@masknet/theme' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' import { InjectedDialog } from '@masknet/shared' -import { CrossIsolationMessages, isDashboardPage } from '@masknet/shared-base' +import { CrossIsolationMessages } from '@masknet/shared-base' import { NetworkPluginID } from '@masknet/web3-shared-base' import { useChainIdValid } from '@masknet/plugin-infra/web3' import { WalletStatusBox } from '../../../../components/shared/WalletStatusBox' @@ -66,7 +66,7 @@ export function WalletStatusDialog(props: WalletStatusDialogProps) { return ( - + {!chainIdValid ? ( diff --git a/packages/mask/src/web3/UI/EthereumChainBoundary.tsx b/packages/mask/src/web3/UI/EthereumChainBoundary.tsx index b8a5ff3e3366..feec69989c84 100644 --- a/packages/mask/src/web3/UI/EthereumChainBoundary.tsx +++ b/packages/mask/src/web3/UI/EthereumChainBoundary.tsx @@ -11,11 +11,7 @@ import { useAllowTestnet, useProviderType, } from '@masknet/plugin-infra/web3' -import { - ChainId, - chainResolver, - ProviderType, -} from '@masknet/web3-shared-evm' +import { ChainId, chainResolver, ProviderType } from '@masknet/web3-shared-evm' import { useRemoteControlledDialog } from '@masknet/shared-base-ui' import { delay } from '@dimensiondev/kit' import ActionButton, { @@ -117,7 +113,6 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { // // read the chain detailed from the built-in chain list // const chainDetailedCAIP = getChainDetailedCAIP(expectedChainId) // if (!chainDetailedCAIP) throw new Error('Unknown network type.') - // // if mask wallet was used it can switch network automatically // if (providerType === ProviderType.MaskWallet) { // await WalletRPC.updateAccount({ @@ -125,7 +120,6 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { // }) // return // } - // if (!networkType) return // try { // const overrides = { @@ -141,7 +135,6 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { // ? Services.Ethereum.switchEthereumChain(expectedChainId, overrides) // : Services.Ethereum.addEthereumChain(chainDetailedCAIP, account, overrides), // ]) - // // recheck // const chainIdHex = await Services.Ethereum.getChainId(overrides) // if (Number.parseInt(chainIdHex, 16) !== expectedChainId) throw new Error('Failed to switch chain.') diff --git a/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx b/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx index bf536fa42b5d..7e5bba612294 100644 --- a/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx +++ b/packages/mask/src/web3/UI/EthereumWalletConnectedBoundary.tsx @@ -5,7 +5,7 @@ import ActionButton, { ActionButtonProps } from '../../extension/options-page/Da import { WalletMessages } from '../../plugins/Wallet/messages' import { useI18N } from '../../utils' import { isZero, NetworkPluginID } from '@masknet/web3-shared-base' -import { useAccount, useChainId, useNativeTokenBalance, useWeb3State } from '@masknet/plugin-infra/src/web3' +import { useAccount, useChainId, useNativeTokenBalance, useWeb3State } from '@masknet/plugin-infra/web3' // import { useWalletRiskWarningDialog } from '../../plugins/Wallet/hooks/useWalletRiskWarningDialog' const useStyles = makeStyles()((theme) => ({ @@ -46,9 +46,9 @@ export function EthereumWalletConnectedBoundary(props: EthereumWalletConnectedBo const nativeTokenBalance = useNativeTokenBalance(NetworkPluginID.PLUGIN_EVM) const { RiskWarning } = useWeb3State(NetworkPluginID.PLUGIN_EVM) - // #region remote controlled confirm risk warning - const { isConfirmed: isRiskWarningConfirmed, openDialog: openRiskWarningDialog } = useWalletRiskWarningDialog() - // #endregion + // // #region remote controlled confirm risk warning + // const { isConfirmed: isRiskWarningConfirmed, openDialog: openRiskWarningDialog } = useWalletRiskWarningDialog() + // // #endregion // #region remote controlled select provider dialog const { openDialog: openSelectProviderDialog } = useRemoteControlledDialog( @@ -69,17 +69,17 @@ export function EthereumWalletConnectedBoundary(props: EthereumWalletConnectedBo ) - if (!isRiskWarningConfirmed && !hideRiskWarningConfirmed) - return ( - - {t('plugin_wallet_confirm_risk_warning')} - - ) + // if (!isRiskWarningConfirmed && !hideRiskWarningConfirmed) + // return ( + // + // {t('plugin_wallet_confirm_risk_warning')} + // + // ) if (isZero(nativeTokenBalance.value ?? '0') && !offChain) return ( diff --git a/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts b/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts index a427018c49be..0589cfed1d5e 100644 --- a/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts +++ b/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts @@ -1,5 +1,5 @@ -import type { Web3Helper } from '../web3-helpers' import type { NetworkPluginID } from '@masknet/web3-shared-base' +import type { Web3Helper } from '../web3-helpers' import { useActivatedPlugin } from './useActivatedPlugin' export function useActivatedPluginWeb3State(pluginID: T) { diff --git a/packages/plugin-infra/src/hooks/useAvailablePlugins.ts b/packages/plugin-infra/src/hooks/useAvailablePlugins.ts index b6967bc275c4..f6f787c5e3b5 100644 --- a/packages/plugin-infra/src/hooks/useAvailablePlugins.ts +++ b/packages/plugin-infra/src/hooks/useAvailablePlugins.ts @@ -1,7 +1,8 @@ import { useMemo } from 'react' import type { NetworkPluginID } from '@masknet/web3-shared-base' import type { Plugin } from '../types' -import { useChainId, useCurrentWeb3NetworkPluginID } from '../web3' +import { useChainId } from '../web3/useChainId' +import { useCurrentWeb3NetworkPluginID } from '../web3/Context' type HasRequirement = { enableRequirement: Plugin.Shared.Definition['enableRequirement'] } diff --git a/packages/plugin-infra/src/web3-helpers/index.ts b/packages/plugin-infra/src/web3-helpers/index.ts index 8d68502906bd..31b7ae04d24c 100644 --- a/packages/plugin-infra/src/web3-helpers/index.ts +++ b/packages/plugin-infra/src/web3-helpers/index.ts @@ -1,4 +1,4 @@ -import { +import type { Connection, ConnectionOptions, NetworkDescriptor, diff --git a/packages/plugin-infra/src/web3-state/Identity.ts b/packages/plugin-infra/src/web3-state/Identity.ts index a9bba4c3ccd7..d142d557ddc7 100644 --- a/packages/plugin-infra/src/web3-state/Identity.ts +++ b/packages/plugin-infra/src/web3-state/Identity.ts @@ -13,6 +13,7 @@ export class IdentityServiceState< protected storage: StorageItem = null! private getIdentityID(identity: SocialIdentity) { + if (!identity.identifier) return '' return `${identity.identifier.network}_${identity.identifier.userId}` } diff --git a/packages/plugin-infra/src/web3/Context.tsx b/packages/plugin-infra/src/web3/Context.tsx index abbc769897eb..525f0e4e1218 100644 --- a/packages/plugin-infra/src/web3/Context.tsx +++ b/packages/plugin-infra/src/web3/Context.tsx @@ -1,6 +1,6 @@ import React, { createContext, useContext } from 'react' -import { EMPTY_OBJECT } from '@masknet/shared-base' import { NetworkPluginID } from '@masknet/web3-shared-base' +import { EMPTY_OBJECT } from '@masknet/shared-base' import type { Web3Helper } from '../web3-helpers' interface Web3Context { @@ -12,7 +12,7 @@ interface Web3Context { const PluginIDContext = createContext(NetworkPluginID.PLUGIN_EVM) -const PluginWeb3Context = createContext>({}) +const PluginWeb3Context = createContext>(EMPTY_OBJECT) const PluginsWeb3Context = createContext>>(null!) diff --git a/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts b/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts index 4497a707d5ae..a68c8e080b47 100644 --- a/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts +++ b/packages/plugin-infra/src/web3/useFungibleTokenPrice.ts @@ -22,7 +22,7 @@ export function useFungibleTokenPrice( return useAsyncRetry(async () => { if (!chainId || !TokenPrice) return 0 - return (TokenPrice.getFubgibleTokenPrice as GetFungibleTokenPrice)( + return (TokenPrice.getFungibleTokenPrice as GetFungibleTokenPrice)( chainId, address ?? '', options?.currencyType, diff --git a/packages/plugin-infra/src/web3/useNativeTokenBalance.ts b/packages/plugin-infra/src/web3/useNativeTokenBalance.ts index 164bbee02ca9..b91e4f6d7731 100644 --- a/packages/plugin-infra/src/web3/useNativeTokenBalance.ts +++ b/packages/plugin-infra/src/web3/useNativeTokenBalance.ts @@ -4,7 +4,10 @@ import type { Web3Helper } from '../web3-helpers' import { useAccount } from './useAccount' import { useWeb3Connection } from './useWeb3Connection' -export function useNativeTokenBalance(pluginID?: T, options?: Web3Helper.Web3ConnectionOptions) { +export function useNativeTokenBalance( + pluginID?: T, + options?: Web3Helper.Web3ConnectionOptions, +) { type GetNativeTokenBalance = (account: string, options?: Web3Helper.Web3ConnectionOptions) => Promise const account = useAccount(pluginID, options?.account) diff --git a/packages/plugin-infra/src/web3/useSocketOnce.ts b/packages/plugin-infra/src/web3/useSocketOnce.ts index 62b4fb866bc8..d34c39c9ad19 100644 --- a/packages/plugin-infra/src/web3/useSocketOnce.ts +++ b/packages/plugin-infra/src/web3/useSocketOnce.ts @@ -1,6 +1,6 @@ -import { getWebSocketInstance, PayloadMessage, RequestMessage } from '@masknet/web3-shared-base' import { useEffect, useState } from 'react' import { useAsyncRetry } from 'react-use' +import { getWebSocketInstance, PayloadMessage, RequestMessage } from '@masknet/web3-shared-base' export const useSocketOnce = (message: Omit) => { const [data, setData] = useState([]) diff --git a/packages/plugin-infra/src/web3/useWeb3Connection.ts b/packages/plugin-infra/src/web3/useWeb3Connection.ts index 66f5cd41e49a..b3cebfe8ef81 100644 --- a/packages/plugin-infra/src/web3/useWeb3Connection.ts +++ b/packages/plugin-infra/src/web3/useWeb3Connection.ts @@ -1,5 +1,5 @@ -import type { NetworkPluginID } from '@masknet/web3-shared-base' import { useAsyncRetry } from 'react-use' +import type { NetworkPluginID } from '@masknet/web3-shared-base' import type { Web3Helper } from '../web3-helpers' import { useAccount } from './useAccount' import { useChainId } from './useChainId' diff --git a/packages/plugins/EVM/src/state/IdentityService.ts b/packages/plugins/EVM/src/state/IdentityService.ts index 21e0b63e2dba..0e97869d5cef 100644 --- a/packages/plugins/EVM/src/state/IdentityService.ts +++ b/packages/plugins/EVM/src/state/IdentityService.ts @@ -42,7 +42,7 @@ export class IdentityService extends IdentityServiceState { const { identifier, bio = '', nickname = '', homepage = '' } = identity const address = getAddress(bio) - const ethereumName = getEthereumName(identifier.userId ?? '', nickname, bio) + const ethereumName = getEthereumName(identifier?.userId ?? '', nickname, bio) const RSS3Id = getRSS3Id(nickname, homepage, bio) const web3 = new Web3( diff --git a/packages/web3-providers/src/types.ts b/packages/web3-providers/src/types.ts index 414b46e16a55..ca5202febe78 100644 --- a/packages/web3-providers/src/types.ts +++ b/packages/web3-providers/src/types.ts @@ -2,12 +2,7 @@ import type { Result } from 'ts-results' import type RSS3 from 'rss3-next' import type { Transaction as Web3Transaction } from 'web3-core' import type { api } from '@dimensiondev/mask-wallet-core/proto' -import type { - NextIDAction, - NextIDStoragePayload, - NextIDPayload, - NextIDPlatform, -} from '@masknet/shared-base' +import type { NextIDAction, NextIDStoragePayload, NextIDPayload, NextIDPlatform } from '@masknet/shared-base' import type { Transaction, FungibleAsset, diff --git a/packages/web3-shared/base/src/specs/index.ts b/packages/web3-shared/base/src/specs/index.ts index 15942b3d9c79..04a184ce002e 100644 --- a/packages/web3-shared/base/src/specs/index.ts +++ b/packages/web3-shared/base/src/specs/index.ts @@ -96,7 +96,7 @@ export interface Identity { } export interface SocialIdentity { - identifier: ProfileIdentifier + identifier?: ProfileIdentifier avatar?: string bio?: string nickname?: string diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aedafd9611ce..c2b95e7a8703 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -154,6 +154,7 @@ importers: '@hookform/resolvers': ^2.8.8 '@masknet/backup-format': workspace:* '@masknet/icons': workspace:* + '@masknet/plugin-evm': workspace:* '@masknet/plugin-example': workspace:* '@masknet/plugin-flow': workspace:* '@masknet/plugin-infra': workspace:* @@ -168,6 +169,8 @@ importers: '@masknet/web3-providers': workspace:* '@masknet/web3-shared-base': workspace:* '@masknet/web3-shared-evm': workspace:* + '@masknet/web3-shared-flow': workspace:* + '@masknet/web3-shared-solana': workspace:* '@msgpack/msgpack': ^2.7.2 '@servie/events': ^3.0.0 '@storybook/addon-actions': ^6.4.22 @@ -210,6 +213,7 @@ importers: '@hookform/resolvers': 2.8.8_react-hook-form@7.30.0 '@masknet/backup-format': link:../backup-format '@masknet/icons': link:../icons + '@masknet/plugin-evm': link:../plugins/EVM '@masknet/plugin-example': link:../plugins/example '@masknet/plugin-flow': link:../plugins/Flow '@masknet/plugin-infra': link:../plugin-infra @@ -224,6 +228,8 @@ importers: '@masknet/web3-providers': link:../web3-providers '@masknet/web3-shared-base': link:../web3-shared/base '@masknet/web3-shared-evm': link:../web3-shared/evm + '@masknet/web3-shared-flow': link:../web3-shared/flow + '@masknet/web3-shared-solana': link:../web3-shared/solana '@msgpack/msgpack': 2.7.2 '@servie/events': 3.0.0 '@types/color': 3.0.3 @@ -340,6 +346,7 @@ importers: '@masknet/plugin-cyberconnect': workspace:* '@masknet/plugin-dao': workspace:* '@masknet/plugin-debugger': workspace:* + '@masknet/plugin-evm': workspace:* '@masknet/plugin-example': workspace:* '@masknet/plugin-file-service': workspace:* '@masknet/plugin-flow': workspace:* @@ -386,7 +393,6 @@ importers: '@uniswap/sdk-core': ^3.0.1 '@uniswap/v2-sdk': 3.0.0-alpha.2 '@uniswap/v3-sdk': ^3.3.2 - '@walletconnect/client': ^1.2.2 anchorme: ^2.1.2 assert: ^2.0.0 async-call-rpc: ^6.0.2 @@ -486,6 +492,7 @@ importers: '@masknet/plugin-cyberconnect': link:../plugins/CyberConnect '@masknet/plugin-dao': link:../plugins/DAO '@masknet/plugin-debugger': link:../plugins/Debugger + '@masknet/plugin-evm': link:../plugins/EVM '@masknet/plugin-example': link:../plugins/example '@masknet/plugin-file-service': link:../plugins/FileService '@masknet/plugin-flow': link:../plugins/Flow @@ -529,7 +536,6 @@ importers: '@uniswap/sdk-core': 3.0.1 '@uniswap/v2-sdk': 3.0.0-alpha.2 '@uniswap/v3-sdk': 3.3.2 - '@walletconnect/client': 1.4.1 anchorme: 2.1.2 assert: 2.0.0 async-call-rpc: 6.0.2 @@ -558,7 +564,7 @@ importers: json2csv: 5.0.6 millify: 4.0.0 next-tick: 1.1.0 - opensea-js: 1.2.7 + opensea-js: 1.2.7_webpack-cli@4.9.2 promievent: 0.1.5 protobufjs: 6.11.2 pure-react-carousel: 1.28.1 @@ -631,34 +637,60 @@ importers: packages/plugin-infra: specifiers: '@dimensiondev/holoflows-kit': ^0.9.0-20210902104757-7c3d0d0 + '@dimensiondev/mask-wallet-core': 0.1.0-20211013082857-eb62e5f '@masknet/encryption': workspace:* '@masknet/shared-base': workspace:* '@masknet/shared-base-ui': workspace:* '@masknet/theme': workspace:* '@masknet/typed-message': workspace:* + '@masknet/web3-constants': workspace:* + '@masknet/web3-contracts': workspace:* '@masknet/web3-shared-base': workspace:* + '@masknet/web3-shared-evm': workspace:* + '@masknet/web3-shared-flow': workspace:* + '@masknet/web3-shared-solana': workspace:* '@servie/events': ^3.0.0 + '@types/ethereum-blockies': ^0.1.0 '@types/use-subscription': ^1.0.0 async-call-rpc: ^6.0.2 bignumber.js: ^9.0.2 + ethereum-blockies: ^0.1.1 react-use: ^17.3.2 unstated-next: ^1.1.0 - use-subscription: 1.6.0 + urlcat: ^2.0.4 + use-subscription: ^1.6.0 + wallet.ts: ^1.0.1 + web3: 1.7.3 + web3-core-helpers: 1.7.3 + web3-utils: 1.7.3 dependencies: '@dimensiondev/holoflows-kit': 0.9.0-20210902104757-7c3d0d0 + '@dimensiondev/mask-wallet-core': 0.1.0-20211013082857-eb62e5f '@masknet/encryption': link:../encryption '@masknet/shared-base': link:../shared-base '@masknet/shared-base-ui': link:../shared-base-ui '@masknet/theme': link:../theme '@masknet/typed-message': link:../typed-message + '@masknet/web3-constants': link:../web3-constants + '@masknet/web3-contracts': link:../web3-contracts '@masknet/web3-shared-base': link:../web3-shared/base + '@masknet/web3-shared-evm': link:../web3-shared/evm + '@masknet/web3-shared-flow': link:../web3-shared/flow + '@masknet/web3-shared-solana': link:../web3-shared/solana '@servie/events': 3.0.0 + '@types/ethereum-blockies': 0.1.0 '@types/use-subscription': 1.0.0 async-call-rpc: 6.0.2 bignumber.js: 9.0.2 + ethereum-blockies: 0.1.1 react-use: 17.3.2 unstated-next: 1.1.0 + urlcat: 2.0.4 use-subscription: 1.6.0 + wallet.ts: 1.0.1 + web3: 1.7.3 + web3-core-helpers: 1.7.3 + web3-utils: 1.7.3 packages/plugins/CrossChainBridge: specifiers: @@ -686,6 +718,7 @@ importers: '@masknet/shared-base': workspace:* '@masknet/theme': workspace:* '@masknet/typed-message': workspace:* + '@masknet/web3-shared-base': workspace:* '@masknet/web3-shared-evm': workspace:* boring-avatars: ^1.6.3 react-use: ^17.3.2 @@ -696,6 +729,7 @@ importers: '@masknet/shared-base': link:../../shared-base '@masknet/theme': link:../../theme '@masknet/typed-message': link:../../typed-message + '@masknet/web3-shared-base': link:../../web3-shared/base '@masknet/web3-shared-evm': link:../../web3-shared/evm boring-avatars: 1.6.3 react-use: 17.3.2 @@ -752,6 +786,75 @@ importers: react-use: 17.3.2 urlcat: 2.0.4 + packages/plugins/EVM: + specifiers: + '@dimensiondev/holoflows-kit': ^0.9.0-20210902104757-7c3d0d0 + '@dimensiondev/metamask-extension-provider': ^3.0.6-20210519045409-1835d4d + '@masknet/icons': workspace:* + '@masknet/injected-script': workspace:* + '@masknet/plugin-infra': workspace:* + '@masknet/shared': workspace:* + '@masknet/shared-base': workspace:* + '@masknet/theme': workspace:* + '@masknet/web3-constants': workspace:* + '@masknet/web3-contracts': workspace:* + '@masknet/web3-providers': workspace:* + '@masknet/web3-shared-base': workspace:* + '@masknet/web3-shared-evm': workspace:* + '@metamask/eth-sig-util': ^4.0.0 + '@servie/events': ^3.0.0 + '@toruslabs/torus-embed': ^1.22.6 + '@types/use-subscription': ^1.0.0 + '@walletconnect/client': ^1.7.5 + '@walletconnect/qrcode-modal': ^1.7.5 + '@walletconnect/types': ^1.7.7 + bignumber.js: ^9.0.2 + ethereumjs-util: ^7.1.0 + ethjs-ens: ^2.0.1 + fortmatic: ^2.2.1 + react-use: ^17.3.2 + urlcat: ^2.0.4 + wallet.ts: ^1.0.1 + web3: 1.7.3 + web3-core: 1.7.3 + web3-core-helpers: 1.7.3 + web3-eth-abi: 1.7.3 + web3-utils: 1.7.3 + dependencies: + '@dimensiondev/holoflows-kit': 0.9.0-20210902104757-7c3d0d0 + '@dimensiondev/metamask-extension-provider': 3.0.6-20210519045409-1835d4d + '@masknet/icons': link:../../icons + '@masknet/injected-script': link:../../injected-script + '@masknet/plugin-infra': link:../../plugin-infra + '@masknet/shared': link:../../shared + '@masknet/shared-base': link:../../shared-base + '@masknet/theme': link:../../theme + '@masknet/web3-constants': link:../../web3-constants + '@masknet/web3-contracts': link:../../web3-contracts + '@masknet/web3-providers': link:../../web3-providers + '@masknet/web3-shared-base': link:../../web3-shared/base + '@masknet/web3-shared-evm': link:../../web3-shared/evm + '@metamask/eth-sig-util': 4.0.0 + '@servie/events': 3.0.0 + '@toruslabs/torus-embed': 1.22.6 + '@walletconnect/client': 1.7.8 + '@walletconnect/qrcode-modal': 1.7.8 + '@walletconnect/types': 1.7.8 + bignumber.js: 9.0.2 + ethereumjs-util: 7.1.4 + ethjs-ens: 2.0.1 + fortmatic: 2.2.1 + react-use: 17.3.2 + urlcat: 2.0.4 + wallet.ts: 1.0.1 + web3: 1.7.3 + web3-core: 1.7.3 + web3-core-helpers: 1.7.3 + web3-eth-abi: 1.7.3 + web3-utils: 1.7.3 + devDependencies: + '@types/use-subscription': 1.0.0 + packages/plugins/FileService: specifiers: '@dimensiondev/common-protocols': 1.6.0-20210723072221-8f46a92 @@ -796,29 +899,38 @@ importers: packages/plugins/Flow: specifiers: - '@blocto/fcl': ^0.0.78-alpha.8 + '@blocto/fcl': ^0.0.78-alpha.10 '@masknet/icons': workspace:* + '@masknet/injected-script': workspace:* '@masknet/plugin-infra': workspace:* '@masknet/shared': workspace:* '@masknet/shared-base': workspace:* '@masknet/theme': workspace:* '@masknet/web3-providers': workspace:* '@masknet/web3-shared-base': workspace:* + '@masknet/web3-shared-evm': workspace:* '@masknet/web3-shared-flow': workspace:* + '@servie/events': ^3.0.0 + '@types/use-subscription': ^1.0.0 bignumber.js: ^9.0.2 react-use: ^17.3.2 dependencies: - '@blocto/fcl': 0.0.78-alpha.8 + '@blocto/fcl': 0.0.78-alpha.10 '@masknet/icons': link:../../icons + '@masknet/injected-script': link:../../injected-script '@masknet/plugin-infra': link:../../plugin-infra '@masknet/shared': link:../../shared '@masknet/shared-base': link:../../shared-base '@masknet/theme': link:../../theme '@masknet/web3-providers': link:../../web3-providers '@masknet/web3-shared-base': link:../../web3-shared/base + '@masknet/web3-shared-evm': link:../../web3-shared/evm '@masknet/web3-shared-flow': link:../../web3-shared/flow + '@servie/events': 3.0.0 bignumber.js: 9.0.2 react-use: 17.3.2 + devDependencies: + '@types/use-subscription': 1.0.0 packages/plugins/GoPlusSecurity: specifiers: @@ -888,12 +1000,19 @@ importers: '@masknet/theme': workspace:* '@masknet/web3-providers': workspace:* '@masknet/web3-shared-base': workspace:* + '@masknet/web3-shared-evm': workspace:* '@masknet/web3-shared-solana': workspace:* '@metaplex-foundation/mpl-token-metadata': ^1.1.0 '@metaplex/js': ^4.11.7 + '@project-serum/sol-wallet-adapter': ^0.2.6 + '@servie/events': ^3.0.0 '@solana/spl-name-service': ^0.1.3 '@solana/spl-token': ^0.1.8 '@solana/spl-token-registry': ^0.2.1301 + '@solana/web3.js': 1.39.1 + '@toruslabs/solana-embed': ^0.1.6 + '@types/bs58': ^4.0.1 + '@types/use-subscription': ^1.0.0 bignumber.js: ^9.0.2 bn.js: ^4.12.0 bs58: ^4.0.1 @@ -910,23 +1029,32 @@ importers: '@masknet/theme': link:../../theme '@masknet/web3-providers': link:../../web3-providers '@masknet/web3-shared-base': link:../../web3-shared/base + '@masknet/web3-shared-evm': link:../../web3-shared/evm '@masknet/web3-shared-solana': link:../../web3-shared/solana '@metaplex-foundation/mpl-token-metadata': 1.1.0 '@metaplex/js': 4.11.7 + '@project-serum/sol-wallet-adapter': 0.2.6_@solana+web3.js@1.39.1 + '@servie/events': 3.0.0 '@solana/spl-name-service': 0.1.3 '@solana/spl-token': 0.1.8 '@solana/spl-token-registry': 0.2.1301 + '@solana/web3.js': 1.39.1 + '@toruslabs/solana-embed': 0.1.6 bignumber.js: 9.0.2 bn.js: 4.12.0 bs58: 4.0.1 buffer: 6.0.3 react-use: 17.3.2 + devDependencies: + '@types/bs58': 4.0.1 + '@types/use-subscription': 1.0.0 packages/plugins/Wallet: specifiers: '@masknet/plugin-infra': workspace:* '@masknet/shared': workspace:* '@masknet/theme': workspace:* + '@masknet/web3-shared-base': workspace:* '@masknet/web3-shared-evm': workspace:* bignumber.js: ^9.0.2 react-use: ^17.3.2 @@ -935,6 +1063,7 @@ importers: '@masknet/plugin-infra': link:../../plugin-infra '@masknet/shared': link:../../shared '@masknet/theme': link:../../theme + '@masknet/web3-shared-base': link:../../web3-shared/base '@masknet/web3-shared-evm': link:../../web3-shared/evm bignumber.js: 9.0.2 react-use: 17.3.2 @@ -1072,6 +1201,7 @@ importers: '@masknet/web3-shared-base': workspace:* '@masknet/web3-shared-evm': workspace:* '@types/qrcode': ^1.4.2 + '@types/socket.io-client': ^1.4.36 anchorme: ^2.1.2 bignumber.js: ^9.0.2 classnames: ^2.3.1 @@ -1091,6 +1221,8 @@ importers: '@masknet/theme': link:../theme '@masknet/web3-shared-base': link:../web3-shared/base '@masknet/web3-shared-evm': link:../web3-shared/evm + '@types/qrcode': 1.4.2 + '@types/socket.io-client': 1.4.36 anchorme: 2.1.2 bignumber.js: 9.0.2 classnames: 2.3.1 @@ -1101,8 +1233,6 @@ importers: react-use: 17.3.2 urlcat: 2.0.4 use-subscription: 1.6.0 - devDependencies: - '@types/qrcode': 1.4.2 packages/shared-base: specifiers: @@ -1139,6 +1269,7 @@ importers: '@mui/system': link:../empty '@servie/events': 3.0.0 '@types/react': 18.0.9 + '@types/use-subscription': 1.0.0 anchorme: 2.1.2 async-call-rpc: 6.0.2 bignumber.js: 9.0.2 @@ -1150,8 +1281,6 @@ importers: typeson: 7.0.2 typeson-registry: 3.0.0 z-schema: 5.0.3 - devDependencies: - '@types/use-subscription': 1.0.0 packages/shared-base-ui: specifiers: @@ -1219,6 +1348,7 @@ importers: '@masknet/shared-base': link:../shared-base '@masknet/storybook-shared': link:../storybook-shared '@types/qrcode': 1.4.2 + '@types/react-window': 1.8.5 '@types/tinycolor2': 1.4.3 classnames: 2.3.1 fuse.js: 6.5.3 @@ -1236,7 +1366,6 @@ importers: '@storybook/builder-webpack5': 6.4.22 '@storybook/manager-webpack5': 6.4.22 '@storybook/react': 6.4.22_25edyf2dljasinbq77nivmb22m - '@types/react-window': 1.8.5 babel-loader: 8.2.5_@babel+core@7.17.10 packages/typed-message: @@ -1271,6 +1400,7 @@ importers: packages/web3-providers: specifiers: + '@dimensiondev/mask-wallet-core': 0.1.0-20211013082857-eb62e5f '@masknet/plugin-infra': workspace:* '@masknet/shared-base': workspace:* '@masknet/web3-constants': workspace:* @@ -1292,6 +1422,7 @@ importers: uuid: ^8.3.2 wallet.ts: ^1.0.1 dependencies: + '@dimensiondev/mask-wallet-core': 0.1.0-20211013082857-eb62e5f '@masknet/plugin-infra': link:../plugin-infra '@masknet/shared-base': link:../shared-base '@masknet/web3-constants': link:../web3-constants @@ -1316,32 +1447,49 @@ importers: packages/web3-shared/base: specifiers: + '@dimensiondev/holoflows-kit': ^0.9.0-20210902104757-7c3d0d0 + '@dimensiondev/mask-wallet-core': 0.1.0-20211013082857-eb62e5f + '@masknet/shared-base': workspace:* + '@servie/events': ^3.0.0 + '@types/use-subscription': ^1.0.0 bignumber.js: 9.0.2 date-fns: ^2.28.0 jest-websocket-mock: ^2.3.0 mock-socket: ^9.1.2 react-use: ^17.3.2 reconnecting-websocket: ^4.4.0 + urlcat: ^2.0.4 dependencies: + '@dimensiondev/holoflows-kit': 0.9.0-20210902104757-7c3d0d0 + '@dimensiondev/mask-wallet-core': 0.1.0-20211013082857-eb62e5f + '@masknet/shared-base': link:../../shared-base + '@servie/events': 3.0.0 + '@types/use-subscription': 1.0.0 bignumber.js: 9.0.2 date-fns: 2.28.0 react-use: 17.3.2 reconnecting-websocket: 4.4.0 + urlcat: 2.0.4 devDependencies: jest-websocket-mock: 2.3.0 mock-socket: 9.1.2 packages/web3-shared/evm: specifiers: + '@dimensiondev/holoflows-kit': ^0.9.0-20210902104757-7c3d0d0 '@ensdomains/address-encoder': ^0.2.6 + '@masknet/injected-script': '*' '@masknet/shared-base': workspace:* '@masknet/web3-constants': workspace:* '@masknet/web3-contracts': workspace:* '@masknet/web3-shared-base': workspace:* + '@toruslabs/torus-embed': ^1.22.6 '@types/ethereum-blockies': ^0.1.0 '@types/punycode': ^2.1.0 '@types/use-subscription': ^1.0.0 '@types/uuid': ^8.3.4 + '@walletconnect/client': ^1.7.5 + '@walletconnect/qrcode-modal': ^1.7.5 bignumber.js: 9.0.2 ethereum-blockies: ^0.1.1 fortmatic: ^2.2.1 @@ -1355,15 +1503,18 @@ importers: wallet.ts: ^1.0.1 web3: 1.7.3 web3-core-helpers: 1.7.3 + web3-eth-contract: 1.7.3 web3-utils: 1.7.3 dependencies: + '@dimensiondev/holoflows-kit': 0.9.0-20210902104757-7c3d0d0 '@ensdomains/address-encoder': 0.2.6 '@masknet/shared-base': link:../../shared-base '@masknet/web3-constants': link:../../web3-constants '@masknet/web3-contracts': link:../../web3-contracts '@masknet/web3-shared-base': link:../base - '@types/ethereum-blockies': 0.1.0 - '@types/punycode': 2.1.0 + '@toruslabs/torus-embed': 1.22.6 + '@walletconnect/client': 1.7.8 + '@walletconnect/qrcode-modal': 1.7.8 bignumber.js: 9.0.2 ethereum-blockies: 0.1.1 fortmatic: 2.2.1 @@ -1377,38 +1528,61 @@ importers: wallet.ts: 1.0.1 web3: 1.7.3 web3-core-helpers: 1.7.3 + web3-eth-contract: 1.7.3 web3-utils: 1.7.3 devDependencies: + '@masknet/injected-script': link:../../injected-script + '@types/ethereum-blockies': 0.1.0 + '@types/punycode': 2.1.0 '@types/use-subscription': 1.0.0 '@types/uuid': 8.3.4 packages/web3-shared/flow: specifiers: - '@blocto/fcl': ^0.0.78-alpha.8 + '@blocto/fcl': ^0.0.78-alpha.10 + '@masknet/shared-base': workspace:* '@masknet/web3-constants': workspace:* '@masknet/web3-shared-base': workspace:* '@onflow/types': ^0.0.5 + bignumber.js: 9.0.2 react-use: ^17.3.2 urlcat: ^2.0.4 dependencies: - '@blocto/fcl': 0.0.78-alpha.8 + '@blocto/fcl': 0.0.78-alpha.10 + '@masknet/shared-base': link:../../shared-base '@masknet/web3-constants': link:../../web3-constants '@masknet/web3-shared-base': link:../base '@onflow/types': 0.0.5 + bignumber.js: 9.0.2 react-use: 17.3.2 urlcat: 2.0.4 packages/web3-shared/solana: specifiers: + '@masknet/shared-base': workspace:* '@masknet/web3-constants': workspace:* '@masknet/web3-shared-base': workspace:* + '@solana/web3.js': 1.39.1 + '@toruslabs/solana-embed': ^0.1.6 + '@types/bs58': ^4.0.1 + bignumber.js: 9.0.2 + bs58: ^4.0.1 + buffer: ^6.0.3 react-use: ^17.3.2 urlcat: ^2.0.4 dependencies: + '@masknet/shared-base': link:../../shared-base '@masknet/web3-constants': link:../../web3-constants '@masknet/web3-shared-base': link:../base + '@solana/web3.js': 1.39.1 + '@toruslabs/solana-embed': 0.1.6 + bignumber.js: 9.0.2 + bs58: 4.0.1 + buffer: 6.0.3 react-use: 17.3.2 urlcat: 2.0.4 + devDependencies: + '@types/bs58': 4.0.1 packages: @@ -2268,14 +2442,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.17.10 - dev: true - - /@babel/parser/7.17.3: - resolution: {integrity: sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.17.10 /@babel/parser/7.17.9: resolution: {integrity: sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==} @@ -5078,8 +5244,8 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@blocto/fcl/0.0.78-alpha.8: - resolution: {integrity: sha512-2tu7yxBopuzFSFBtV2Beg9QRaJMGtZ5QlonKt0VZmtsOtGTs1OI6R7g/+MiddWKQIkfS+iQT/vab+hfDdSj9WA==} + /@blocto/fcl/0.0.78-alpha.10: + resolution: {integrity: sha512-BmJUF7S5PbM9poiAXs2eHif60F2ubcZGcvWmdPy2c4M/j9qZZcni4I4cHGfnmIY5hUuXGGNB7Lsq+vga/pmLtw==} dependencies: '@onflow/interaction': 0.0.11 '@onflow/rlp': 0.0.3 @@ -5089,7 +5255,7 @@ packages: '@onflow/util-invariant': 0.0.0 '@onflow/util-template': 0.0.1 '@onflow/util-uid': 0.0.1 - '@portto/sdk': 0.0.56-alpha.1 + '@portto/sdk': 0.0.56-alpha.3 transitivePeerDependencies: - google-protobuf dev: false @@ -5098,8 +5264,8 @@ packages: resolution: {integrity: sha512-D7exTVYs9oQMF5FiasJV4zYlEVgwdoHFprdpw1lofRDZLw57ZYM9q8qxm/aKpMjdv3vsMN9DjfcnPrCmMZTbTA==} dev: false - /@blocto/protobuf/0.1.10: - resolution: {integrity: sha512-Pf08C5TVu9/CW0Nkk0U47Fk0J8N5lw+li6HQqfxh6m/NcClKj/Nvr5gr5o5kCxXxgXax5rmnwNEnC9Y4/mysZQ==} + /@blocto/protobuf/0.1.12: + resolution: {integrity: sha512-0ZvufAM9YSmvmEmGaWERXWZGQKN7oPd8nr9tJ6LqKephrMZG/9g2M3mGuIxB9xuCnKHrSWKoVMBXQgEzhAlB0Q==} dependencies: '@blocto/google-protobuf': 3.19.1 '@improbable-eng/grpc-web': 0.12.0 @@ -5767,6 +5933,7 @@ packages: /@dimensiondev/eslint-plugin/0.0.2-20220516081411-2649814_eslint@8.15.0: resolution: {integrity: sha512-cEEKTD1ku7ScTuifqrZHAXpc8a1hwew12MLee/jvFEdOkoQSDxYiqAh7V35wQLGappUUyqJiLc6vgk6qlpzQeA==, tarball: download/@dimensiondev/eslint-plugin/0.0.2-20220516081411-2649814/f8750f35c321553cee686b564cea6d4c5dffe62eaab4af3ab64a6392d8e4743b} + engines: {node: '>= 16'} peerDependencies: eslint: '>= 8' dependencies: @@ -5810,6 +5977,12 @@ packages: lodash-es: 4.17.21 dev: false + /@dimensiondev/mask-wallet-core/0.1.0-20211013082857-eb62e5f: + resolution: {integrity: sha512-2d7v1/z9Khw4O7J7oBNKLBo7BONd7ZE2gpw34uHVtdG9i0aEz+LSRappgNTZyUZ/+TRJ7ZgAf+Dbeql1oPMvNA==, tarball: download/@dimensiondev/mask-wallet-core/0.1.0-20211013082857-eb62e5f/18071bcb96269e2a8175867950285a4b236a387c232e108ae0672a36649e33bc} + peerDependencies: + protobufjs: '>= 6.10 < 7' + dev: false + /@dimensiondev/mask-wallet-core/0.1.0-20211013082857-eb62e5f_protobufjs@6.11.2: resolution: {integrity: sha512-2d7v1/z9Khw4O7J7oBNKLBo7BONd7ZE2gpw34uHVtdG9i0aEz+LSRappgNTZyUZ/+TRJ7ZgAf+Dbeql1oPMvNA==, tarball: download/@dimensiondev/mask-wallet-core/0.1.0-20211013082857-eb62e5f/18071bcb96269e2a8175867950285a4b236a387c232e108ae0672a36649e33bc} peerDependencies: @@ -7147,18 +7320,6 @@ packages: '@jridgewell/sourcemap-codec': 1.4.11 dev: true - /@json-rpc-tools/types/1.7.6: - resolution: {integrity: sha512-nDSqmyRNEqEK9TZHtM15uNnDljczhCUdBmRhpNZ95bIPKEDQ+nTDmGMFd2lLin3upc5h2VVVd9tkTDdbXUhDIQ==} - dependencies: - keyvaluestorage-interface: 1.0.0 - dev: false - - /@json-rpc-tools/utils/1.6.1: - resolution: {integrity: sha512-cNwP4QapAls+xATU8zLLqPYa9qCbgwEyWEK7vE1oH91b3LfbUYwHtiWZ1+rv0X/mh/9cWNTo2Oi2Sah/QX0WwA==} - dependencies: - '@json-rpc-tools/types': 1.7.6 - dev: false - /@leichtgewicht/ip-codec/2.0.3: resolution: {integrity: sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==} dev: true @@ -7268,6 +7429,14 @@ packages: readable-stream: 2.3.7 dev: false + /@metamask/obs-store/7.0.0: + resolution: {integrity: sha512-Tr61Uu9CGXkCg5CZwOYRMQERd+y6fbtrtLd/PzDTPHO5UJpmSbU+7MPcQK7d1DwZCOCeCIvhmZSUCvYliC8uGw==} + engines: {node: '>=12.0.0'} + dependencies: + '@metamask/safe-event-emitter': 2.0.0 + through2: 2.0.5 + dev: false + /@metamask/safe-event-emitter/2.0.0: resolution: {integrity: sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==} dev: false @@ -7802,27 +7971,6 @@ packages: dev: false optional: true - /@pedrouid/environment/1.0.1: - resolution: {integrity: sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug==} - dev: false - - /@pedrouid/iso-crypto/1.1.0: - resolution: {integrity: sha512-twi+tW67XT0BSOv4rsegnGo4TQMhfFswS/GY3KhrjFiNw3z9x+cMkfO+itNe1JZghQxsxHuhifvfsnG814g1hQ==} - dependencies: - '@pedrouid/iso-random': 1.2.1 - aes-js: 3.1.2 - enc-utils: 3.0.0 - hash.js: 1.1.7 - dev: false - - /@pedrouid/iso-random/1.2.1: - resolution: {integrity: sha512-C35NqYMmLsg61WDiEup4OwjRhgfZIcK4BL+Qg49xowHUJ+f7/LFZCO+TGuQqoXFAj1beKIOpUN33f0fqV7zneQ==} - dependencies: - '@pedrouid/environment': 1.0.1 - enc-utils: 3.0.0 - randombytes: 2.1.0 - dev: false - /@pmmmwh/react-refresh-webpack-plugin/0.5.5_a3gyllrqvxpec3fpybsrposvju: resolution: {integrity: sha512-RbG7h6TuP6nFFYKJwbcToA1rjC1FyPg25NR2noAZ0vKI+la01KTSRPkuVPE+U88jXv7javx2JHglUcL1MHcshQ==} engines: {node: '>= 10.13'} @@ -7905,10 +8053,10 @@ packages: /@popperjs/core/2.11.5: resolution: {integrity: sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==} - /@portto/sdk/0.0.56-alpha.1: - resolution: {integrity: sha512-EqNS5k0FMWEESn0Fn1jU0ygFkhdhQpDdmP5RjN7cDMGaYcoCG69uEArL/m4dk0JRnQ/9rITtQffTH16KSycudQ==} + /@portto/sdk/0.0.56-alpha.3: + resolution: {integrity: sha512-0o+WDIIdck6qcCUhn0Q8tOneD2iEkgZgOBFlrT+Tl2ILDNT4K47P6rzxhELxu1ckFwF6Es7VYp0qs7wYa+41ng==} dependencies: - '@blocto/protobuf': 0.1.10 + '@blocto/protobuf': 0.1.12 '@improbable-eng/grpc-web': 0.14.1 '@improbable-eng/grpc-web-node-http-transport': 0.14.1_p4qmepzqxnh62ysspkonijiajy '@onflow/rlp': 0.0.3 @@ -7933,6 +8081,17 @@ packages: eventemitter3: 4.0.7 dev: false + /@project-serum/sol-wallet-adapter/0.2.6_@solana+web3.js@1.39.1: + resolution: {integrity: sha512-cpIb13aWPW8y4KzkZAPDgw+Kb+DXjCC6rZoH74MGm3I/6e/zKyGnfAuW5olb2zxonFqsYgnv7ev8MQnvSgJ3/g==} + engines: {node: '>=10'} + peerDependencies: + '@solana/web3.js': ^1.5.0 + dependencies: + '@solana/web3.js': 1.39.1 + bs58: 4.0.1 + eventemitter3: 4.0.7 + dev: false + /@protobufjs/aspromise/1.1.2: resolution: {integrity: sha1-m4sMxmPWaafY9vXQiToU00jzD78=} dev: false @@ -8146,6 +8305,10 @@ packages: - utf-8-validate dev: false + /@socket.io/component-emitter/3.1.0: + resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} + dev: false + /@solana/buffer-layout-utils/0.2.0: resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} engines: {node: '>= 10'} @@ -8575,6 +8738,7 @@ packages: - '@storybook/builder-webpack5' - '@storybook/manager-webpack5' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -8685,6 +8849,7 @@ packages: - '@storybook/builder-webpack5' - '@storybook/manager-webpack5' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -8747,6 +8912,7 @@ packages: - '@storybook/react' - '@storybook/vue3' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -8814,6 +8980,7 @@ packages: - '@storybook/react' - '@storybook/vue3' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9065,7 +9232,7 @@ packages: css-loader: 3.6.0_webpack@4.46.0 file-loader: 6.2.0_webpack@4.46.0 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 4.1.6 + fork-ts-checker-webpack-plugin: 4.1.6_webpack@4.46.0 glob: 7.2.0 glob-promise: 3.4.0_glob@7.2.0 global: 4.4.0 @@ -9088,6 +9255,7 @@ packages: webpack-virtual-modules: 0.2.2 transitivePeerDependencies: - '@types/react' + - bluebird - eslint - supports-color - vue-template-compiler @@ -9169,7 +9337,6 @@ packages: transitivePeerDependencies: - '@swc/core' - '@types/react' - - acorn - esbuild - eslint - supports-color @@ -9548,6 +9715,7 @@ packages: ws: 8.5.0 transitivePeerDependencies: - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9624,6 +9792,7 @@ packages: ws: 8.5.0 transitivePeerDependencies: - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9659,6 +9828,7 @@ packages: transitivePeerDependencies: - '@storybook/manager-webpack5' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9693,6 +9863,7 @@ packages: transitivePeerDependencies: - '@storybook/manager-webpack5' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9728,6 +9899,7 @@ packages: transitivePeerDependencies: - '@storybook/manager-webpack5' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9762,6 +9934,7 @@ packages: transitivePeerDependencies: - '@storybook/manager-webpack5' - '@types/react' + - bluebird - bufferutil - encoding - eslint @@ -9854,6 +10027,7 @@ packages: webpack-virtual-modules: 0.2.2 transitivePeerDependencies: - '@types/react' + - bluebird - encoding - eslint - supports-color @@ -9912,7 +10086,6 @@ packages: transitivePeerDependencies: - '@swc/core' - '@types/react' - - acorn - encoding - esbuild - eslint @@ -10037,6 +10210,7 @@ packages: - '@storybook/manager-webpack5' - '@types/react' - '@types/webpack' + - bluebird - bufferutil - encoding - eslint @@ -10101,6 +10275,7 @@ packages: - '@storybook/manager-webpack5' - '@types/react' - '@types/webpack' + - bluebird - bufferutil - encoding - eslint @@ -10404,46 +10579,235 @@ packages: engines: {node: '>= 10'} dev: false - /@tsconfig/node10/1.0.8: - resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} - dev: true - - /@tsconfig/node12/1.0.9: - resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} - dev: true - - /@tsconfig/node14/1.0.1: - resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} - dev: true - - /@tsconfig/node16/1.0.2: - resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} - dev: true - - /@typechain/web3-v1/3.0.0_typechain@5.1.2: - resolution: {integrity: sha512-7N9yGzGOmyW8HJAa3U+0oUqc1JxZcMUIh6Fn4jMkl1z98rKyrzvrllXzT2QmqJ9etZKiyI39AVVly/YPYKTCxQ==} + /@toruslabs/base-controllers/1.6.18: + resolution: {integrity: sha512-C/NGlVeB9x3H5c/+tX4ZTnFYpDzb9Sz+G/061s24Rubr+MRsjncaG7zN8C1y48D83JUvUkSJX9MAFt3m7aTFFA==} peerDependencies: - typechain: ^5.0.0 - web3: ^1.0.0 + '@babel/runtime': 7.x dependencies: - typechain: 5.1.2 + '@toruslabs/broadcast-channel': 4.13.0 + '@toruslabs/http-helpers': 2.2.0 + '@toruslabs/openlogin-jrpc': 1.7.3 + async-mutex: 0.3.2 + bignumber.js: 9.0.2 + bowser: 2.11.0 + eth-rpc-errors: 4.0.3 + ethereumjs-util: 7.1.4 + json-rpc-random-id: 1.0.1 + lodash: 4.17.21 + loglevel: 1.8.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate dev: false - /@types/asn1js/2.0.2: - resolution: {integrity: sha512-t4YHCgtD+ERvH0FyxvNlYwJ2ezhqw7t+Ygh4urQ7dJER8i185JPv6oIM3ey5YQmGN6Zp9EMbpohkjZi9t3UxwA==} + /@toruslabs/broadcast-channel/4.13.0: + resolution: {integrity: sha512-qPpVzLtqjiLRNW5C5xnCNwzWNBcGLSx/rC8C7UTP08Z9HnTIP3JxR+NbdtjR7/AjA2VemdcLQq3n+trJf9gUKQ==} + dependencies: + '@babel/runtime': 7.17.9 + '@toruslabs/eccrypto': 1.1.8 + '@toruslabs/metadata-helpers': 2.5.0_@babel+runtime@7.17.9 + bowser: 2.11.0 + detect-node: 2.1.0 + keccak: 3.0.2 + loglevel: 1.8.0 + microtime: 3.0.0 + oblivious-set: 1.1.1 + p-queue: 6.6.2 + rimraf: 3.0.2 + socket.io-client: 4.5.1 + unload: 2.3.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate dev: false - optional: true - /@types/babel__core/7.1.18: - resolution: {integrity: sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==} + /@toruslabs/eccrypto/1.1.8: + resolution: {integrity: sha512-5dIrO2KVqvnAPOPfJ2m6bnjp9vav9GIcCZXiXRW/bJuIDRLVxJhVvRlleF4oaEZPq5yX5piHq5jVHagNNS0jOQ==} dependencies: - '@babel/parser': 7.17.10 - '@babel/types': 7.17.10 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.14.2 - dev: true - + acorn: 8.7.1 + elliptic: 6.5.4 + es6-promise: 4.2.8 + nan: 2.15.0 + optionalDependencies: + secp256k1: 3.8.0 + dev: false + + /@toruslabs/fetch-node-details/5.1.0: + resolution: {integrity: sha512-3LwpFm5ulVLjLT82ySPFevAUIlQWriz8ih/4qohbbF0Wdfm6MNpQtqNyP1pnyDZKFdOTyzeegIASHyyS60kzyg==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + web3-eth-contract: 1.7.3 + web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@toruslabs/http-helpers/2.2.0: + resolution: {integrity: sha512-xkzZZuE+DmWmJBTYneCrMJY24izNQCOdoJMpsXKQx20Va/rTQvNPbdkpx9LBf/pisk8jOwETNAfFQ8YTBc/bZw==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + lodash.merge: 4.6.2 + loglevel: 1.8.0 + dev: false + + /@toruslabs/http-helpers/2.2.0_@babel+runtime@7.17.9: + resolution: {integrity: sha512-xkzZZuE+DmWmJBTYneCrMJY24izNQCOdoJMpsXKQx20Va/rTQvNPbdkpx9LBf/pisk8jOwETNAfFQ8YTBc/bZw==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + '@babel/runtime': 7.17.9 + lodash.merge: 4.6.2 + loglevel: 1.8.0 + dev: false + + /@toruslabs/metadata-helpers/2.5.0_@babel+runtime@7.17.9: + resolution: {integrity: sha512-zhAAGhPcy5Fz68Zg3FXXmYKHHsFBCWsxXurSbdPMFldDrq9GwKChbAbvKBF0sz+juhEOO5gX1BbVah580YVobg==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + '@babel/runtime': 7.17.9 + '@toruslabs/eccrypto': 1.1.8 + '@toruslabs/http-helpers': 2.2.0_@babel+runtime@7.17.9 + elliptic: 6.5.4 + json-stable-stringify: 1.0.1 + keccak: 3.0.2 + dev: false + + /@toruslabs/openlogin-jrpc/1.7.3: + resolution: {integrity: sha512-xjixDKPLZN7T5hCjwmGTU58NttdZiHn3YlK6II2z4v8IifPUwoquYP08XfaE79ksxamgDYkGERf7bQGkV5Wf5w==} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + '@toruslabs/openlogin-utils': 1.7.0 + end-of-stream: 1.4.4 + eth-rpc-errors: 4.0.3 + events: 3.3.0 + fast-safe-stringify: 2.1.1 + once: 1.4.0 + pump: 3.0.0 + readable-stream: 3.6.0 + dev: false + + /@toruslabs/openlogin-utils/1.7.0: + resolution: {integrity: sha512-y+j22v+h6EfzN4sfFnmtmMrcxEdkScdJOAgbtvX42BpUYOuFa1Tv0SZjdtsGGDE4g5szmL3rb9NGMHdBF1rZtg==} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + base64url: 3.0.1 + keccak: 3.0.2 + randombytes: 2.1.0 + dev: false + + /@toruslabs/solana-embed/0.1.6: + resolution: {integrity: sha512-+WcF97qLTyW6xJ/oDmsLRc4KUN0w8/0pPx2QstcUV0OPgV3VON9LXgRFmSLXNvBVjFzie7aOWJFORUIL6Odqhw==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + '@solana/web3.js': 1.39.1 + '@toruslabs/base-controllers': 1.6.18 + '@toruslabs/http-helpers': 2.2.0 + '@toruslabs/openlogin-jrpc': 1.7.3 + eth-rpc-errors: 4.0.3 + fast-deep-equal: 3.1.3 + is-stream: 2.0.1 + lodash-es: 4.17.21 + loglevel: 1.8.0 + pump: 3.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /@toruslabs/torus-embed/1.22.6: + resolution: {integrity: sha512-a+jyK3slcEFxdFFLhzAJa1MkjFbbWf8gEe7PSh1aaX1y0MnbZKvE4S7cQQiFm3ON26DH4QkwZD2JEekx3HEZzQ==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + '@metamask/obs-store': 7.0.0 + '@toruslabs/fetch-node-details': 5.1.0 + '@toruslabs/http-helpers': 2.2.0 + '@toruslabs/openlogin-jrpc': 1.7.3 + '@toruslabs/torus.js': 5.1.0 + create-hash: 1.2.0 + end-of-stream: 1.4.4 + eth-rpc-errors: 4.0.3 + events: 3.3.0 + fast-deep-equal: 3.1.3 + is-stream: 2.0.1 + lodash.merge: 4.6.2 + loglevel: 1.8.0 + once: 1.4.0 + pump: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@toruslabs/torus.js/5.1.0: + resolution: {integrity: sha512-5R9mz6ULwlW8rS+ocjq+2P4BYB/+2cSeHwTyDwA31ZTbreB3ugcUzX5+r+zlx9BTgJC2LdBkCNBJVfDMmzA4iA==} + engines: {node: '>=14.17.0', npm: '>=6.x'} + peerDependencies: + '@babel/runtime': 7.x + dependencies: + '@toruslabs/eccrypto': 1.1.8 + '@toruslabs/http-helpers': 2.2.0 + bn.js: 5.2.0 + elliptic: 6.5.4 + json-stable-stringify: 1.0.1 + loglevel: 1.8.0 + web3-utils: 1.7.3 + dev: false + + /@tsconfig/node10/1.0.8: + resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} + dev: true + + /@tsconfig/node12/1.0.9: + resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} + dev: true + + /@tsconfig/node14/1.0.1: + resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} + dev: true + + /@tsconfig/node16/1.0.2: + resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} + dev: true + + /@typechain/web3-v1/3.0.0_typechain@5.1.2: + resolution: {integrity: sha512-7N9yGzGOmyW8HJAa3U+0oUqc1JxZcMUIh6Fn4jMkl1z98rKyrzvrllXzT2QmqJ9etZKiyI39AVVly/YPYKTCxQ==} + peerDependencies: + typechain: ^5.0.0 + web3: ^1.0.0 + dependencies: + typechain: 5.1.2 + dev: false + + /@types/asn1js/2.0.2: + resolution: {integrity: sha512-t4YHCgtD+ERvH0FyxvNlYwJ2ezhqw7t+Ygh4urQ7dJER8i185JPv6oIM3ey5YQmGN6Zp9EMbpohkjZi9t3UxwA==} + dev: false + optional: true + + /@types/babel__core/7.1.18: + resolution: {integrity: sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==} + dependencies: + '@babel/parser': 7.17.10 + '@babel/types': 7.17.10 + '@types/babel__generator': 7.6.4 + '@types/babel__template': 7.4.1 + '@types/babel__traverse': 7.14.2 + dev: true + /@types/babel__generator/7.6.4: resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} dependencies: @@ -10489,8 +10853,7 @@ packages: /@types/bs58/4.0.1: resolution: {integrity: sha512-yfAgiWgVLjFCmRv8zAcOIHywYATEwiTVccTLnRp6UxTNavT55M9d/uhK3T03St/+8/z/wW+CRjGKUNmEqoHHCA==} dependencies: - base-x: 3.0.8 - dev: false + base-x: 3.0.9 /@types/chrome/0.0.136: resolution: {integrity: sha512-XDEiRhLkMd+SB7Iw3ZUIj/fov3wLd4HyTdLltVszkgl1dBfc3Rb7oPMVZ2Mz2TLqnF7Ow+StbR8E7r9lqpb4DA==} @@ -10747,7 +11110,6 @@ packages: /@types/ethereum-blockies/0.1.0: resolution: {integrity: sha512-yQgqv9dqnFm9pHmCPUBPGu4NRIGSD/hihO+BwcuzxaxmMX3juD97vRvwUB3uY/MUBQ+7pWvUWDPYSAcZ1dIQDA==} - dev: false /@types/expect/1.20.4: resolution: {integrity: sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==} @@ -10916,10 +11278,6 @@ packages: resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==} dev: true - /@types/lodash/4.14.181: - resolution: {integrity: sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==} - dev: false - /@types/lodash/4.14.182: resolution: {integrity: sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==} @@ -11003,12 +11361,13 @@ packages: /@types/punycode/2.1.0: resolution: {integrity: sha512-PG5aLpW6PJOeV2fHRslP4IOMWn+G+Uq8CfnyJ+PDS8ndCbU+soO+fB3NKCKo0p/Jh2Y4aPaiQZsrOXFdzpcA6g==} - dev: false + dev: true /@types/qrcode/1.4.2: resolution: {integrity: sha512-7uNT9L4WQTNJejHTSTdaJhfBSCN73xtXaHFyBJ8TSwiLhe4PRuTue7Iph0s2nG9R/ifUaSnGhLUOZavlBEqDWQ==} dependencies: '@types/node': 17.0.31 + dev: false /@types/qs/6.9.7: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} @@ -11083,6 +11442,7 @@ packages: resolution: {integrity: sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==} dependencies: '@types/react': 18.0.9 + dev: false /@types/react/18.0.9: resolution: {integrity: sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==} @@ -11477,74 +11837,146 @@ packages: tiny-warning: 1.0.3 dev: false - /@walletconnect/browser-utils/1.4.1: - resolution: {integrity: sha512-ONrkPSI/27o1Wj8kUwE0uUZFk0GDCDQBJy614GsrhcwuQwJEW/B+nXPQ+Ca/4WvQySM5hWVHp1gO1kozSUkh3A==} + /@walletconnect/browser-utils/1.7.8: + resolution: {integrity: sha512-iCL0XCWOZaABIc0lqA79Vyaybr3z26nt8mxiwvfrG8oaKUf5Y21Of4dj+wIXQ4Hhblre6SgDlU0Ffb39+1THOw==} dependencies: - '@walletconnect/types': 1.4.1 + '@walletconnect/safe-json': 1.0.0 + '@walletconnect/types': 1.7.8 + '@walletconnect/window-getters': 1.0.0 + '@walletconnect/window-metadata': 1.0.0 detect-browser: 5.2.0 - safe-json-utils: 1.0.0 - window-getters: 1.0.0 - window-metadata: 1.0.0 dev: false - /@walletconnect/client/1.4.1: - resolution: {integrity: sha512-JRW+9+j9LwszY76/WcIumEiLmhX7eidorH9SFFmI2pFfbrhB6KLe87FaA106kxwZUyWKOLZ6jVV4d1urYSdEwA==} + /@walletconnect/client/1.7.8: + resolution: {integrity: sha512-pBroM6jZAaUM0SoXJZg5U7aPTiU3ljQAw3Xh/i2pxFDeN/oPKao7husZ5rdxS5xuGSV6YpqqRb0RxW1IeoR2Pg==} dependencies: - '@walletconnect/core': 1.4.1 - '@walletconnect/iso-crypto': 1.4.1 - '@walletconnect/types': 1.4.1 - '@walletconnect/utils': 1.4.1 + '@walletconnect/core': 1.7.8 + '@walletconnect/iso-crypto': 1.7.8 + '@walletconnect/types': 1.7.8 + '@walletconnect/utils': 1.7.8 transitivePeerDependencies: - bufferutil - utf-8-validate dev: false - /@walletconnect/core/1.4.1: - resolution: {integrity: sha512-NzWvhk4akI2uhORUxMDMS/8yAdfp+nzvb5QdTE0eTD0WOrK16qAfYLSU/IjFc2J2lqhuPVxfO2XV7QoxgCXfwA==} + /@walletconnect/core/1.7.8: + resolution: {integrity: sha512-9xcQ0YNf9JUFb0YOX1Mpy4Yojt+6w2yQz/0aIEyj2X/s9D71NW0fTYsMcdhkLOI7mn2cqVbx2t1lRvdgqsbrSQ==} dependencies: - '@walletconnect/socket-transport': 1.4.1 - '@walletconnect/types': 1.4.1 - '@walletconnect/utils': 1.4.1 + '@walletconnect/socket-transport': 1.7.8 + '@walletconnect/types': 1.7.8 + '@walletconnect/utils': 1.7.8 transitivePeerDependencies: - bufferutil - utf-8-validate dev: false - /@walletconnect/iso-crypto/1.4.1: - resolution: {integrity: sha512-rzfqM/DFhzNxBriMCU4DOarPkH+Brgll+2a2YeO6zHgMlwZtBKi5mMgzBwbDC3XygOvKbcRTB9G9hr8uYn+i5g==} + /@walletconnect/crypto/1.0.2: + resolution: {integrity: sha512-+OlNtwieUqVcOpFTvLBvH+9J9pntEqH5evpINHfVxff1XIgwV55PpbdvkHu6r9Ib4WQDOFiD8OeeXs1vHw7xKQ==} dependencies: - '@pedrouid/iso-crypto': 1.1.0 - '@walletconnect/types': 1.4.1 - '@walletconnect/utils': 1.4.1 + '@walletconnect/encoding': 1.0.1 + '@walletconnect/environment': 1.0.0 + '@walletconnect/randombytes': 1.0.2 + aes-js: 3.1.2 + hash.js: 1.1.7 dev: false - /@walletconnect/socket-transport/1.4.1: - resolution: {integrity: sha512-/5Mhu4bu3tS52LqTlmmjx5x/N89XqbuT0YMobvQ+k/m+VqSeBDntqIjwBt7XiFlCbrUTq3/yTajavGFxWFB6pA==} + /@walletconnect/encoding/1.0.1: + resolution: {integrity: sha512-8opL2rs6N6E3tJfsqwS82aZQDL3gmupWUgmvuZ3CGU7z/InZs3R9jkzH8wmYtpbq0sFK3WkJkQRZFFk4BkrmFA==} dependencies: - '@walletconnect/types': 1.4.1 - '@walletconnect/utils': 1.4.1 - ws: 7.3.0 + is-typedarray: 1.0.0 + typedarray-to-buffer: 3.1.5 + dev: false + + /@walletconnect/environment/1.0.0: + resolution: {integrity: sha512-4BwqyWy6KpSvkocSaV7WR3BlZfrxLbJSLkg+j7Gl6pTDE+U55lLhJvQaMuDVazXYxcjBsG09k7UlH7cGiUI5vQ==} + dev: false + + /@walletconnect/iso-crypto/1.7.8: + resolution: {integrity: sha512-Qo6qDcMG0Ac+9fpWE0h/oE55NHLk6eM2vlXpWlQDN/me7RZGrkvk+LXsAkQ3UiYPEiPfq4eswcyRWC9AcrAscg==} + dependencies: + '@walletconnect/crypto': 1.0.2 + '@walletconnect/types': 1.7.8 + '@walletconnect/utils': 1.7.8 + dev: false + + /@walletconnect/jsonrpc-types/1.0.0: + resolution: {integrity: sha512-11QXNq5H1PKZk7bP8SxgmCw3HRaDuPOVE+wObqEvmhc7OWYUZqfuaaMb+OXGRSOHL3sbC+XHfdeCxFTMXSFyng==} + dependencies: + keyvaluestorage-interface: 1.0.0 + dev: false + + /@walletconnect/jsonrpc-utils/1.0.0: + resolution: {integrity: sha512-qUHbKUK6sHeHn67qtHZoLoYk5hS6x1arTPjKDRkY93/6Fx+ZmNIpdm1owX3l6aYueyegJ7mz43FpvYHUqJ8xcw==} + dependencies: + '@walletconnect/environment': 1.0.0 + '@walletconnect/jsonrpc-types': 1.0.0 + dev: false + + /@walletconnect/mobile-registry/1.4.0: + resolution: {integrity: sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw==} + deprecated: 'Deprecated in favor of dynamic registry available from: https://github.com/walletconnect/walletconnect-registry' + dev: false + + /@walletconnect/qrcode-modal/1.7.8: + resolution: {integrity: sha512-LqNJMLWO+ljvoRSdq8tcEslW0imKrrb+ugs3bw4w/jEI1FSJzVeinEsgVpyaMv8wsUcyTcSCXSkXpT1SXHtcpw==} + dependencies: + '@walletconnect/browser-utils': 1.7.8 + '@walletconnect/mobile-registry': 1.4.0 + '@walletconnect/types': 1.7.8 + copy-to-clipboard: 3.3.1 + preact: 10.4.1 + qrcode: 1.4.4 + dev: false + + /@walletconnect/randombytes/1.0.2: + resolution: {integrity: sha512-ivgOtAyqQnN0rLQmOFPemsgYGysd/ooLfaDA/ACQ3cyqlca56t3rZc7pXfqJOIETx/wSyoF5XbwL+BqYodw27A==} + dependencies: + '@walletconnect/encoding': 1.0.1 + '@walletconnect/environment': 1.0.0 + randombytes: 2.1.0 + dev: false + + /@walletconnect/safe-json/1.0.0: + resolution: {integrity: sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg==} + dev: false + + /@walletconnect/socket-transport/1.7.8: + resolution: {integrity: sha512-bqEjLxfSzG79v2OT7XVOZoyUkg6g3yng0fURrdLusWs42fYHWnrSrIZDejFn8N5PiZk5R2edrggkQ7w0VUUAfw==} + dependencies: + '@walletconnect/types': 1.7.8 + '@walletconnect/utils': 1.7.8 + ws: 7.5.3 transitivePeerDependencies: - bufferutil - utf-8-validate dev: false - /@walletconnect/types/1.4.1: - resolution: {integrity: sha512-lzS9NbXjVb5N+W/UnCZAflxjLtYepUi4ev1IeFozSvr/cWxAhEe/sjixe7WEIpYklW27kfBhKccMH/KjUoRC7w==} + /@walletconnect/types/1.7.8: + resolution: {integrity: sha512-0oSZhKIrtXRJVP1jQ0EDTRtotQY6kggGjDcmm/LLQBKnOZXdPeo0sPkV/7DjT5plT3O7Cjc6JvuXt9WOY0hlCA==} dev: false - /@walletconnect/utils/1.4.1: - resolution: {integrity: sha512-JrVjcXmWVcU02fmVNZFBpJ48f84qyar24CF7szGv+k9ZxvU9J7XkM+Fic4790Dt3DaWhOzS9/eBUa+BEZcBbNw==} + /@walletconnect/utils/1.7.8: + resolution: {integrity: sha512-DSpfH6Do0TQmdrgzu+SyjVhupVjN0WEMvNWGK9K4VlSmLFpCWfme7qxzrvuxBZ47gDqs1kGWvjyJmviWqvOnAg==} dependencies: - '@json-rpc-tools/utils': 1.6.1 - '@walletconnect/browser-utils': 1.4.1 - '@walletconnect/types': 1.4.1 + '@walletconnect/browser-utils': 1.7.8 + '@walletconnect/encoding': 1.0.1 + '@walletconnect/jsonrpc-utils': 1.0.0 + '@walletconnect/types': 1.7.8 bn.js: 4.11.8 - enc-utils: 3.0.0 js-sha3: 0.8.0 query-string: 6.13.5 dev: false + /@walletconnect/window-getters/1.0.0: + resolution: {integrity: sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA==} + dev: false + + /@walletconnect/window-metadata/1.0.0: + resolution: {integrity: sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA==} + dependencies: + '@walletconnect/window-getters': 1.0.0 + dev: false + /@webassemblyjs/ast/1.11.1: resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} dependencies: @@ -11940,7 +12372,6 @@ packages: resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} engines: {node: '>=0.4.0'} hasBin: true - dev: true /address/1.1.2: resolution: {integrity: sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==} @@ -12136,7 +12567,7 @@ packages: dev: true /ansi-styles/2.2.1: - resolution: {integrity: sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=} + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} dev: false @@ -12196,6 +12627,26 @@ packages: normalize-path: 2.1.1 transitivePeerDependencies: - supports-color + dev: true + + /anymatch/2.0.0_supports-color@4.5.0: + resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + dependencies: + micromatch: 3.1.10_supports-color@4.5.0 + normalize-path: 2.1.1 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /anymatch/2.0.0_supports-color@6.1.0: + resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + dependencies: + micromatch: 3.1.10_supports-color@6.1.0 + normalize-path: 2.1.1 + transitivePeerDependencies: + - supports-color + dev: false /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} @@ -12537,6 +12988,12 @@ packages: resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==} dev: false + /async-mutex/0.3.2: + resolution: {integrity: sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==} + dependencies: + tslib: 2.4.0 + dev: false + /async-settle/1.0.0: resolution: {integrity: sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=} engines: {node: '>= 0.10'} @@ -12545,7 +13002,7 @@ packages: dev: true /async/1.5.2: - resolution: {integrity: sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=} + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} dev: false /async/2.6.3: @@ -12612,10 +13069,12 @@ packages: mkdirp: 0.5.6 source-map-support: 0.5.21 typescript: 2.9.2 + transitivePeerDependencies: + - supports-color dev: false /aws-sign2/0.7.0: - resolution: {integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=} + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} dev: false /aws4/1.11.0: @@ -12623,7 +13082,7 @@ packages: dev: false /axios/0.17.1: - resolution: {integrity: sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=} + resolution: {integrity: sha512-mZzWRyJeJ0rtK7e1/6iYBUzmeXjzei+1h1IvbedyU0sB52++tU5AU6r6TLXpwNVR0ebXIpvTVW+9CpWNyc1n8w==} deprecated: Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410 dependencies: follow-redirects: 1.14.9 @@ -12657,7 +13116,7 @@ packages: dev: false /babel-code-frame/6.26.0: - resolution: {integrity: sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=} + resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==} dependencies: chalk: 1.1.3 esutils: 2.0.3 @@ -12686,6 +13145,8 @@ packages: private: 0.1.8 slash: 1.0.0 source-map: 0.5.7 + transitivePeerDependencies: + - supports-color dev: false /babel-generator/6.26.1: @@ -12702,72 +13163,82 @@ packages: dev: false /babel-helper-builder-binary-assignment-operator-visitor/6.24.1: - resolution: {integrity: sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=} + resolution: {integrity: sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==} dependencies: babel-helper-explode-assignable-expression: 6.24.1 babel-runtime: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-helper-call-delegate/6.24.1: - resolution: {integrity: sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=} + resolution: {integrity: sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==} dependencies: babel-helper-hoist-variables: 6.24.1 babel-runtime: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-helper-define-map/6.26.0: - resolution: {integrity: sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=} + resolution: {integrity: sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==} dependencies: babel-helper-function-name: 6.24.1 babel-runtime: 6.26.0 babel-types: 6.26.0 lodash: 4.17.21 + transitivePeerDependencies: + - supports-color dev: false /babel-helper-explode-assignable-expression/6.24.1: - resolution: {integrity: sha1-8luCz33BBDPFX3BZLVdGQArCLKo=} + resolution: {integrity: sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==} dependencies: babel-runtime: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-helper-function-name/6.24.1: - resolution: {integrity: sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=} + resolution: {integrity: sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==} dependencies: babel-helper-get-function-arity: 6.24.1 babel-runtime: 6.26.0 babel-template: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-helper-get-function-arity/6.24.1: - resolution: {integrity: sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=} + resolution: {integrity: sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 dev: false /babel-helper-hoist-variables/6.24.1: - resolution: {integrity: sha1-HssnaJydJVE+rbyZFKc/VAi+enY=} + resolution: {integrity: sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 dev: false /babel-helper-optimise-call-expression/6.24.1: - resolution: {integrity: sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=} + resolution: {integrity: sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 dev: false /babel-helper-regex/6.26.0: - resolution: {integrity: sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=} + resolution: {integrity: sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 @@ -12775,17 +13246,19 @@ packages: dev: false /babel-helper-remap-async-to-generator/6.24.1: - resolution: {integrity: sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=} + resolution: {integrity: sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==} dependencies: babel-helper-function-name: 6.24.1 babel-runtime: 6.26.0 babel-template: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-helper-replace-supers/6.24.1: - resolution: {integrity: sha1-v22/5Dk40XNpohPKiov3S2qQqxo=} + resolution: {integrity: sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==} dependencies: babel-helper-optimise-call-expression: 6.24.1 babel-messages: 6.23.0 @@ -12793,13 +13266,17 @@ packages: babel-template: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-helpers/6.24.1: - resolution: {integrity: sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=} + resolution: {integrity: sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==} dependencies: babel-runtime: 6.26.0 babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-jest/28.1.0_@babel+core@7.17.10: @@ -12895,7 +13372,7 @@ packages: dev: true /babel-messages/6.23.0: - resolution: {integrity: sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=} + resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} dependencies: babel-runtime: 6.26.0 dev: false @@ -12918,7 +13395,7 @@ packages: dev: true /babel-plugin-check-es2015-constants/6.22.0: - resolution: {integrity: sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=} + resolution: {integrity: sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==} dependencies: babel-runtime: 6.26.0 dev: false @@ -13227,11 +13704,11 @@ packages: dev: true /babel-plugin-syntax-async-functions/6.13.0: - resolution: {integrity: sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=} + resolution: {integrity: sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==} dev: false /babel-plugin-syntax-exponentiation-operator/6.13.0: - resolution: {integrity: sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=} + resolution: {integrity: sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==} dev: false /babel-plugin-syntax-jsx/6.18.0: @@ -13239,41 +13716,45 @@ packages: dev: true /babel-plugin-syntax-trailing-function-commas/6.22.0: - resolution: {integrity: sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=} + resolution: {integrity: sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==} dev: false /babel-plugin-transform-async-to-generator/6.24.1: - resolution: {integrity: sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=} + resolution: {integrity: sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==} dependencies: babel-helper-remap-async-to-generator: 6.24.1 babel-plugin-syntax-async-functions: 6.13.0 babel-runtime: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-arrow-functions/6.22.0: - resolution: {integrity: sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=} + resolution: {integrity: sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-block-scoped-functions/6.22.0: - resolution: {integrity: sha1-u8UbSflk1wy42OC5ToICRs46YUE=} + resolution: {integrity: sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-block-scoping/6.26.0: - resolution: {integrity: sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=} + resolution: {integrity: sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==} dependencies: babel-runtime: 6.26.0 babel-template: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 lodash: 4.17.21 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-classes/6.24.1: - resolution: {integrity: sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=} + resolution: {integrity: sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==} dependencies: babel-helper-define-map: 6.26.0 babel-helper-function-name: 6.24.1 @@ -13284,54 +13765,62 @@ packages: babel-template: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-computed-properties/6.24.1: - resolution: {integrity: sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=} + resolution: {integrity: sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==} dependencies: babel-runtime: 6.26.0 babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-destructuring/6.23.0: - resolution: {integrity: sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=} + resolution: {integrity: sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-duplicate-keys/6.24.1: - resolution: {integrity: sha1-c+s9MQypaePvnskcU3QabxV2Qj4=} + resolution: {integrity: sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 dev: false /babel-plugin-transform-es2015-for-of/6.23.0: - resolution: {integrity: sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=} + resolution: {integrity: sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-function-name/6.24.1: - resolution: {integrity: sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=} + resolution: {integrity: sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==} dependencies: babel-helper-function-name: 6.24.1 babel-runtime: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-literals/6.22.0: - resolution: {integrity: sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=} + resolution: {integrity: sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-modules-amd/6.24.1: - resolution: {integrity: sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=} + resolution: {integrity: sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==} dependencies: babel-plugin-transform-es2015-modules-commonjs: 6.26.2 babel-runtime: 6.26.0 babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-modules-commonjs/6.26.2: @@ -13341,33 +13830,41 @@ packages: babel-runtime: 6.26.0 babel-template: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-modules-systemjs/6.24.1: - resolution: {integrity: sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=} + resolution: {integrity: sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==} dependencies: babel-helper-hoist-variables: 6.24.1 babel-runtime: 6.26.0 babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-modules-umd/6.24.1: - resolution: {integrity: sha1-rJl+YoXNGO1hdq22B9YCNErThGg=} + resolution: {integrity: sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==} dependencies: babel-plugin-transform-es2015-modules-amd: 6.24.1 babel-runtime: 6.26.0 babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-object-super/6.24.1: - resolution: {integrity: sha1-JM72muIcuDp/hgPa0CH1cusnj40=} + resolution: {integrity: sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==} dependencies: babel-helper-replace-supers: 6.24.1 babel-runtime: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-parameters/6.24.1: - resolution: {integrity: sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=} + resolution: {integrity: sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==} dependencies: babel-helper-call-delegate: 6.24.1 babel-helper-get-function-arity: 6.24.1 @@ -13375,23 +13872,25 @@ packages: babel-template: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-es2015-shorthand-properties/6.24.1: - resolution: {integrity: sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=} + resolution: {integrity: sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 dev: false /babel-plugin-transform-es2015-spread/6.22.0: - resolution: {integrity: sha1-1taKmfia7cRTbIGlQujdnxdG+NE=} + resolution: {integrity: sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-sticky-regex/6.24.1: - resolution: {integrity: sha1-AMHNsaynERLN8M9hJsLta0V8zbw=} + resolution: {integrity: sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==} dependencies: babel-helper-regex: 6.26.0 babel-runtime: 6.26.0 @@ -13399,19 +13898,19 @@ packages: dev: false /babel-plugin-transform-es2015-template-literals/6.22.0: - resolution: {integrity: sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=} + resolution: {integrity: sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-typeof-symbol/6.23.0: - resolution: {integrity: sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=} + resolution: {integrity: sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==} dependencies: babel-runtime: 6.26.0 dev: false /babel-plugin-transform-es2015-unicode-regex/6.24.1: - resolution: {integrity: sha1-04sS9C6nMj9yk4fxinxa4frrNek=} + resolution: {integrity: sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==} dependencies: babel-helper-regex: 6.26.0 babel-runtime: 6.26.0 @@ -13419,21 +13918,23 @@ packages: dev: false /babel-plugin-transform-exponentiation-operator/6.24.1: - resolution: {integrity: sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=} + resolution: {integrity: sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==} dependencies: babel-helper-builder-binary-assignment-operator-visitor: 6.24.1 babel-plugin-syntax-exponentiation-operator: 6.13.0 babel-runtime: 6.26.0 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-transform-regenerator/6.26.0: - resolution: {integrity: sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=} + resolution: {integrity: sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==} dependencies: regenerator-transform: 0.10.1 dev: false /babel-plugin-transform-strict-mode/6.24.1: - resolution: {integrity: sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=} + resolution: {integrity: sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==} dependencies: babel-runtime: 6.26.0 babel-types: 6.26.0 @@ -13495,6 +13996,8 @@ packages: browserslist: 3.2.8 invariant: 2.2.4 semver: 5.7.1 + transitivePeerDependencies: + - supports-color dev: false /babel-preset-jest/28.0.2_@babel+core@7.17.10: @@ -13512,7 +14015,7 @@ packages: dev: true /babel-register/6.26.0: - resolution: {integrity: sha1-btAhFz4vy0htestFxgCahW9kcHE=} + resolution: {integrity: sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==} dependencies: babel-core: 6.26.3 babel-runtime: 6.26.0 @@ -13521,27 +14024,31 @@ packages: lodash: 4.17.21 mkdirp: 0.5.6 source-map-support: 0.4.18 + transitivePeerDependencies: + - supports-color dev: false /babel-runtime/6.26.0: - resolution: {integrity: sha1-llxwWGaOgrVde/4E/yM3vItWR/4=} + resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} dependencies: core-js: 2.6.12 regenerator-runtime: 0.11.1 dev: false /babel-template/6.26.0: - resolution: {integrity: sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=} + resolution: {integrity: sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==} dependencies: babel-runtime: 6.26.0 babel-traverse: 6.26.0 babel-types: 6.26.0 babylon: 6.18.0 lodash: 4.17.21 + transitivePeerDependencies: + - supports-color dev: false /babel-traverse/6.26.0: - resolution: {integrity: sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=} + resolution: {integrity: sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==} dependencies: babel-code-frame: 6.26.0 babel-messages: 6.23.0 @@ -13552,10 +14059,12 @@ packages: globals: 9.18.0 invariant: 2.2.4 lodash: 4.17.21 + transitivePeerDependencies: + - supports-color dev: false /babel-types/6.26.0: - resolution: {integrity: sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=} + resolution: {integrity: sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==} dependencies: babel-runtime: 6.26.0 esutils: 2.0.3 @@ -13564,10 +14073,12 @@ packages: dev: false /babelify/7.3.0: - resolution: {integrity: sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=} + resolution: {integrity: sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA==} dependencies: babel-core: 6.26.3 object-assign: 4.1.1 + transitivePeerDependencies: + - supports-color dev: false /babylon/6.18.0: @@ -13610,7 +14121,6 @@ packages: resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} dependencies: safe-buffer: 5.2.1 - dev: false /base/0.11.2: resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} @@ -13641,6 +14151,11 @@ packages: resolution: {integrity: sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg==} dev: false + /base64url/3.0.1: + resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} + engines: {node: '>=6.0.0'} + dev: false + /batch-processor/1.0.0: resolution: {integrity: sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=} dev: true @@ -13649,7 +14164,7 @@ packages: resolution: {integrity: sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=} /bcrypt-pbkdf/1.0.2: - resolution: {integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=} + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} dependencies: tweetnacl: 0.14.5 dev: false @@ -13719,7 +14234,7 @@ packages: file-uri-to-path: 1.0.0 /bintrees/1.0.2: - resolution: {integrity: sha1-SfiW1uhYpKSZ34XDj7OZua/4QPg=} + resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==} dev: false /bip32/2.0.6: @@ -13744,6 +14259,13 @@ packages: randombytes: 2.1.0 dev: false + /bip66/1.1.5: + resolution: {integrity: sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==} + dependencies: + safe-buffer: 5.2.1 + dev: false + optional: true + /blakejs/1.1.1: resolution: {integrity: sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==} @@ -13795,6 +14317,26 @@ packages: qs: 6.9.7 raw-body: 2.4.3 type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + + /body-parser/1.19.2_supports-color@6.1.0: + resolution: {integrity: sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + content-type: 1.0.4 + debug: 2.6.9_supports-color@6.1.0 + depd: 1.1.2 + http-errors: 1.8.1 + iconv-lite: 0.4.24 + on-finished: 2.3.0 + qs: 6.9.7 + raw-body: 2.4.3 + type-is: 1.6.18 + transitivePeerDependencies: + - supports-color + dev: false /body-parser/1.20.0: resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==} @@ -13812,6 +14354,8 @@ packages: raw-body: 2.5.1 type-is: 1.6.18 unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color dev: false /bonjour-service/1.0.11: @@ -13880,6 +14424,10 @@ packages: text-encoding-utf-8: 1.0.2 dev: false + /bowser/2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + dev: false + /boxen/5.1.2: resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} engines: {node: '>=10'} @@ -13923,6 +14471,43 @@ packages: transitivePeerDependencies: - supports-color + /braces/2.3.2_supports-color@4.5.0: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2_supports-color@4.5.0 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /braces/2.3.2_supports-color@6.1.0: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2_supports-color@6.1.0 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /braces/3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -14049,6 +14634,17 @@ packages: node-int64: 0.4.0 dev: true + /buffer-alloc-unsafe/1.1.0: + resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} + dev: false + + /buffer-alloc/1.2.0: + resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} + dependencies: + buffer-alloc-unsafe: 1.1.0 + buffer-fill: 1.0.0 + dev: false + /buffer-crc32/0.2.13: resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} dev: false @@ -14058,6 +14654,10 @@ packages: engines: {node: '>=0.4.0'} dev: true + /buffer-fill/1.0.0: + resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} + dev: false + /buffer-from/0.1.2: resolution: {integrity: sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==} dev: false @@ -14075,7 +14675,7 @@ packages: dev: false /buffer-to-arraybuffer/0.0.5: - resolution: {integrity: sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=} + resolution: {integrity: sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==} dev: false /buffer-xor/1.0.3: @@ -14115,7 +14715,7 @@ packages: node-gyp-build: 4.3.0 /builtin-modules/1.1.1: - resolution: {integrity: sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=} + resolution: {integrity: sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==} engines: {node: '>=0.10.0'} dev: false @@ -14167,7 +14767,7 @@ packages: mississippi: 3.0.0 mkdirp: 0.5.6 move-concurrently: 1.0.1 - promise-inflight: 1.0.1 + promise-inflight: 1.0.1_bluebird@3.7.2 rimraf: 2.7.1 ssri: 6.0.2 unique-filename: 1.1.1 @@ -14196,6 +14796,8 @@ packages: ssri: 8.0.1 tar: 6.1.11 unique-filename: 1.1.1 + transitivePeerDependencies: + - bluebird dev: true /cache-base/1.0.1: @@ -14322,7 +14924,7 @@ packages: dev: true /caseless/0.12.0: - resolution: {integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=} + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} dev: false /cborg/1.7.0: @@ -14343,7 +14945,7 @@ packages: dev: false /chalk/1.1.3: - resolution: {integrity: sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=} + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} dependencies: ansi-styles: 2.2.1 @@ -14396,7 +14998,7 @@ packages: dev: false /checkpoint-store/1.1.0: - resolution: {integrity: sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=} + resolution: {integrity: sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg==} dependencies: functional-red-black-tree: 1.0.1 dev: false @@ -14420,6 +15022,50 @@ packages: fsevents: 1.2.13 transitivePeerDependencies: - supports-color + dev: true + + /chokidar/2.1.8_supports-color@4.5.0: + resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} + deprecated: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies + dependencies: + anymatch: 2.0.0_supports-color@4.5.0 + async-each: 1.0.3 + braces: 2.3.2_supports-color@4.5.0 + glob-parent: 3.1.0 + inherits: 2.0.4 + is-binary-path: 1.0.1 + is-glob: 4.0.3 + normalize-path: 3.0.0 + path-is-absolute: 1.0.1 + readdirp: 2.2.1_supports-color@4.5.0 + upath: 1.2.0 + optionalDependencies: + fsevents: 1.2.13 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /chokidar/2.1.8_supports-color@6.1.0: + resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} + deprecated: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies + dependencies: + anymatch: 2.0.0_supports-color@6.1.0 + async-each: 1.0.3 + braces: 2.3.2_supports-color@6.1.0 + glob-parent: 3.1.0 + inherits: 2.0.4 + is-binary-path: 1.0.1 + is-glob: 4.0.3 + normalize-path: 3.0.0 + path-is-absolute: 1.0.1 + readdirp: 2.2.1_supports-color@6.1.0 + upath: 1.2.0 + optionalDependencies: + fsevents: 1.2.13 + transitivePeerDependencies: + - supports-color + dev: false /chokidar/3.5.2: resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} @@ -14876,6 +15522,24 @@ packages: on-headers: 1.0.2 safe-buffer: 5.1.2 vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /compression/1.7.4_supports-color@6.1.0: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9_supports-color@6.1.0 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false /compute-scroll-into-view/1.0.17: resolution: {integrity: sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==} @@ -15034,6 +15698,7 @@ packages: mkdirp: 0.5.6 webpack: 4.46.0 transitivePeerDependencies: + - supports-color - webpack-cli - webpack-command dev: true @@ -15164,6 +15829,8 @@ packages: p-all: 2.1.0 p-filter: 2.1.0 p-map: 3.0.0 + transitivePeerDependencies: + - supports-color dev: true /crc-32/1.2.2: @@ -15791,8 +16458,38 @@ packages: dependencies: ms: 2.0.0 + /debug/2.6.9_supports-color@4.5.0: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + supports-color: 4.5.0 + dev: false + optional: true + + /debug/2.6.9_supports-color@6.1.0: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + supports-color: 6.1.0 + dev: false + /debug/3.1.0: resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.0.0 dev: false @@ -15806,6 +16503,19 @@ packages: optional: true dependencies: ms: 2.1.3 + dev: true + + /debug/3.2.7_supports-color@6.1.0: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + supports-color: 6.1.0 + dev: false /debug/4.3.2: resolution: {integrity: sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==} @@ -16105,6 +16815,8 @@ packages: dependencies: address: 1.1.2 debug: 2.6.9 + transitivePeerDependencies: + - supports-color dev: true /did-jwt/5.12.3: @@ -16368,6 +17080,16 @@ packages: tslib: 2.4.0 dev: true + /drbg.js/1.0.1: + resolution: {integrity: sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=} + engines: {node: '>=0.10'} + dependencies: + browserify-aes: 1.2.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + dev: false + optional: true + /duplexer/0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: false @@ -16515,13 +17237,6 @@ packages: hoist-non-react-statics: 3.3.2 dev: true - /enc-utils/3.0.0: - resolution: {integrity: sha512-e57t/Z2HzWOLwOp7DZcV0VMEY8t7ptWwsxyp6kM2b2zrk6JqIpXxzkruHAMiBsy5wg9jp/183GdiRXCvBtzsYg==} - dependencies: - is-typedarray: 1.0.0 - typedarray-to-buffer: 3.1.5 - dev: false - /encode-utf8/1.0.3: resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} dev: false @@ -16565,6 +17280,21 @@ packages: yeast: 0.1.2 transitivePeerDependencies: - bufferutil + - supports-color + - utf-8-validate + dev: false + + /engine.io-client/6.2.2: + resolution: {integrity: sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + engine.io-parser: 5.0.4 + ws: 8.2.3 + xmlhttprequest-ssl: 2.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color - utf-8-validate dev: false @@ -16578,6 +17308,11 @@ packages: has-binary2: 1.0.3 dev: false + /engine.io-parser/5.0.4: + resolution: {integrity: sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==} + engines: {node: '>=10.0.0'} + dev: false + /enhanced-resolve/3.3.0: resolution: {integrity: sha512-2qbxE7ek3YxPJ1ML6V+satHkzHpJQKWkRHmRx6mfAoW59yP8YH8BFplbegSP+u2hBd6B6KCOpvJQ3dZAP+hkpg==} engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} @@ -17225,6 +17960,8 @@ packages: json-rpc-engine: 3.8.0 pify: 2.3.0 tape: 4.15.1 + transitivePeerDependencies: + - supports-color dev: false /eth-ens-namehash/1.0.2: @@ -17250,6 +17987,10 @@ packages: servify: 0.1.12 ws: 3.3.3 xhr-request-promise: 0.1.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate dev: false /eth-lib/0.2.8: @@ -17682,19 +18423,50 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /expand-brackets/2.1.4: + /expand-brackets/2.1.4: + resolution: {integrity: sha1-t3c14xXOMPa27/D4OwQVGiJEliI=} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + + /expand-brackets/2.1.4_supports-color@4.5.0: + resolution: {integrity: sha1-t3c14xXOMPa27/D4OwQVGiJEliI=} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9_supports-color@4.5.0 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@4.5.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /expand-brackets/2.1.4_supports-color@6.1.0: resolution: {integrity: sha1-t3c14xXOMPa27/D4OwQVGiJEliI=} engines: {node: '>=0.10.0'} dependencies: - debug: 2.6.9 + debug: 2.6.9_supports-color@6.1.0 define-property: 0.2.5 extend-shallow: 2.0.1 posix-character-classes: 0.1.1 regex-not: 1.0.2 - snapdragon: 0.8.2 + snapdragon: 0.8.2_supports-color@6.1.0 to-regex: 3.0.2 transitivePeerDependencies: - supports-color + dev: false /expand-tilde/2.0.2: resolution: {integrity: sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=} @@ -17748,6 +18520,46 @@ packages: type-is: 1.6.18 utils-merge: 1.0.1 vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + /express/4.17.3_supports-color@6.1.0: + resolution: {integrity: sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.19.2_supports-color@6.1.0 + content-disposition: 0.5.4 + content-type: 1.0.4 + cookie: 0.4.2 + cookie-signature: 1.0.6 + debug: 2.6.9_supports-color@6.1.0 + depd: 1.1.2 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.1.2_supports-color@6.1.0 + fresh: 0.5.2 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.3.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.9.7 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.17.2_supports-color@6.1.0 + serve-static: 1.14.2_supports-color@6.1.0 + setprototypeof: 1.2.0 + statuses: 1.5.0 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false /ext/1.4.0: resolution: {integrity: sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==} @@ -17799,6 +18611,39 @@ packages: transitivePeerDependencies: - supports-color + /extglob/2.0.4_supports-color@4.5.0: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4_supports-color@4.5.0 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@4.5.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /extglob/2.0.4_supports-color@6.1.0: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4_supports-color@6.1.0 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /extract-files/9.0.0: resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==} engines: {node: ^10.17.0 || ^12.0.0 || >= 13.7.0} @@ -17855,6 +18700,8 @@ packages: is-glob: 4.0.3 merge2: 1.4.1 micromatch: 3.1.10 + transitivePeerDependencies: + - supports-color dev: true /fast-glob/3.2.11: @@ -18027,6 +18874,23 @@ packages: parseurl: 1.3.3 statuses: 1.5.0 unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + /finalhandler/1.1.2_supports-color@6.1.0: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9_supports-color@6.1.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false /find-cache-dir/2.1.0: resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} @@ -18254,9 +19118,21 @@ packages: resolution: {integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=} dev: false - /fork-ts-checker-webpack-plugin/4.1.6: + /fork-ts-checker-webpack-plugin/4.1.6_webpack@4.46.0: resolution: {integrity: sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==} engines: {node: '>=6.11.5', yarn: '>=1.0.0'} + peerDependencies: + eslint: '>= 6' + typescript: '>= 2.7' + vue-template-compiler: '*' + webpack: '>= 4' + peerDependenciesMeta: + eslint: + optional: true + typescript: + optional: true + vue-template-compiler: + optional: true dependencies: '@babel/code-frame': 7.16.7 chalk: 2.4.2 @@ -18264,7 +19140,10 @@ packages: minimatch: 3.1.2 semver: 5.7.1 tapable: 1.1.3 + webpack: 4.46.0 worker-rpc: 0.1.1 + transitivePeerDependencies: + - supports-color dev: true /fork-ts-checker-webpack-plugin/6.5.1_webpack@4.46.0: @@ -18843,6 +19722,8 @@ packages: ignore: 4.0.6 pify: 4.0.1 slash: 2.0.0 + transitivePeerDependencies: + - supports-color dev: true /glogg/1.0.2: @@ -19340,8 +20221,6 @@ packages: param-case: 3.0.4 relateurl: 0.2.7 terser: 5.10.0 - transitivePeerDependencies: - - acorn dev: true /html-parse-stringify/3.0.1: @@ -19404,8 +20283,6 @@ packages: pretty-error: 4.0.0 tapable: 2.2.1 webpack: 5.72.0_webpack-cli@4.9.2 - transitivePeerDependencies: - - acorn dev: true /htmlparser2/6.1.0: @@ -19471,16 +20348,17 @@ packages: - supports-color dev: false - /http-proxy-middleware/0.19.1_debug@4.3.4: + /http-proxy-middleware/0.19.1_tmpgdztspuwvsxzgjkhoqk7duq: resolution: {integrity: sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==} engines: {node: '>=4.0.0'} dependencies: http-proxy: 1.18.1_debug@4.3.4 is-glob: 4.0.3 lodash: 4.17.21 - micromatch: 3.1.10 + micromatch: 3.1.10_supports-color@6.1.0 transitivePeerDependencies: - debug + - supports-color dev: false /http-proxy-middleware/2.0.4_@types+express@4.17.13: @@ -20413,7 +21291,6 @@ packages: /isarray/2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true /isexe/2.0.0: resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} @@ -20613,7 +21490,7 @@ packages: dependencies: '@types/connect': 3.4.35 '@types/express-serve-static-core': 4.17.28 - '@types/lodash': 4.14.181 + '@types/lodash': 4.14.182 '@types/node': 17.0.31 '@types/ws': 7.4.7 commander: 2.20.3 @@ -20852,6 +21729,8 @@ packages: walker: 1.0.8 optionalDependencies: fsevents: 2.3.2 + transitivePeerDependencies: + - supports-color dev: true /jest-haste-map/28.1.0: @@ -21337,6 +22216,8 @@ packages: json-rpc-error: 2.0.0 promise-to-callback: 1.0.0 safe-event-emitter: 1.0.1 + transitivePeerDependencies: + - supports-color dev: false /json-rpc-engine/6.1.0: @@ -21905,7 +22786,6 @@ packages: /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true /lodash.set/4.3.2: resolution: {integrity: sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=} @@ -22328,6 +23208,49 @@ packages: transitivePeerDependencies: - supports-color + /micromatch/3.1.10_supports-color@4.5.0: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2_supports-color@4.5.0 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4_supports-color@4.5.0 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13_supports-color@4.5.0 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@4.5.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /micromatch/3.1.10_supports-color@6.1.0: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2_supports-color@6.1.0 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4_supports-color@6.1.0 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13_supports-color@6.1.0 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /micromatch/4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -22336,6 +23259,14 @@ packages: picomatch: 2.3.1 dev: true + /microtime/3.0.0: + resolution: {integrity: sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==} + engines: {node: '>= 4.0.0'} + dependencies: + node-addon-api: 1.7.2 + node-gyp-build: 3.9.0 + dev: false + /miller-rabin/4.0.1: resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} hasBin: true @@ -22798,6 +23729,45 @@ packages: transitivePeerDependencies: - supports-color + /nanomatch/1.2.13_supports-color@4.5.0: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@4.5.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /nanomatch/1.2.13_supports-color@6.1.0: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /native-abort-controller/1.0.4_abort-controller@3.0.0: resolution: {integrity: sha512-zp8yev7nxczDJMoP6pDxyD20IU0T22eX8VwN2ztDccKvSZhRaV33yP1BGwKSZfXuqWUzsXopVFjBdau9OOAwMQ==} peerDependencies: @@ -22873,6 +23843,10 @@ packages: tslib: 2.3.1 dev: true + /node-addon-api/1.7.2: + resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} + dev: false + /node-addon-api/2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} @@ -22933,6 +23907,11 @@ packages: engines: {node: '>= 6.13.0'} dev: true + /node-gyp-build/3.9.0: + resolution: {integrity: sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==} + hasBin: true + dev: false + /node-gyp-build/4.2.3: resolution: {integrity: sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==} hasBin: true @@ -23230,6 +24209,10 @@ packages: resolution: {integrity: sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==} dev: true + /oblivious-set/1.1.1: + resolution: {integrity: sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w==} + dev: false + /oboe/2.1.5: resolution: {integrity: sha1-VVQoTFQ6ImbXo48X4HOCH73jk80=} dependencies: @@ -23283,7 +24266,7 @@ packages: is-wsl: 2.2.0 dev: true - /opensea-js/1.2.7: + /opensea-js/1.2.7_webpack-cli@4.9.2: resolution: {integrity: sha512-s/ixGOIOpvqKiau3lSdUJF/osKVYh9yVZBpOslsk5bgRlbkJkBrfqCh0/2GH11EvX/wRYSaL70IYKvYew7g2pg==} dependencies: bignumber.js: 4.1.0 @@ -23295,11 +24278,14 @@ packages: lodash: 4.17.21 query-string: 6.13.5 web3: 0.20.7 - webpack: 3.12.0 - wyvern-js: github.com/ProjectOpenSea/wyvern-js/fabb7660f23f2252c141077e32193d281036299e + webpack: 3.12.0_webpack-cli@4.9.2 + wyvern-js: github.com/ProjectOpenSea/wyvern-js/fabb7660f23f2252c141077e32193d281036299e_webpack-cli@4.9.2 wyvern-schemas: github.com/ProjectOpenSea/wyvern-schemas/e1a08fcf8ce2b11a0fe9cbdc7c9f77c59fadef26 transitivePeerDependencies: - debug + - supports-color + - webpack-cli + - webpack-command dev: false /opn/5.5.0: @@ -23489,6 +24475,14 @@ packages: aggregate-error: 3.1.0 dev: true + /p-queue/6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + dev: false + /p-retry/3.0.1: resolution: {integrity: sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==} engines: {node: '>=6'} @@ -23516,7 +24510,6 @@ packages: engines: {node: '>=8'} dependencies: p-finally: 1.0.0 - dev: true /p-try/1.0.0: resolution: {integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=} @@ -23829,6 +24822,11 @@ packages: engines: {node: '>=4'} dev: true + /pngjs/3.4.0: + resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} + engines: {node: '>=4.0.0'} + dev: false + /pngjs/5.0.0: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} @@ -23850,13 +24848,15 @@ packages: '@babel/runtime': 7.17.9 dev: true - /portfinder/1.0.28: + /portfinder/1.0.28_supports-color@6.1.0: resolution: {integrity: sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==} engines: {node: '>= 0.12.0'} dependencies: async: 2.6.3 - debug: 3.2.7 + debug: 3.2.7_supports-color@6.1.0 mkdirp: 0.5.6 + transitivePeerDependencies: + - supports-color dev: false /posix-character-classes/0.1.1: @@ -23993,6 +24993,10 @@ packages: shortid: 2.2.16 dev: false + /preact/10.4.1: + resolution: {integrity: sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q==} + dev: false + /prelude-ls/1.1.2: resolution: {integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=} engines: {node: '>= 0.8.0'} @@ -24095,6 +25099,22 @@ packages: /promise-inflight/1.0.1: resolution: {integrity: sha1-mEcocL8igTL8vdhoEputEsPAKeM=} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dev: true + + /promise-inflight/1.0.1_bluebird@3.7.2: + resolution: {integrity: sha1-mEcocL8igTL8vdhoEputEsPAKeM=} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dependencies: + bluebird: 3.7.2 dev: true /promise-to-callback/1.0.0: @@ -24312,6 +25332,20 @@ packages: resolution: {integrity: sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==} dev: false + /qrcode/1.4.4: + resolution: {integrity: sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==} + engines: {node: '>=4'} + hasBin: true + dependencies: + buffer: 5.7.1 + buffer-alloc: 1.2.0 + buffer-from: 1.1.2 + dijkstrajs: 1.0.2 + isarray: 2.0.5 + pngjs: 3.4.0 + yargs: 13.3.2 + dev: false + /qrcode/1.5.0: resolution: {integrity: sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==} engines: {node: '>=10.13.0'} @@ -25062,19 +26096,43 @@ packages: resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} engines: {node: '>= 6'} dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + /readdirp/2.2.1: + resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} + engines: {node: '>=0.10'} + dependencies: + graceful-fs: 4.2.10 + micromatch: 3.1.10 + readable-stream: 2.3.7 + transitivePeerDependencies: + - supports-color + dev: true + + /readdirp/2.2.1_supports-color@4.5.0: + resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} + engines: {node: '>=0.10'} + dependencies: + graceful-fs: 4.2.10 + micromatch: 3.1.10_supports-color@4.5.0 + readable-stream: 2.3.7 + transitivePeerDependencies: + - supports-color + dev: false + optional: true - /readdirp/2.2.1: + /readdirp/2.2.1_supports-color@6.1.0: resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} engines: {node: '>=0.10'} dependencies: graceful-fs: 4.2.10 - micromatch: 3.1.10 + micromatch: 3.1.10_supports-color@6.1.0 readable-stream: 2.3.7 transitivePeerDependencies: - supports-color + dev: false /readdirp/3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -25643,8 +26701,6 @@ packages: rollup: 2.72.0 serialize-javascript: 4.0.0 terser: 5.10.0 - transitivePeerDependencies: - - acorn dev: true /rollup/2.72.0: @@ -25771,10 +26827,6 @@ packages: events: 3.3.0 dev: false - /safe-json-utils/1.0.0: - resolution: {integrity: sha512-n0hJm6BgX8wk3G+AS8MOQnfcA8dfE6ZMUfwkHUNx69YxPlU3HDaZTHXWto35Z+C4mOjK1odlT95WutkGC+0Idw==} - dev: false - /safe-regex/1.1.0: resolution: {integrity: sha1-QKNmnzsHfR6UPURinhV91IAjvy4=} dependencies: @@ -25804,6 +26856,8 @@ packages: micromatch: 3.1.10 minimist: 1.2.6 walker: 1.0.8 + transitivePeerDependencies: + - supports-color dev: true /saxes/5.0.1: @@ -25872,6 +26926,21 @@ packages: /scrypt-js/3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + /secp256k1/3.8.0: + resolution: {integrity: sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==} + engines: {node: '>=4.0.0'} + dependencies: + bindings: 1.5.0 + bip66: 1.1.5 + bn.js: 4.12.0 + create-hash: 1.2.0 + drbg.js: 1.0.1 + elliptic: 6.5.4 + nan: 2.15.0 + safe-buffer: 5.2.1 + dev: false + optional: true + /secp256k1/4.0.2: resolution: {integrity: sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==} engines: {node: '>=10.0.0'} @@ -25976,6 +27045,29 @@ packages: on-finished: 2.3.0 range-parser: 1.2.1 statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + + /send/0.17.2_supports-color@6.1.0: + resolution: {integrity: sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9_supports-color@6.1.0 + depd: 1.1.2 + destroy: 1.0.4 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 1.8.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.3.0 + range-parser: 1.2.1 + statuses: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false /serialize-javascript/4.0.0: resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} @@ -26017,6 +27109,24 @@ packages: http-errors: 1.6.3 mime-types: 2.1.35 parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /serve-index/1.9.1_supports-color@6.1.0: + resolution: {integrity: sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9_supports-color@6.1.0 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + dev: false /serve-static/1.14.2: resolution: {integrity: sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==} @@ -26026,6 +27136,20 @@ packages: escape-html: 1.0.3 parseurl: 1.3.3 send: 0.17.2 + transitivePeerDependencies: + - supports-color + + /serve-static/1.14.2_supports-color@6.1.0: + resolution: {integrity: sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.17.2_supports-color@6.1.0 + transitivePeerDependencies: + - supports-color + dev: false /servify/0.1.12: resolution: {integrity: sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==} @@ -26036,6 +27160,8 @@ packages: express: 4.17.3 request: 2.88.2 xhr: 2.6.0 + transitivePeerDependencies: + - supports-color dev: false /ses/0.15.15: @@ -26242,6 +27368,39 @@ packages: transitivePeerDependencies: - supports-color + /snapdragon/0.8.2_supports-color@4.5.0: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9_supports-color@4.5.0 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /snapdragon/0.8.2_supports-color@6.1.0: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9_supports-color@6.1.0 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: false + /socket.io-client/2.4.0: resolution: {integrity: sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==} dependencies: @@ -26258,6 +27417,21 @@ packages: to-array: 0.1.4 transitivePeerDependencies: - bufferutil + - supports-color + - utf-8-validate + dev: false + + /socket.io-client/4.5.1: + resolution: {integrity: sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + engine.io-client: 6.2.2 + socket.io-parser: 4.2.0 + transitivePeerDependencies: + - bufferutil + - supports-color - utf-8-validate dev: false @@ -26267,17 +27441,31 @@ packages: component-emitter: 1.3.0 debug: 3.1.0 isarray: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /socket.io-parser/4.2.0: + resolution: {integrity: sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color dev: false - /sockjs-client/1.6.0: + /sockjs-client/1.6.0_supports-color@6.1.0: resolution: {integrity: sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ==} engines: {node: '>=12'} dependencies: - debug: 3.2.7 + debug: 3.2.7_supports-color@6.1.0 eventsource: 1.1.0 faye-websocket: 0.11.4 inherits: 2.0.4 url-parse: 1.5.10 + transitivePeerDependencies: + - supports-color dev: false /sockjs/0.3.24: @@ -26992,6 +28180,10 @@ packages: setimmediate: 1.0.5 tar: 4.4.19 xhr-request: 1.1.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate dev: false /swc-loader/0.2.0_bv6b5h5gpy5xmvv4nr5rsqz4y4: @@ -27155,6 +28347,8 @@ packages: terser: 5.12.1 webpack: 4.46.0 webpack-sources: 1.4.3 + transitivePeerDependencies: + - bluebird dev: true /terser-webpack-plugin/5.3.1_bv6b5h5gpy5xmvv4nr5rsqz4y4: @@ -27221,8 +28415,6 @@ packages: resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==} engines: {node: '>=10'} hasBin: true - peerDependencies: - acorn: ^8.5.0 peerDependenciesMeta: acorn: optional: true @@ -27323,7 +28515,6 @@ packages: dependencies: readable-stream: 2.3.7 xtend: 4.0.2 - dev: true /through2/3.0.2: resolution: {integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==} @@ -28093,7 +29284,7 @@ packages: dependencies: source-map: 0.5.7 uglify-js: 2.8.29 - webpack: 3.12.0 + webpack: 3.12.0_webpack-cli@4.9.2 webpack-sources: 1.4.3 dev: false @@ -28293,6 +29484,13 @@ packages: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} + /unload/2.3.1: + resolution: {integrity: sha512-MUZEiDqvAN9AIDRbbBnVYVvfcR6DrjCqeU2YQMmliFZl9uaBUjTkhuDQkBiyAy8ad5bx1TXVbqZ3gg7namsWjA==} + dependencies: + '@babel/runtime': 7.17.9 + detect-node: 2.1.0 + dev: false + /unpipe/1.0.0: resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} engines: {node: '>= 0.8'} @@ -28714,6 +29912,18 @@ packages: resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==} dependencies: chokidar: 2.1.8 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /watchpack-chokidar2/2.0.1_supports-color@4.5.0: + resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==} + dependencies: + chokidar: 2.1.8_supports-color@4.5.0 + transitivePeerDependencies: + - supports-color + dev: false optional: true /watchpack/1.7.5: @@ -28724,6 +29934,21 @@ packages: optionalDependencies: chokidar: 3.5.3 watchpack-chokidar2: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /watchpack/1.7.5_supports-color@4.5.0: + resolution: {integrity: sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==} + dependencies: + graceful-fs: 4.2.10 + neo-async: 2.6.2 + optionalDependencies: + chokidar: 3.5.3 + watchpack-chokidar2: 2.0.1_supports-color@4.5.0 + transitivePeerDependencies: + - supports-color + dev: false /watchpack/2.3.1: resolution: {integrity: sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==} @@ -28757,6 +29982,10 @@ packages: '@types/node': 17.0.31 got: 9.6.0 swarm-js: 0.1.40 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate dev: false /web3-core-helpers/1.7.3: @@ -28837,6 +30066,8 @@ packages: web3-core-helpers: 1.7.3 web3-core-method: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color dev: false /web3-eth-contract/1.7.3: @@ -28851,6 +30082,8 @@ packages: web3-core-subscriptions: 1.7.3 web3-eth-abi: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color /web3-eth-ens/1.7.3: resolution: {integrity: sha512-q7+hFGHIc0mBI3LwgRVcLCQmp6GItsWgUtEZ5bjwdjOnJdbjYddm7PO9RDcTDQ6LIr7hqYaY4WTRnDHZ6BEt5Q==} @@ -28864,6 +30097,8 @@ packages: web3-eth-abi: 1.7.3 web3-eth-contract: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color dev: false /web3-eth-iban/1.7.3: @@ -28883,6 +30118,8 @@ packages: web3-core-method: 1.7.3 web3-net: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color dev: false /web3-eth/1.7.3: @@ -28901,6 +30138,8 @@ packages: web3-eth-personal: 1.7.3 web3-net: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color dev: false /web3-net/1.7.3: @@ -28910,6 +30149,8 @@ packages: web3-core: 1.7.3 web3-core-method: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - supports-color dev: false /web3-provider-engine/13.8.0: @@ -28934,6 +30175,8 @@ packages: tape: 4.15.1 xhr: 2.6.0 xtend: 4.0.2 + transitivePeerDependencies: + - supports-color dev: false /web3-providers-http/1.7.3: @@ -28968,6 +30211,8 @@ packages: web3-core-method: 1.7.3 web3-core-subscriptions: 1.7.3 web3-net: 1.7.3 + transitivePeerDependencies: + - supports-color dev: false /web3-utils/1.7.3: @@ -29003,6 +30248,10 @@ packages: web3-net: 1.7.3 web3-shh: 1.7.3 web3-utils: 1.7.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate dev: false /webcrypto-core/1.4.0: @@ -29149,14 +30398,14 @@ packages: dependencies: ansi-html-community: 0.0.8 bonjour: 3.5.0 - chokidar: 2.1.8 - compression: 1.7.4 + chokidar: 2.1.8_supports-color@6.1.0 + compression: 1.7.4_supports-color@6.1.0 connect-history-api-fallback: 1.6.0 debug: 4.3.4_supports-color@6.1.0 del: 4.1.1 - express: 4.17.3 + express: 4.17.3_supports-color@6.1.0 html-entities: 1.4.0 - http-proxy-middleware: 0.19.1_debug@4.3.4 + http-proxy-middleware: 0.19.1_tmpgdztspuwvsxzgjkhoqk7duq import-local: 2.0.0 internal-ip: 4.3.0 ip: 1.1.5 @@ -29165,13 +30414,13 @@ packages: loglevel: 1.8.0 opn: 5.5.0 p-retry: 3.0.1 - portfinder: 1.0.28 + portfinder: 1.0.28_supports-color@6.1.0 schema-utils: 1.0.0 selfsigned: 1.10.14 semver: 6.3.0 - serve-index: 1.9.1 + serve-index: 1.9.1_supports-color@6.1.0 sockjs: 0.3.24 - sockjs-client: 1.6.0 + sockjs-client: 1.6.0_supports-color@6.1.0 spdy: 4.0.2_supports-color@6.1.0 strip-ansi: 3.0.1 supports-color: 6.1.0 @@ -29180,6 +30429,9 @@ packages: webpack-log: 2.0.0 ws: 6.2.2 yargs: 13.3.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate dev: false /webpack-dev-server/4.9.0_q7qo2wgeiyigo3znjsjh7f36ue: @@ -29287,16 +30539,26 @@ packages: resolution: {integrity: sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==} dependencies: debug: 3.2.7 + transitivePeerDependencies: + - supports-color dev: true /webpack-virtual-modules/0.4.3: resolution: {integrity: sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==} dev: true - /webpack/3.12.0: + /webpack/3.12.0_webpack-cli@4.9.2: resolution: {integrity: sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==} engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} hasBin: true + peerDependencies: + webpack-cli: '*' + webpack-command: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + webpack-command: + optional: true dependencies: acorn: 5.7.4 acorn-dynamic-import: 2.0.2 @@ -29317,7 +30579,8 @@ packages: supports-color: 4.5.0 tapable: 0.2.9 uglifyjs-webpack-plugin: 0.4.6_webpack@3.12.0 - watchpack: 1.7.5 + watchpack: 1.7.5_supports-color@4.5.0 + webpack-cli: 4.9.2_4evrg3m2qioscfus6hwjof6pci webpack-sources: 1.4.3 yargs: 8.0.2 dev: false @@ -29358,6 +30621,8 @@ packages: terser-webpack-plugin: 1.4.5_webpack@4.46.0 watchpack: 1.7.5 webpack-sources: 1.4.3 + transitivePeerDependencies: + - supports-color dev: true /webpack/5.72.0: @@ -29607,16 +30872,6 @@ packages: resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==} dev: true - /window-getters/1.0.0: - resolution: {integrity: sha512-xyvEFq3x+7dCA7NFhqOmTMk0fPmmAzCUYL2svkw2LGBaXXQLRP0lFnfXHzysri9WZNMkzp/FD1u0w2Qc7Co+JA==} - dev: false - - /window-metadata/1.0.0: - resolution: {integrity: sha512-eYoXsZ9X4J+6xZgbHhNAatSR5bCtT409q8B+2Ol9ySx7qsdtgVZcNfox4qszFmKlGsFtT2b1Tcmcy69bRMObcg==} - dependencies: - window-getters: 1.0.0 - dev: false - /window-size/0.1.0: resolution: {integrity: sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=} engines: {node: '>= 0.8.0'} @@ -29706,6 +30961,14 @@ packages: /ws/3.3.3: resolution: {integrity: sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true dependencies: async-limiter: 1.0.1 safe-buffer: 5.1.2 @@ -29714,6 +30977,14 @@ packages: /ws/6.2.2: resolution: {integrity: sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true dependencies: async-limiter: 1.0.1 dev: false @@ -29731,8 +31002,8 @@ packages: optional: true dev: false - /ws/7.3.0: - resolution: {integrity: sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==} + /ws/7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -29744,8 +31015,8 @@ packages: optional: true dev: false - /ws/7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + /ws/7.5.3: + resolution: {integrity: sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -29785,6 +31056,19 @@ packages: utf-8-validate: 5.0.9 dev: false + /ws/8.2.3: + resolution: {integrity: sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /ws/8.5.0: resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} @@ -29864,6 +31148,11 @@ packages: engines: {node: '>=0.4.0'} dev: false + /xmlhttprequest-ssl/2.0.0: + resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} + engines: {node: '>=0.4.0'} + dev: false + /xmlhttprequest/1.8.0: resolution: {integrity: sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=} engines: {node: '>=0.4.0'} @@ -30191,8 +31480,9 @@ packages: web3: 0.20.7 dev: false - github.com/ProjectOpenSea/wyvern-js/fabb7660f23f2252c141077e32193d281036299e: + github.com/ProjectOpenSea/wyvern-js/fabb7660f23f2252c141077e32193d281036299e_webpack-cli@4.9.2: resolution: {tarball: https://codeload.github.com/ProjectOpenSea/wyvern-js/tar.gz/fabb7660f23f2252c141077e32193d281036299e} + id: github.com/ProjectOpenSea/wyvern-js/fabb7660f23f2252c141077e32193d281036299e name: wyvern-js version: 3.2.0 dependencies: @@ -30220,7 +31510,11 @@ packages: typescript: 2.9.2 typescript-eslint-parser: 16.0.1_typescript@2.9.2 web3: 0.20.7 - webpack: 3.12.0 + webpack: 3.12.0_webpack-cli@4.9.2 + transitivePeerDependencies: + - supports-color + - webpack-cli + - webpack-command dev: false github.com/ProjectOpenSea/wyvern-schemas/e1a08fcf8ce2b11a0fe9cbdc7c9f77c59fadef26: @@ -30236,6 +31530,7 @@ packages: wyvern-js: github.com/ProjectOpenSea/wyvern-js/6f85f1b42f0962d2cc8e97b7e7f680865e3f26c1 transitivePeerDependencies: - debug + - supports-color dev: false github.com/ProjectWyvern/ethereumjs-abi/3d2d89641a6ad5984929b6ca4b646452ec74f73d: