diff --git a/.i18n-codegen.json b/.i18n-codegen.json index cb999243cc8d..7349a032131d 100644 --- a/.i18n-codegen.json +++ b/.i18n-codegen.json @@ -182,6 +182,18 @@ "sourceMap": "inline" } }, + { + "input": "./packages/plugins/ENS/src/locales/en-US.json", + "output": "./packages/plugins/ENS/src/locales/i18n_generated", + "parser": "i18next", + "generator": { + "type": "i18next/react-hooks", + "hooks": "useI18N", + "namespace": "io.mask.ens-plugin", + "trans": "Translate", + "sourceMap": "inline" + } + }, { "input": "./packages/plugins/GoPlusSecurity/src/locales/en-US.json", "output": "./packages/plugins/GoPlusSecurity/src/locales/i18n_generated", diff --git a/docs/plugin-development-quickstart.md b/docs/plugin-development-quickstart.md index f547d25093ec..b2e9c1f82dab 100644 --- a/docs/plugin-development-quickstart.md +++ b/docs/plugin-development-quickstart.md @@ -4,28 +4,112 @@ author: Randolph # Quick start for Plugin Development -## 1. Start a plugin file +## 1. Introduction -input following code to start a plugin file +This is an example of how to develop plugin according to tools provided by Mask. And our task is to obtain ENS from user data, and display details about the ENS domain in timeline and profile of twitter. Besides, user can search specific ENS details in application board. + +## 2. Start a plugin file + +Create a plugin folder by entering following command > npx gulp new-pkg -...(a brief introduction about the files generated) +After entering related information about the plugin, a plugin folder will be created in `packages/plugins`. This folder contains lots of files, and core files are `SNSAdaptor` and `Worker`. The former contains all the code related to front-end interaction, the latter plays a database-like role. +Since we want to add a application into maskbook, we need to add related config to register: + +`packages/mask/src/plugin-infra/register.js` + +```JavaScript + import '@masknet/plugin-ENS' +``` + +## 3. How to inject UI + +We will inject our UI in three places of twitter to provide different services. And `Plugin.SNSAdaptor.Definition` in `SNSAdaptor` is where we inject our UI mainly. + +### 3.1 Add UI in application board + +Add following config: + +```JavaScript + ApplicationEntries: [ + { + RenderEntryComponent({ disabled }) { + return ( + + CrossIsolationMessages.events.requestComposition.sendToLocal({ + reason: 'timeline', + open: true, + options: { + startupPlugin: base.ID, + }, + }) + } + /> + ) + }, + defaultSortingPriority: 1, + }, + ], +``` + +### 3.2 Add UI in Timeline + +It is normal that we inject specific UI according to content in timeline. Now we want to parse the URLs in the content to generate our UI, Mask provide `PostInspector` entry: + +```JavaScript + PostInspector: function Component(): JSX.Element | null { + const links = usePostInfoDetails.mentionedLinks() // links we find in timeline content + const link = links.find(isENS) // find ENS url + if (!link) return null + return // render UI if ENS URL is found + }, +``` + +### 3.3 Add UI as a tab in user profile + +We have injected `web3` tab in user profile, so we add a tab called `ENS` under it. Same as before, add following config in `Plugin.SNSAdaptor.Definition`: + +```JavaScript + ProfileTabs: [ + { + ID: `${PLUGIN_ID}_tabContent`, // PLUGIN_ID is generated when we use codegen command + label: 'ENS', + priority: 10, + UI: { + TabContent: ENSCard, // ENSCard is the UI we want to display + }, + }, + ], +``` + +Now we have created entries to inject UI, the rest is to add style and interaction logic like writing a web page in `ENSCard` and `ENSDialog` to meet our needs. -## 2. How to inject ui +## 4. How to get data from blockchain -1. change definitions in SNSAdaptor to add entry -2. what is metadata and how to decode and encode metadata - if we want to inject ui in a post, we need metadata that contains related information -3. write ui by our component +We have successfully injected entries in twitter, now we can focus on the UI and interaction. Additionally, we want to see ENS details, so we need to acquire information on blockchain. +We can grab user's ENS in their profile and ENS url in timeline, and we want to inject a card to show details like owner and expiration date of this ENS domain. For acquiring information from blockchain, we need smart contract address of ENS which can be found in ENS website. The smart contract address we need is `0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e`, so we need to call related function of this smart contract. +Copy ABI of this smart contract from `etherscan` and make it as a `json` file. Mask provide tools to use it: -## 3. How to interact with worker +```JavaScript +import { useContract } from '@masknet/web3-shared-evm' +import ENS_REGISTRY_ABI from '@masknet/web3-contracts/abis/ens_registry.json' +import { hash } from 'eth-ens-namehash' -1. how to write Service to manage data -2. a brief introduction about backend page +const contract = useContract('0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', ENS_REGISTRY_ABI) -## 4. How to interact with blockchain +const handleSearch = useCallback(async () => { + const nameHash = hash(ensName) // name string should be hashed to be a node + const owner = await contract?.methods?.owner(nameHash)?.call({ from: account }) // get owner + const resolver = await contract?.methods?.resolver(nameHash)?.call({ from: account }) // get resolver + const ttl = await contract?.methods?.ttl(nameHash)?.call({ from: account }) // get ttl + console.log({ owner, resolver, ttl, nameHash }) + }, [ensName]) +``` -1. how to send a transaction -2. how to get data stored in the blockchain -3. a brief introduction about transaction process +Be careful about contract address and ABI. If you use mismatched information, the function call will fail +The above is an example to get some basic information about ENS. If you need more, you can refer to its ABI, calling other methods to read the data from blockchain. diff --git a/packages/mask/.webpack/config.ts b/packages/mask/.webpack/config.ts index 8fe5fbdd2ac9..dea904dc5078 100644 --- a/packages/mask/.webpack/config.ts +++ b/packages/mask/.webpack/config.ts @@ -96,6 +96,7 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration { '@masknet/encryption': join(__dirname, '../../encryption/src'), '@masknet/typed-message/dom$': require.resolve('../../typed-message/dom/index.ts'), '@masknet/typed-message$': require.resolve('../../typed-message/base/index.ts'), + '@masknet/plugin-ens': join(__dirname, '../../plugins/ENS/src'), // @masknet/scripts: insert-here '@uniswap/v3-sdk': require.resolve('@uniswap/v3-sdk/dist/index.js'), } diff --git a/packages/mask/package.json b/packages/mask/package.json index b7f508b55166..fb03ddac2e2d 100644 --- a/packages/mask/package.json +++ b/packages/mask/package.json @@ -28,6 +28,7 @@ "@masknet/plugin-infra": "workspace:*", "@masknet/plugin-rss3": "workspace:*", "@masknet/plugin-solana": "workspace:*", + "@masknet/plugin-ens": "workspace:*", "@masknet/plugin-wallet": "workspace:*", "@masknet/plugin-go-plus-security": "workspace:*", "@masknet/public-api": "workspace:*", diff --git a/packages/mask/src/plugin-infra/register.js b/packages/mask/src/plugin-infra/register.js index 5cbbf531805e..37c9f1a7a0aa 100644 --- a/packages/mask/src/plugin-infra/register.js +++ b/packages/mask/src/plugin-infra/register.js @@ -37,3 +37,4 @@ import '../plugins/Pets' import '../plugins/CryptoartAI' import '../plugins/FindTruman' import '../plugins/ArtBlocks' +import '@masknet/plugin-ens' diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index e0bc35cd42ec..c6f40a3ea8ef 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -688,6 +688,7 @@ export enum PluginId { UnlockProtocol = 'com.maskbook.unlockprotocol', FileService = 'com.maskbook.fileservice', CyberConnect = 'me.cyberconnect.app', + ENS = 'io.mask.ens-plugin', GoPlusSecurity = 'io.gopluslabs.security', // @masknet/scripts: insert-here } diff --git a/packages/plugins/ENS/README.md b/packages/plugins/ENS/README.md new file mode 100644 index 000000000000..c67dc19c5f8b --- /dev/null +++ b/packages/plugins/ENS/README.md @@ -0,0 +1,7 @@ +# Example plugin + +## TODOs + +## Referenced resources + +## Known issues / Caveats diff --git a/packages/plugins/ENS/package.json b/packages/plugins/ENS/package.json new file mode 100644 index 000000000000..928dc77dee17 --- /dev/null +++ b/packages/plugins/ENS/package.json @@ -0,0 +1,16 @@ +{ + "name": "@masknet/plugin-ens", + "private": true, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "dependencies": { + "@masknet/plugin-infra": "workspace:*", + "@masknet/shared": "workspace:*", + "@masknet/shared-base": "workspace:*", + "@masknet/web3-shared-evm":"workspace:*", + "@masknet/web3-contracts":"workspace:*", + "react-use": "^17.3.2", + "eth-ens-namehash":"2.0.8", + "web3-utils":"1.5.3" + } +} diff --git a/packages/plugins/ENS/src/Dashboard/index.tsx b/packages/plugins/ENS/src/Dashboard/index.tsx new file mode 100644 index 000000000000..3052bb2f8ad3 --- /dev/null +++ b/packages/plugins/ENS/src/Dashboard/index.tsx @@ -0,0 +1,9 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { base } from '../base' + +const dashboard: Plugin.Dashboard.Definition = { + ...base, + init(signal, context) {}, +} + +export default dashboard diff --git a/packages/plugins/ENS/src/SNSAdaptor/ENSCard.tsx b/packages/plugins/ENS/src/SNSAdaptor/ENSCard.tsx new file mode 100644 index 000000000000..fe14d56931b4 --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/ENSCard.tsx @@ -0,0 +1,112 @@ +import { makeStyles } from '@masknet/theme' +import { Box } from '@mui/system' +import { useAsyncRetry } from 'react-use' +import { Card, CardHeader, Typography, CardContent } from '@mui/material' +import { useI18N } from '../locales/index' +const { hash } = require('eth-ens-namehash') +import { useAccount } from '@masknet/web3-shared-evm' +import { useENSContract } from './hook/useENSContract' +import ENSDetail from './ENSDetail' +import { getEthereumName } from './hook/getEthereumName' + +const useStyles = makeStyles()((theme) => ({ + root: { + '--contentHeight': '200px', + '--tabHeight': '35px', + + width: '100%', + border: `solid 1px ${theme.palette.divider}`, + padding: 0, + }, + content: { + width: '100%', + minHeight: 'var(--contentHeight)', + display: 'flex', + flexDirection: 'column', + padding: '0 !important', + }, + body: { + flex: 1, + maxHeight: 'calc(var(--contentHeight) - var(--tabHeight))', + overflow: 'auto', + scrollbarWidth: 'none', + '&::-webkit-scrollbar': { + display: 'none', + }, + }, + tabs: { + height: 'var(--tabHeight)', + width: '100%', + minHeight: 'unset', + borderTop: `solid 1px ${theme.palette.divider}`, + borderBottom: `solid 1px ${theme.palette.divider}`, + }, + tab: { + height: 'var(--tabHeight)', + minHeight: 'unset', + minWidth: 'unset', + }, + subtitle: { + fontSize: 12, + marginRight: theme.spacing(0.5), + }, +})) +interface identity { + nickname?: string + userId?: string + bio?: string +} +interface ENSCardProps { + url?: string + identity?: identity +} + +const ENSCard: React.FC = ({ url, identity }) => { + const { classes } = useStyles() + const t = useI18N() + const contract = useENSContract() + const account = useAccount() + + const { value: ENS_Info } = useAsyncRetry(async () => { + const ENS_name = + url?.split('/')?.find((str) => str?.includes('.eth')) ?? + getEthereumName?.(identity?.userId ?? '', identity?.nickname ?? '', identity?.bio ?? '') + const nameHash = hash(ENS_name) + const owner = await contract?.methods?.owner(nameHash)?.call({ from: account }) + const resolver = await contract?.methods?.resolver(nameHash)?.call({ from: account }) + const ttl = await contract?.methods?.ttl(nameHash)?.call({ from: account }) + return { + owner, + resolver, + ttl, + ENS_name, + } + }, [contract, account]) + return ( + + + + + {t['Ethereum Name Service']} + + + #{ENS_Info?.ENS_name} + + + + } + /> + + + + + ) +} + +export default ENSCard diff --git a/packages/plugins/ENS/src/SNSAdaptor/ENSDetail.tsx b/packages/plugins/ENS/src/SNSAdaptor/ENSDetail.tsx new file mode 100644 index 000000000000..4163b21f6adb --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/ENSDetail.tsx @@ -0,0 +1,79 @@ +import { makeStyles } from '@masknet/theme' +import { Box } from '@mui/system' +import { ChangeEvent, useCallback, useState } from 'react' +import { Typography } from '@mui/material' +import { useI18N } from '../locales/index' +import type { ENS_Info_type } from './types' + +const useStyles = makeStyles()((theme) => ({ + wrapper: { + width: 600, + display: 'flex', + paddingLeft: theme.spacing(2), + paddingTop: theme.spacing(1), + }, + input: { + flex: 1, + padding: theme.spacing(0.5), + }, + button: { + padding: theme.spacing(1, 2), + marginLeft: theme.spacing(1), + marginTop: theme.spacing(1), + }, + skeleton: { + borderRadius: 8, + margin: theme.spacing(1), + marginTop: 0, + backgroundColor: theme.palette.background.default, + height: '48px', + }, +})) +interface ENSDetailProps { + ENS_Info?: ENS_Info_type +} + +const ENSDetail: React.FC = ({ ENS_Info }) => { + const { classes } = useStyles() + const t = useI18N() + const [ensName, setEnsName] = useState('') + + const handleEnsNameChange = useCallback((ev: ChangeEvent) => { + const ens_ = ev.currentTarget.value + setEnsName(ens_) + }, []) + + const handleSearch = useCallback(() => { + console.log(ensName) + }, [ensName]) + return ( + <> + + {t.parent()}: + + eth + + + + {t.owner()}: + + {ENS_Info?.owner} + + + + {t.resolver()}: + + {ENS_Info?.resolver} + + + + {t.ttl()}: + + {ENS_Info?.ttl === '0' ? 'not found' : ENS_Info?.ttl} + + + + ) +} + +export default ENSDetail diff --git a/packages/plugins/ENS/src/SNSAdaptor/ENSDialog.tsx b/packages/plugins/ENS/src/SNSAdaptor/ENSDialog.tsx new file mode 100644 index 000000000000..0449d97febd9 --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/ENSDialog.tsx @@ -0,0 +1,104 @@ +import { MaskDialog } from '../../../../theme/src/Components' +import { makeStyles } from '@masknet/theme' +import { Box } from '@mui/system' +import { ChangeEvent, useCallback, useState } from 'react' +import { TextField, Button } from '@mui/material' +import { useAccount } from '@masknet/web3-shared-evm' +const { hash } = require('eth-ens-namehash') +import { useI18N } from '../locales/index' +import ENSDetail from './ENSDetail' +import type { ENS_Info_type } from './types' +import { useENSContract } from './hook/useENSContract' + +const useStyles = makeStyles()((theme) => ({ + wrapper: { + width: 600, + overflow: 'scroll', + display: 'flex', + padding: theme.spacing(1), + }, + input: { + flex: 1, + padding: theme.spacing(0.5), + }, + button: { + padding: theme.spacing(1, 2), + marginLeft: theme.spacing(1), + marginTop: theme.spacing(1), + }, + skeleton: { + borderRadius: 8, + margin: theme.spacing(1), + marginTop: 0, + backgroundColor: theme.palette.background.default, + height: '48px', + }, +})) +interface TestDialogProps { + open: boolean + onClose: () => void +} + +const TestDialog: React.FC = (props) => { + const { classes } = useStyles() + const t = useI18N() + const [ensName, setEnsName] = useState('') + const [ENSInfo, setENSInfo] = useState() + const account = useAccount() + + const contract = useENSContract() + + const handleEnsNameChange = useCallback((ev: ChangeEvent) => { + const ens_ = ev.currentTarget.value + setEnsName(ens_) + }, []) + + const handleSearch = useCallback(async () => { + const nameHash = hash(ensName) + const owner = await contract?.methods?.owner(nameHash)?.call({ from: account }) + const resolver = await contract?.methods?.resolver(nameHash)?.call({ from: account }) + const ttl = await contract?.methods?.ttl(nameHash)?.call({ from: account }) + setENSInfo({ + owner, + ttl, + resolver, + }) + }, [ensName]) + + return ( + + + +
+ +
+
+ +
+ ) +} + +export default TestDialog diff --git a/packages/plugins/ENS/src/SNSAdaptor/assets/ens.png b/packages/plugins/ENS/src/SNSAdaptor/assets/ens.png new file mode 100644 index 000000000000..5b60b5fe0dc4 Binary files /dev/null and b/packages/plugins/ENS/src/SNSAdaptor/assets/ens.png differ diff --git a/packages/plugins/ENS/src/SNSAdaptor/hook/getEthereumName.ts b/packages/plugins/ENS/src/SNSAdaptor/hook/getEthereumName.ts new file mode 100644 index 000000000000..fc50cac6220b --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/hook/getEthereumName.ts @@ -0,0 +1,6 @@ +export function getEthereumName(twitterId: string, nickname: string, bio: string) { + const ENS_RE = /\S{1,256}\.(eth|kred|xyz|luxe)\b/ + const [matched] = nickname.match(ENS_RE) ?? bio.match(ENS_RE) ?? [] + if (matched) return matched + return twitterId && !twitterId.endsWith('.eth') ? `${twitterId}.eth` : twitterId +} diff --git a/packages/plugins/ENS/src/SNSAdaptor/hook/useENSContract.ts b/packages/plugins/ENS/src/SNSAdaptor/hook/useENSContract.ts new file mode 100644 index 000000000000..74282456efdd --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/hook/useENSContract.ts @@ -0,0 +1,7 @@ +import { useContract } from '@masknet/web3-shared-evm' +import ENS_Registry_ABI from '@masknet/web3-contracts/abis/ENSRegistry.json' +import type { AbiItem } from 'web3-utils' + +export function useENSContract() { + return useContract('0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', ENS_Registry_ABI as AbiItem[]) +} diff --git a/packages/plugins/ENS/src/SNSAdaptor/index.tsx b/packages/plugins/ENS/src/SNSAdaptor/index.tsx new file mode 100644 index 000000000000..929764345d09 --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/index.tsx @@ -0,0 +1,68 @@ +import { Plugin, usePostInfoDetails } from '@masknet/plugin-infra' +import { ApplicationEntry } from '@masknet/shared' +import { CrossIsolationMessages } from '@masknet/shared-base' +import { base } from '../base' +import ENSDialog from './ENSDialog' +import ENSCard from './ENSCard' +import { PLUGIN_ID } from '../constants' + +const isENS = (x: string): boolean => /^https:\/\/app.ens.domains\/name\/[\S\s]{3,}.eth\/details$/.test(x) + +const sns: Plugin.SNSAdaptor.Definition = { + ...base, + init(signal, context) {}, + CompositionDialogEntry: { + label: 'ENS', + dialog: ENSDialog, + }, + PostInspector: function Component(): JSX.Element | null { + const links = usePostInfoDetails.mentionedLinks() + const link = links.find(isENS) + if (!link) return null + return + }, + ProfileTabs: [ + { + ID: `${PLUGIN_ID}_tabContent`, + label: 'ENS', + priority: 10, + UI: { + TabContent: (identity) => ( + + ), + }, + }, + ], + ApplicationEntries: [ + { + RenderEntryComponent({ disabled }) { + return ( + + CrossIsolationMessages.events.requestComposition.sendToLocal({ + reason: 'timeline', + open: true, + options: { + startupPlugin: base.ID, + }, + }) + } + /> + ) + }, + defaultSortingPriority: 1, + }, + ], +} + +export default sns diff --git a/packages/plugins/ENS/src/SNSAdaptor/types.ts b/packages/plugins/ENS/src/SNSAdaptor/types.ts new file mode 100644 index 000000000000..b14b936cf4ac --- /dev/null +++ b/packages/plugins/ENS/src/SNSAdaptor/types.ts @@ -0,0 +1,6 @@ +export interface ENS_Info_type { + owner?: string + ttl?: string + resolver?: string + ENS_name?: string +} diff --git a/packages/plugins/ENS/src/Worker/index.ts b/packages/plugins/ENS/src/Worker/index.ts new file mode 100644 index 000000000000..6c436f1cb4fb --- /dev/null +++ b/packages/plugins/ENS/src/Worker/index.ts @@ -0,0 +1,9 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { base } from '../base' + +const worker: Plugin.Worker.Definition = { + ...base, + init(signal, context) {}, +} + +export default worker diff --git a/packages/plugins/ENS/src/base.ts b/packages/plugins/ENS/src/base.ts new file mode 100644 index 000000000000..b88adee59a7f --- /dev/null +++ b/packages/plugins/ENS/src/base.ts @@ -0,0 +1,18 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { PLUGIN_DESCRIPTION, PLUGIN_ID, PLUGIN_NAME } from './constants' +import { languages } from './locales/languages' + +export const base: Plugin.Shared.Definition = { + ID: PLUGIN_ID, + icon: '\u{1F9EA}', + name: { fallback: PLUGIN_NAME }, + description: { fallback: PLUGIN_DESCRIPTION }, + publisher: { name: { fallback: '' }, link: '' }, + enableRequirement: { + architecture: { app: false, web: true }, + networks: { type: 'opt-out', networks: {} }, + target: 'beta', + }, + experimentalMark: true, + i18n: languages, +} diff --git a/packages/plugins/ENS/src/constants.ts b/packages/plugins/ENS/src/constants.ts new file mode 100644 index 000000000000..3d6ffbf1eb38 --- /dev/null +++ b/packages/plugins/ENS/src/constants.ts @@ -0,0 +1,6 @@ +import { PluginId } from '@masknet/plugin-infra' + +export const PLUGIN_ID = PluginId.ENS +export const PLUGIN_DESCRIPTION = 'An example plugin of Mask Network.' +export const PLUGIN_NAME = 'ENS' +export const mainnetNode = 'https://mainnet.infura.io/v3/e5cdff80adef46bd989817301ecd9c7e' diff --git a/packages/plugins/ENS/src/env.d.ts b/packages/plugins/ENS/src/env.d.ts new file mode 100644 index 000000000000..868322d5ff30 --- /dev/null +++ b/packages/plugins/ENS/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/plugins/ENS/src/index.ts b/packages/plugins/ENS/src/index.ts new file mode 100644 index 000000000000..ec9b1a34e7af --- /dev/null +++ b/packages/plugins/ENS/src/index.ts @@ -0,0 +1,23 @@ +import { registerPlugin } from '@masknet/plugin-infra' +import { base } from './base' + +export * from './constants' + +registerPlugin({ + ...base, + SNSAdaptor: { + load: () => import('./SNSAdaptor'), + hotModuleReload: (hot) => + import.meta.webpackHot && import.meta.webpackHot.accept('./SNSAdaptor', () => hot(import('./SNSAdaptor'))), + }, + Dashboard: { + load: () => import('./Dashboard'), + hotModuleReload: (hot) => + import.meta.webpackHot && import.meta.webpackHot.accept('./Dashboard', () => hot(import('./Dashboard'))), + }, + Worker: { + load: () => import('./Worker'), + hotModuleReload: (hot) => + import.meta.webpackHot && import.meta.webpackHot.accept('./Worker', () => hot(import('./Worker'))), + }, +}) diff --git a/packages/plugins/ENS/src/locales/en-US.json b/packages/plugins/ENS/src/locales/en-US.json new file mode 100644 index 000000000000..dae216210161 --- /dev/null +++ b/packages/plugins/ENS/src/locales/en-US.json @@ -0,0 +1,15 @@ +{ + "name": "Example Plugin", + "__entry__": "🤔 Example", + "ens": "Etherenum Name Service", + "search": "search", + "parent": "parent", + "registrant": "REGISTRANT", + "controller": "CONTROLLER", + "expiration_date": "EXPIRATION DATE", + "buy": "buy", + "Ethereum Name Service": "Ethereum Name Service", + "resolver": "resolver", + "owner": "owner", + "ttl": "time-to-live" +} diff --git a/packages/plugins/ENS/src/locales/index.ts b/packages/plugins/ENS/src/locales/index.ts new file mode 100644 index 000000000000..d6ead60252e4 --- /dev/null +++ b/packages/plugins/ENS/src/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/plugins/ENS/src/locales/ja-JP.json b/packages/plugins/ENS/src/locales/ja-JP.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/ENS/src/locales/ja-JP.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/ENS/src/locales/ko-KR.json b/packages/plugins/ENS/src/locales/ko-KR.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/ENS/src/locales/ko-KR.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/ENS/src/locales/languages.ts b/packages/plugins/ENS/src/locales/languages.ts new file mode 100644 index 000000000000..d3d7772e44a4 --- /dev/null +++ b/packages/plugins/ENS/src/locales/languages.ts @@ -0,0 +1,34 @@ +// 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' +import ja_JP from './ja-JP.json' +import ko_KR from './ko-KR.json' +import qya_AA from './qya-AA.json' +import zh_CN from './zh-CN.json' +import zh_TW from './zh-TW.json' +export const languages = { + en: en_US, + ja: ja_JP, + ko: ko_KR, + qy: qya_AA, + 'zh-CN': zh_CN, + zh: zh_TW, +} +// @ts-ignore +if (import.meta.webpackHot) { + // @ts-ignore + import.meta.webpackHot.accept( + ['./en-US.json', './ja-JP.json', './ko-KR.json', './qya-AA.json', './zh-CN.json', './zh-TW.json'], + () => + globalThis.dispatchEvent?.( + new CustomEvent('MASK_I18N_HMR', { + detail: [ + 'io.mask.ens-plugin', + { en: en_US, ja: ja_JP, ko: ko_KR, qy: qya_AA, 'zh-CN': zh_CN, zh: zh_TW }, + ], + }), + ), + ) +} diff --git a/packages/plugins/ENS/src/locales/qya-AA.json b/packages/plugins/ENS/src/locales/qya-AA.json new file mode 100644 index 000000000000..439535f8dd96 --- /dev/null +++ b/packages/plugins/ENS/src/locales/qya-AA.json @@ -0,0 +1,4 @@ +{ + "name": "crwdns13280:0crwdne13280:0", + "__entry__": "crwdns13282:0crwdne13282:0" +} diff --git a/packages/plugins/ENS/src/locales/zh-CN.json b/packages/plugins/ENS/src/locales/zh-CN.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/ENS/src/locales/zh-CN.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/ENS/src/locales/zh-TW.json b/packages/plugins/ENS/src/locales/zh-TW.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/packages/plugins/ENS/src/locales/zh-TW.json @@ -0,0 +1 @@ +{} diff --git a/packages/plugins/ENS/tsconfig.json b/packages/plugins/ENS/tsconfig.json new file mode 100644 index 000000000000..c8c34c61f89b --- /dev/null +++ b/packages/plugins/ENS/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "tsBuildInfoFile": "dist/.tsbuildinfo" + }, + "include": ["src", "src/**/*.json"], + "references": [{ "path": "../../plugin-infra" }, { "path": "../../shared" }] +} diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json index 855d124c6fa3..5e21ac1bf745 100644 --- a/packages/plugins/tsconfig.json +++ b/packages/plugins/tsconfig.json @@ -9,6 +9,7 @@ { "path": "./FileService/" }, { "path": "./RSS3/" }, { "path": "./DAO/" }, - { "path": "./CyberConnect/" } + { "path": "./CyberConnect/" }, + { "path": "./ENS/" } ] } diff --git a/packages/web3-contracts/abis/Controllar.json b/packages/web3-contracts/abis/Controllar.json new file mode 100644 index 000000000000..66ba81fc6166 --- /dev/null +++ b/packages/web3-contracts/abis/Controllar.json @@ -0,0 +1,403 @@ +[ + { + "inputs": [{ "internalType": "contract ENS", "name": "_ens", "type": "address" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": true, "internalType": "uint256", "name": "contentType", "type": "uint256" } + ], + "name": "ABIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "address", "name": "a", "type": "address" } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "uint256", "name": "coinType", "type": "uint256" }, + { "indexed": false, "internalType": "bytes", "name": "newAddress", "type": "bytes" } + ], + "name": "AddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "target", "type": "address" }, + { "indexed": false, "internalType": "bool", "name": "isAuthorised", "type": "bool" } + ], + "name": "AuthorisationChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes", "name": "hash", "type": "bytes" } + ], + "name": "ContenthashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes", "name": "name", "type": "bytes" }, + { "indexed": false, "internalType": "uint16", "name": "resource", "type": "uint16" }, + { "indexed": false, "internalType": "bytes", "name": "record", "type": "bytes" } + ], + "name": "DNSRecordChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes", "name": "name", "type": "bytes" }, + { "indexed": false, "internalType": "uint16", "name": "resource", "type": "uint16" } + ], + "name": "DNSRecordDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "DNSZoneCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": true, "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }, + { "indexed": false, "internalType": "address", "name": "implementer", "type": "address" } + ], + "name": "InterfaceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "string", "name": "name", "type": "string" } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes32", "name": "x", "type": "bytes32" }, + { "indexed": false, "internalType": "bytes32", "name": "y", "type": "bytes32" } + ], + "name": "PubkeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": true, "internalType": "string", "name": "indexedKey", "type": "string" }, + { "indexed": false, "internalType": "string", "name": "key", "type": "string" } + ], + "name": "TextChanged", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "contentTypes", "type": "uint256" } + ], + "name": "ABI", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "bytes", "name": "", "type": "bytes" } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "addr", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "coinType", "type": "uint256" } + ], + "name": "addr", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "", "type": "bytes32" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "authorisations", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "clearDNSZone", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "contenthash", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes32", "name": "name", "type": "bytes32" }, + { "internalType": "uint16", "name": "resource", "type": "uint16" } + ], + "name": "dnsRecord", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes32", "name": "name", "type": "bytes32" } + ], + "name": "hasDNSRecords", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" } + ], + "name": "interfaceImplementer", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "bytes[]", "name": "data", "type": "bytes[]" }], + "name": "multicall", + "outputs": [{ "internalType": "bytes[]", "name": "results", "type": "bytes[]" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "pubkey", + "outputs": [ + { "internalType": "bytes32", "name": "x", "type": "bytes32" }, + { "internalType": "bytes32", "name": "y", "type": "bytes32" } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "contentType", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "setABI", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint256", "name": "coinType", "type": "uint256" }, + { "internalType": "bytes", "name": "a", "type": "bytes" } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "a", "type": "address" } + ], + "name": "setAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "bool", "name": "isAuthorised", "type": "bool" } + ], + "name": "setAuthorisation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes", "name": "hash", "type": "bytes" } + ], + "name": "setContenthash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "setDNSRecords", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }, + { "internalType": "address", "name": "implementer", "type": "address" } + ], + "name": "setInterface", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "string", "name": "name", "type": "string" } + ], + "name": "setName", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes32", "name": "x", "type": "bytes32" }, + { "internalType": "bytes32", "name": "y", "type": "bytes32" } + ], + "name": "setPubkey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "string", "name": "key", "type": "string" }, + { "internalType": "string", "name": "value", "type": "string" } + ], + "name": "setText", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "string", "name": "key", "type": "string" } + ], + "name": "text", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/web3-contracts/abis/ENSRegistry.json b/packages/web3-contracts/abis/ENSRegistry.json new file mode 100644 index 000000000000..0c156469f737 --- /dev/null +++ b/packages/web3-contracts/abis/ENSRegistry.json @@ -0,0 +1,202 @@ +[ + { + "inputs": [{ "internalType": "contract ENS", "name": "_old", "type": "address" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, + { "indexed": false, "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": true, "internalType": "bytes32", "name": "label", "type": "bytes32" }, + { "indexed": false, "internalType": "address", "name": "owner", "type": "address" } + ], + "name": "NewOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "address", "name": "resolver", "type": "address" } + ], + "name": "NewResolver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "uint64", "name": "ttl", "type": "uint64" } + ], + "name": "NewTTL", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "indexed": false, "internalType": "address", "name": "owner", "type": "address" } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "operator", "type": "address" } + ], + "name": "isApprovedForAll", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "old", + "outputs": [{ "internalType": "contract ENS", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "recordExists", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "resolver", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "operator", "type": "address" }, + { "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "setApprovalForAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "owner", "type": "address" } + ], + "name": "setOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "resolver", "type": "address" }, + { "internalType": "uint64", "name": "ttl", "type": "uint64" } + ], + "name": "setRecord", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "address", "name": "resolver", "type": "address" } + ], + "name": "setResolver", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes32", "name": "label", "type": "bytes32" }, + { "internalType": "address", "name": "owner", "type": "address" } + ], + "name": "setSubnodeOwner", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "bytes32", "name": "label", "type": "bytes32" }, + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "resolver", "type": "address" }, + { "internalType": "uint64", "name": "ttl", "type": "uint64" } + ], + "name": "setSubnodeRecord", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "bytes32", "name": "node", "type": "bytes32" }, + { "internalType": "uint64", "name": "ttl", "type": "uint64" } + ], + "name": "setTTL", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "bytes32", "name": "node", "type": "bytes32" }], + "name": "ttl", + "outputs": [{ "internalType": "uint64", "name": "", "type": "uint64" }], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ce135339edc..df641f8a8d3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -308,6 +308,7 @@ importers: '@masknet/plugin-cyberconnect': workspace:* '@masknet/plugin-dao': workspace:* '@masknet/plugin-debugger': workspace:* + '@masknet/plugin-ens': workspace:* '@masknet/plugin-example': workspace:* '@masknet/plugin-file-service': workspace:* '@masknet/plugin-flow': workspace:* @@ -446,6 +447,7 @@ importers: '@masknet/plugin-cyberconnect': link:../plugins/CyberConnect '@masknet/plugin-dao': link:../plugins/DAO '@masknet/plugin-debugger': link:../plugins/Debugger + '@masknet/plugin-ens': link:../plugins/ENS '@masknet/plugin-example': link:../plugins/example '@masknet/plugin-file-service': link:../plugins/FileService '@masknet/plugin-flow': link:../plugins/Flow @@ -686,6 +688,26 @@ importers: react-use: 17.3.2_react-dom@18.0.0+react@18.0.0 urlcat: 2.0.4 + packages/plugins/ENS: + specifiers: + '@masknet/plugin-infra': workspace:* + '@masknet/shared': workspace:* + '@masknet/shared-base': workspace:* + '@masknet/web3-contracts': workspace:* + '@masknet/web3-shared-evm': workspace:* + eth-ens-namehash: 2.0.8 + react-use: ^17.3.2 + web3-utils: 1.5.3 + dependencies: + '@masknet/plugin-infra': link:../../plugin-infra + '@masknet/shared': link:../../shared + '@masknet/shared-base': link:../../shared-base + '@masknet/web3-contracts': link:../../web3-contracts + '@masknet/web3-shared-evm': link:../../web3-shared/evm + eth-ens-namehash: 2.0.8 + react-use: 17.3.2_react-dom@18.0.0+react@18.0.0 + web3-utils: 1.5.3 + packages/plugins/FileService: specifiers: '@dimensiondev/common-protocols': 1.6.0-20210723072221-8f46a92 diff --git a/tsconfig.json b/tsconfig.json index 79afc1ef69a4..45f7ff2fe453 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -99,6 +99,7 @@ "@masknet/plugin-solana": ["./packages/plugins/Solana/src"], "@masknet/plugin-template": ["./packages/plugins/template/src"], "@masknet/plugin-cyberconnect": ["./packages/plugins/CyberConnect/src"], + "@masknet/plugin-ens": ["./packages/plugins/ENS/src"], "@masknet/plugin-go-plus-security": ["./packages/plugins/GoPlusSecurity/src"], // @masknet/scripts: insert-here 3 "@masknet/plugin-wallet": ["./packages/plugins/Wallet/src"]