Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v23.6.0
v24.5.0
6 changes: 6 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,16 @@
"words": [
"arbitrum",
"boba",
"Bsky",
"cashtags",
"celo",
"deeplink",
"endregion",
"firelfy",
"linkedin",
"luma",
"muln",
"pathnames",
"reposted",
"reposts",
"sepolia",
Expand All @@ -260,6 +264,8 @@
"tweetnacl",
"txid",
"waitlist",
"WARPCAST",
"webm",
"youtube"
]
}
19 changes: 10 additions & 9 deletions packages/mask/background/database/persona/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,31 +180,32 @@ export async function createPersonaByJsonWebKey(options: {

export async function createProfileWithPersona(
profileID: ProfileIdentifier,
data: LinkedProfileDetails,
keys: {
linkMeta: LinkedProfileDetails,
persona: {
nickname?: string
publicKey: EC_Public_JsonWebKey
privateKey?: EC_Private_JsonWebKey
localKey?: AESJsonWebKey
mnemonic?: PersonaRecord['mnemonic']
},
token?: string | null,
): Promise<void> {
const ec_id = (await ECKeyIdentifier.fromJsonWebKey(keys.publicKey)).unwrap()
const ec_id = (await ECKeyIdentifier.fromJsonWebKey(persona.publicKey)).unwrap()
const rec: PersonaRecord = {
createdAt: new Date(),
updatedAt: new Date(),
identifier: ec_id,
linkedProfiles: new Map(),
nickname: keys.nickname,
publicKey: keys.publicKey,
privateKey: keys.privateKey,
localKey: keys.localKey,
mnemonic: keys.mnemonic,
nickname: persona.nickname,
publicKey: persona.publicKey,
privateKey: persona.privateKey,
localKey: persona.localKey,
mnemonic: persona.mnemonic,
hasLogout: false,
}
await consistentPersonaDBWriteAccess(async (t) => {
await createOrUpdatePersonaDB(rec, { explicitUndefinedField: 'ignore', linkedProfiles: 'merge' }, t)
await attachProfileDB(profileID, ec_id, data, t)
await attachProfileDB(profileID, ec_id, linkMeta, { token }, t)
})
}
// #endregion
Expand Down
1 change: 1 addition & 0 deletions packages/mask/background/database/persona/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export interface ProfileRecord {
nickname?: string
localKey?: AESJsonWebKey
linkedPersona?: PersonaIdentifier
token?: string
createdAt: Date
updatedAt: Date
}
Expand Down
7 changes: 7 additions & 0 deletions packages/mask/background/database/persona/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ export async function attachProfileDB(
identifier: ProfileIdentifier,
attachTo: PersonaIdentifier,
data: LinkedProfileDetails,
profileExtra?: { token?: string | null },
t?: FullPersonaDBTransaction<'readwrite'>,
): Promise<void> {
t = t || createTransaction(await db(), 'readwrite')('personas', 'profiles', 'relations')
Expand All @@ -536,6 +537,12 @@ export async function attachProfileDB(
await detachProfileDB(identifier, t)
}

if (profileExtra?.token) {
profile.token = profileExtra.token
} else if (profileExtra && 'token' in profileExtra && !profileExtra.token) {
delete profile.token
}

profile.linkedPersona = attachTo
persona.linkedProfiles.set(identifier, data)

Expand Down
8 changes: 5 additions & 3 deletions packages/mask/background/services/identity/profile/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,22 +86,23 @@ export async function resolveUnknownLegacyIdentity(identifier: ProfileIdentifier
export async function attachProfile(
source: ProfileIdentifier,
target: ProfileIdentifier | PersonaIdentifier,
data: LinkedProfileDetails,
linkMeta: LinkedProfileDetails,
profileExtra?: { token?: string | null },
): Promise<void> {
if (target instanceof ProfileIdentifier) {
const profile = await queryProfileDB(target)
if (!profile?.linkedPersona) throw new Error('target not found')
target = profile.linkedPersona
}
return attachProfileDB(source, target, data)
return attachProfileDB(source, target, linkMeta, profileExtra)
}
export function detachProfile(identifier: ProfileIdentifier): Promise<void> {
return detachProfileDB(identifier)
}

/**
* Set NextID profile to profileDB
* */
*/

export async function attachNextIDPersonaToProfile(item: ProfileInformationFromNextID, whoAmI: ECKeyIdentifier) {
if (!item.linkedPersona) throw new Error('LinkedPersona Not Found')
Expand Down Expand Up @@ -137,6 +138,7 @@ export async function attachNextIDPersonaToProfile(item: ProfileInformationFromN
profileRecord.identifier,
item.linkedPersona!,
{ connectionConfirmState: 'confirmed' },
undefined,
t,
)
await createOrUpdateRelationDB(
Expand Down
6 changes: 3 additions & 3 deletions packages/mask/background/services/site-adaptors/connect.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { compact, first, sortBy } from 'lodash-es'
import stringify from 'json-stable-stringify'
import { delay } from '@masknet/kit'
import {
type PersonaIdentifier,
type ProfileIdentifier,
currentSetupGuideStatus,
SetupGuideStep,
} from '@masknet/shared-base'
import stringify from 'json-stable-stringify'
import { compact, first, sortBy } from 'lodash-es'
import type { Tabs } from 'webextension-polyfill'
import { definedSiteAdaptors } from '../../../shared/site-adaptors/definitions.js'
import type { SiteAdaptor } from '../../../shared/site-adaptors/types.js'
import type { Tabs } from 'webextension-polyfill'

async function hasPermission(origin: string): Promise<boolean> {
return browser.permissions.contains({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Trans } from '@lingui/react/macro'
import { Icons } from '@masknet/icons'
import { BindingDialog, LoadingStatus, SOCIAL_MEDIA_ROUND_ICON_MAPPING, type BindingDialogProps } from '@masknet/shared'
import { Sniffings, SOCIAL_MEDIA_NAME } from '@masknet/shared-base'
Expand All @@ -6,7 +7,6 @@ import { Box, Button, Typography } from '@mui/material'
import { memo } from 'react'
import { activatedSiteAdaptorUI } from '../../../site-adaptor-infra/ui.js'
import { SetupGuideContext } from './SetupGuideContext.js'
import { Trans } from '@lingui/react/macro'

const useStyles = makeStyles()((theme) => {
return {
Expand Down
1 change: 1 addition & 0 deletions packages/mask/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@dimensiondev/mask-wallet-core": "0.1.0-20211013082857-eb62e5f",
"@ethereumjs/util": "^9.0.3",
"@hookform/resolvers": "^3.6.0",
"@lens-protocol/client": "0.0.0-canary-20250408064617",
"@masknet/backup-format": "workspace:^",
"@masknet/encryption": "workspace:^",
"@masknet/flags": "workspace:^",
Expand Down
47 changes: 28 additions & 19 deletions packages/mask/popups/Popup.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { PageUIProvider, PersonaContext } from '@masknet/shared'
import { jsxCompose, MaskMessages, PopupRoutes } from '@masknet/shared-base'
import { MaskMessages, PopupRoutes } from '@masknet/shared-base'
import { PopupSnackbarProvider } from '@masknet/theme'
import { EVMWeb3ContextProvider } from '@masknet/web3-hooks-base'
import { ProviderType } from '@masknet/web3-shared-evm'
import { Box } from '@mui/material'
import { Suspense, cloneElement, lazy, memo, useEffect, useMemo, useState, type ReactNode } from 'react'
import { Suspense, lazy, memo, useEffect, useMemo, useState, type ReactNode } from 'react'
import { useIdleTimer } from 'react-idle-timer'
import {
createHashRouter,
Expand All @@ -30,6 +30,7 @@ import { WalletFrame, walletRoutes } from './pages/Wallet/index.js'
import { ContactsFrame, contactsRoutes } from './pages/Friends/index.js'
import { ErrorBoundaryUIOfError } from '../../shared-base-ui/src/components/ErrorBoundary/ErrorBoundary.js'
import { TraderFrame, traderRoutes } from './pages/Trader/index.js'
import { InteractionWalletContext } from './pages/Wallet/Interaction/InteractionContext.js'

const personaInitialState = {
queryOwnedPersonaInformation: Services.Identity.queryOwnedPersonaInformation,
Expand Down Expand Up @@ -108,23 +109,31 @@ export default function Popups() {
throttle: 10000,
})

return jsxCompose(
<PersistQueryClientProvider client={queryClient} persistOptions={queryPersistOptions} />,
// eslint-disable-next-line react-compiler/react-compiler
<PageUIProvider useTheme={usePopupTheme} />,
<PopupSnackbarProvider children={null!} />,
<EVMWeb3ContextProvider providerType={ProviderType.MaskWallet} />,
<PopupContext />,
<PageTitleContext value={titleContext} />,
)(
cloneElement,
<>
{/* https://github.com/TanStack/query/issues/5417 */}
{process.env.NODE_ENV === 'development' ?
<ReactQueryDevtools buttonPosition="bottom-right" />
: null}
<RouterProvider router={router} fallbackElement={pending} future={{ v7_startTransition: true }} />
</>,
return (
<PersistQueryClientProvider client={queryClient} persistOptions={queryPersistOptions}>
{/* eslint-disable-next-line react-compiler/react-compiler */}
<PageUIProvider useTheme={usePopupTheme}>
<PopupSnackbarProvider>
<EVMWeb3ContextProvider providerType={ProviderType.MaskWallet}>
<InteractionWalletContext>
<PopupContext>
<PageTitleContext value={titleContext}>
{/* https://github.com/TanStack/query/issues/5417 */}
{process.env.NODE_ENV === 'development' ?
<ReactQueryDevtools buttonPosition="bottom-right" />
: null}
<RouterProvider
router={router}
fallbackElement={pending}
future={{ v7_startTransition: true }}
/>
</PageTitleContext>
</PopupContext>
</InteractionWalletContext>
</EVMWeb3ContextProvider>
</PopupSnackbarProvider>
</PageUIProvider>
</PersistQueryClientProvider>
)
}

Expand Down
2 changes: 1 addition & 1 deletion packages/mask/popups/components/SocialAccounts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const SocialAccounts = memo<SocialAccountsProps>(function SocialAccounts(
<Box className={classes.accountItem} key={index} onClick={() => onAccountClick(account)}>
<AccountAvatar
avatar={account.avatar}
network={account.identifier.network}
network={account.identifier.network as EnhanceableSite}
isValid={account.is_valid}
classes={{ avatar: classes.avatar }}
/>
Expand Down
5 changes: 4 additions & 1 deletion packages/mask/popups/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { EnhanceableSite } from '@masknet/shared-base'
export const MATCH_PASSWORD_RE = /^(?=.{8,20}$)(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^\dA-Za-z]).*/u
export const MAX_FILE_SIZE = 10 * 1024 * 1024

export const SOCIAL_MEDIA_ICON_FILTER_COLOR: Record<EnhanceableSite | string, string> = {
export const SOCIAL_MEDIA_ICON_FILTER_COLOR: Record<EnhanceableSite, string> = {
[EnhanceableSite.Twitter]: 'drop-shadow(0px 6px 12px rgba(29, 161, 242, 0.20))',
[EnhanceableSite.Facebook]: 'drop-shadow(0px 6px 12px rgba(60, 89, 155, 0.20))',
[EnhanceableSite.Minds]: 'drop-shadow(0px 6px 12px rgba(33, 37, 42, 0.20))',
[EnhanceableSite.Instagram]: 'drop-shadow(0px 6px 12px rgba(246, 100, 16, 0.20))',
[EnhanceableSite.OpenSea]: '',
[EnhanceableSite.Mirror]: '',
[EnhanceableSite.Localhost]: '',
[EnhanceableSite.Firefly]: '',
[EnhanceableSite.Farcaster]: '',
[EnhanceableSite.Lens]: '',
}
2 changes: 1 addition & 1 deletion packages/mask/popups/hooks/useSupportSocialNetworks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useQuery } from '@tanstack/react-query'

export function useSupportSocialNetworks() {
return useQuery({
queryKey: ['@@Service.SiteAdaptor.getSupportedSites({ isSocialNetwork: true })'],
queryKey: ['Service.SiteAdaptor.getSupportedSites({ isSocialNetwork: true })'],
queryFn: async () => {
const sites = await Service.SiteAdaptor.getSupportedSites({ isSocialNetwork: true })
return sites.map((x) => x.networkIdentifier as EnhanceableSite)
Expand Down
19 changes: 13 additions & 6 deletions packages/mask/popups/modals/ConnectSocialAccountModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import { memo, useCallback } from 'react'
import { EMPTY_LIST, type EnhanceableSite } from '@masknet/shared-base'
import Services from '#services'
import { Trans } from '@lingui/react/macro'
import { PersonaContext } from '@masknet/shared'
import { EMPTY_LIST, EnhanceableSite, PopupRoutes } from '@masknet/shared-base'
import { Telemetry } from '@masknet/web3-telemetry'
import { EventType } from '@masknet/web3-telemetry/types'
import { memo, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { requestPermissionFromExtensionPage } from '../../../shared-ui/index.js'
import { ActionModal, type ActionModalBaseProps } from '../../components/index.js'
import { EventMap } from '../../../shared/definitions/event.js'
import { ConnectSocialAccounts } from '../../components/ConnectSocialAccounts/index.js'
import { ActionModal, type ActionModalBaseProps } from '../../components/index.js'
import { useSupportSocialNetworks } from '../../hooks/index.js'
import Services from '#services'
import { EventMap } from '../../../shared/definitions/event.js'
import { Trans } from '@lingui/react/macro'

export const ConnectSocialAccountModal = memo<ActionModalBaseProps>(function ConnectSocialAccountModal(props) {
const { data: definedSocialNetworks = EMPTY_LIST } = useSupportSocialNetworks()

const { currentPersona } = PersonaContext.useContainer()
const navigate = useNavigate()

const handleConnect = useCallback(
async (networkIdentifier: EnhanceableSite) => {
if (networkIdentifier === EnhanceableSite.Farcaster) {
return navigate(PopupRoutes.ConnectFirefly)
} else if (networkIdentifier === EnhanceableSite.Lens) {
return navigate(PopupRoutes.ConnectLens)
}
if (!currentPersona) return
if (!(await requestPermissionFromExtensionPage(networkIdentifier))) return
await Services.SiteAdaptor.connectSite(currentPersona.identifier, networkIdentifier, undefined)
Expand Down
12 changes: 5 additions & 7 deletions packages/mask/popups/modals/SupportedSitesModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,19 @@ export const SupportedSitesModal = memo<ActionModalBaseProps>(function Supported
<List className={classes.list}>
{!isPending && data ?
data.map((x) => {
const Icon = SOCIAL_MEDIA_ROUND_ICON_MAPPING[x.networkIdentifier]

const networkIdentifier = x.networkIdentifier as EnhanceableSite
const Icon = SOCIAL_MEDIA_ROUND_ICON_MAPPING[networkIdentifier]
return (
<ListItemButton
key={x.networkIdentifier}
className={classes.item}
onClick={() =>
handleSwitch({ ...x, networkIdentifier: x.networkIdentifier as EnhanceableSite })
}>
onClick={() => handleSwitch({ ...x, networkIdentifier })}>
{Icon ?
<ListItemIcon className={classes.icon}>
<Icon
size={24}
style={{
filter: SOCIAL_MEDIA_ICON_FILTER_COLOR[x.networkIdentifier],
filter: SOCIAL_MEDIA_ICON_FILTER_COLOR[networkIdentifier],
backdropFilter: 'blur(8px)',
borderRadius: 99,
}}
Expand All @@ -98,7 +96,7 @@ export const SupportedSitesModal = memo<ActionModalBaseProps>(function Supported
: null}
<ListItemText
classes={{ primary: classes.name }}
primary={SOCIAL_MEDIA_NAME[x.networkIdentifier]}
primary={SOCIAL_MEDIA_NAME[networkIdentifier]}
/>
<Switch checked={!!x.hasPermission && !!x.allowInject} />
</ListItemButton>
Expand Down
4 changes: 2 additions & 2 deletions packages/mask/popups/pages/Personas/AccountDetail/UI.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Trans } from '@lingui/react/macro'
import type { BindingProof, ProfileAccount } from '@masknet/shared-base'
import type { BindingProof, EnhanceableSite, ProfileAccount } from '@masknet/shared-base'
import { makeStyles } from '@masknet/theme'
import { Box, Button, Typography } from '@mui/material'
import { memo, useCallback } from 'react'
Expand Down Expand Up @@ -52,7 +52,7 @@ export const AccountDetailUI = memo<AccountDetailUIProps>(function AccountDetail
<Box className={classes.account}>
<AccountAvatar
avatar={account.avatar}
network={account.identifier.network}
network={account.identifier.network as EnhanceableSite}
isValid={account.is_valid}
classes={{ avatar: classes.avatar }}
/>
Expand Down
Loading