Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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 docs/rfc/000-TypedMessage-binary-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type TypedMessageBase = [
type: TypedMessageTypeEnum | String,
version: Integer,
metadata: Map | Nil,
...rest: Array<Any>
...rest: Array<Any>,
]
enum TypedMessageTypeEnum {
Tuple = 0,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"yarn": ">=999.0.0",
"npm": ">=999.0.0"
},
"version": "2.5.0",
"version": "2.6.0",
"private": true,
"license": "AGPL-3.0-or-later",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,12 @@ export interface PersonaRowCardUIProps {
profiles: ProfileInformation[]
definedSocialNetworks: SocialNetwork[]
publicKey: string
onConnect: (identifier: PersonaIdentifier, networkIdentifier: string, type?: 'local' | 'nextID') => void
onConnect: (
identifier: PersonaIdentifier,
networkIdentifier: string,
type?: 'local' | 'nextID',
profile?: ProfileIdentifier,
) => void
onDisconnect: (identifier: ProfileIdentifier) => void
onRename: (identifier: PersonaIdentifier, target: string, callback?: () => void) => Promise<void>
onDeleteBound: (
Expand Down Expand Up @@ -200,7 +205,9 @@ export const PersonaRowCardUI = memo<PersonaRowCardUIProps>((props) => {
disableAdd={currentNetworkProfiles.length >= 5}
isHideOperations={false}
key={networkIdentifier}
onConnect={(type) => onConnect(identifier, networkIdentifier, type)}
onConnect={(type, profile) =>
onConnect(identifier, networkIdentifier, type, profile)
}
onDisconnect={onDisconnect}
onDeleteBound={(profile: ProfileIdentifier) => {
onDeleteBound(identifier, profile, networkIdentifier, NextIDAction.Delete)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ export const PersonaCard = memo<PersonaCardProps>((props) => {

export interface PersonaCardUIProps extends PersonaCardProps {
definedSocialNetworks: SocialNetwork[]
onConnect: (identifier: PersonaIdentifier, networkIdentifier: string, type?: 'local' | 'nextID') => void
onConnect: (
identifier: PersonaIdentifier,
networkIdentifier: string,
type?: 'local' | 'nextID',
profile?: ProfileIdentifier,
) => void
onDisconnect: (identifier: ProfileIdentifier) => void
verification?: NextIDPersonaBindings
}
Expand Down Expand Up @@ -121,7 +126,9 @@ export const PersonaCardUI = memo<PersonaCardUIProps>((props) => {
proof={proof}
isHideOperations
key={networkIdentifier}
onConnect={(type) => onConnect(identifier, networkIdentifier, type)}
onConnect={(type, profile) =>
onConnect(identifier, networkIdentifier, type, profile)
}
onDisconnect={onDisconnect}
profileIdentifiers={currentNetworkProfiles.map((x) => x.identifier)}
networkIdentifier={networkIdentifier}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const UnconnectedPersonaLine = memo<UnconnectedPersonaLineProps>(({ onCon

export interface ConnectedPersonaLineProps {
isHideOperations: boolean
onConnect: (type: 'nextID' | 'local') => void
onConnect: (type: 'nextID' | 'local', profile?: ProfileIdentifier) => void
onDisconnect: (identifier: ProfileIdentifier) => void
onDeleteBound?: (profile: ProfileIdentifier) => void
profileIdentifiers: ProfileIdentifier[]
Expand Down Expand Up @@ -108,10 +108,10 @@ export const ConnectedPersonaLine = memo<ConnectedPersonaLineProps>(
const handleUserIdClick = async (network: string, userId: string) => {
await openProfilePage(network, userId)
}
const handleProofIconClick = (e: MouseEvent, proof: BindingProof | undefined) => {
const handleProofIconClick = (e: MouseEvent, proof: BindingProof | undefined, profile: ProfileIdentifier) => {
e.stopPropagation()
if (!proof || !proof.is_valid) {
onConnect('nextID')
onConnect('nextID', profile)
}
}

Expand All @@ -138,7 +138,7 @@ export const ConnectedPersonaLine = memo<ConnectedPersonaLineProps>(
{profile.network === EnhanceableSite.Twitter && (
<Typography
className={classes.proofIconBox}
onClick={(e: MouseEvent) => handleProofIconClick(e, isProved)}>
onClick={(e: MouseEvent) => handleProofIconClick(e, isProved, profile)}>
{proof.loading ? (
<LoadingAnimation />
) : isProved?.is_valid ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function dispatchEventRaw<T extends Event>(
overwrites: Partial<T> = {},
) {
let currentTarget: null | Node | Document = target
const event = getMockedEvent(eventBase, () => currentTarget!, overwrites)
const event = getMockedEvent(eventBase, () => (isTwitter() ? target! : currentTarget!), overwrites)
// Note: in firefox, "event" is "Opaque". Displayed as an empty object.
const type = eventBase.type
if (!CapturingEvents.has(type)) return warn("[@masknet/injected-script] Trying to send event didn't captured.")
Expand Down
1 change: 1 addition & 0 deletions packages/mask/.webpack/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
'@masknet/gun-utils': join(__dirname, '../../gun-utils/src/'),
'@masknet/shared': join(__dirname, '../../shared/src/'),
'@masknet/shared-base': join(__dirname, '../../shared-base/src/'),
'@masknet/shared-base-ui': join(__dirname, '../../shared-base-ui/src/'),
'@masknet/theme': join(__dirname, '../../theme/src/'),
'@masknet/icons': join(__dirname, '../../icons/index.ts'),
'@masknet/web3-providers': join(__dirname, '../../web3-providers/src'),
Expand Down
13 changes: 13 additions & 0 deletions packages/mask/background/services/crypto/decryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ import {
} from '@masknet/encryption'
import {
AESCryptoKey,
ECKeyIdentifierFromJsonWebKey,
EC_JsonWebKey,
EC_Public_JsonWebKey,
IdentifierMap,
PostIVIdentifier,
ProfileIdentifier,
} from '@masknet/shared-base'
import type { TypedMessage } from '@masknet/typed-message'
import { noop } from 'lodash-unified'
import { queryProfileDB, queryPersonaDB } from '../../database/persona/db'
import {
createProfileWithPersona,
decryptByLocalKey,
Expand Down Expand Up @@ -225,6 +228,16 @@ async function storeAuthorPublicKey(
if (pub.algr !== EC_KeyCurveEnum.secp256k1) {
throw new Error('TODO: support other curves')
}

// if privateKey, we should possibly not recreate it
const profile = await queryProfileDB(payloadAuthor)
const persona = profile?.linkedPersona ? await queryPersonaDB(profile.linkedPersona) : undefined
if (persona?.privateKey) return

const key = (await crypto.subtle.exportKey('jwk', pub.key)) as EC_JsonWebKey
const otherPersona = await queryPersonaDB(ECKeyIdentifierFromJsonWebKey(key))
if (otherPersona?.privateKey) return

return createProfileWithPersona(
payloadAuthor,
{ connectionConfirmState: 'confirmed' },
Expand Down
2 changes: 1 addition & 1 deletion packages/mask/background/services/identity/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { createPersonaByPrivateKey } from './persona/create'
export { signWithPersona, type SignRequest, type SignRequestResult } from './persona/sign'
export { signWithPersona, type SignRequest, type SignRequestResult, generateSignResult } from './persona/sign'
export { exportPersonaMnemonicWords, exportPersonaPrivateKey } from './persona/backup'
6 changes: 5 additions & 1 deletion packages/mask/background/services/identity/persona/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ECDSASignature,
} from 'ethereumjs-util'
import { MaskMessages } from '../../../../shared'
import { PersonaIdentifier, fromBase64URL, PopupRoutes } from '@masknet/shared-base'
import { PersonaIdentifier, fromBase64URL, PopupRoutes, ECKeyIdentifier } from '@masknet/shared-base'
import { queryPersonasWithPrivateKey } from '../../../../background/database/persona/db'
import { openPopupWindow } from '../../../../background/services/helper'
import { delay } from '@dimensiondev/kit'
Expand Down Expand Up @@ -49,6 +49,10 @@ export async function signWithPersona({ message, method, identifier }: SignReque
})
})
const signer = await waitForApprove
return generateSignResult(signer, message)
}

export async function generateSignResult(signer: ECKeyIdentifier, message: string) {
const persona = (await queryPersonasWithPrivateKey()).find((x) => x.identifier.equals(signer))
if (!persona) throw new Error('Persona not found')

Expand Down
1 change: 1 addition & 0 deletions packages/mask/shared-ui/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"setup_guide_connect_auto": "Connect",
"setup_guide_connect_failed": "Re-Connect",
"setup_guide_verify": "Verfiy",
"setup_guide_verify_should_change_profile": "Inconsistent Account",
"setup_guide_verify_dismiss": "Don't show again.",
"setup_guide_verify_checking": "Checking",
"setup_guide_verify_post_not_found": "No verification post found",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ export function Composition({ type = 'timeline', requireClipboardPermission }: P

useEffect(() => {
return MaskMessages.events.requestComposition.on(({ reason, open, content, options }) => {
if (reason !== 'reply' && (reason !== type || globalUIState.profiles.value.length <= 0)) return
if (
(reason !== 'reply' && reason !== type) ||
(reason === 'reply' && type === 'popup') ||
globalUIState.profiles.value.length <= 0
)
return
setOpen(open)
setReason(reason)
if (content) UI.current?.setMessage(content)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ export const CompositionDialogUI = forwardRef<CompositionRef, CompositionProps>(
})
}, [])

useImperativeHandle(
ref,
const refItem = useMemo(
(): CompositionRef => ({
setMessage: (msg) => {
if (Editor.current) Editor.current.value = msg
Expand All @@ -119,6 +118,8 @@ export const CompositionDialogUI = forwardRef<CompositionRef, CompositionProps>(
[reset],
)

useImperativeHandle(ref, () => refItem, [refItem])

const context = useMemo(
(): CompositionContext => ({
attachMetadata: (meta, data) => Editor.current?.attachMetadata(meta, data),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { RedPacketPluginID } from '../../plugins/RedPacket/constants'
import { ITO_PluginID } from '../../plugins/ITO/constants'
import { ClickableChip } from '../shared/SelectRecipients/ClickableChip'
import { makeStyles } from '@masknet/theme'
import { useCallback, useState, useRef, forwardRef, memo, useImperativeHandle } from 'react'
import { useCallback, useState, useRef, forwardRef, memo, useImperativeHandle, useMemo } from 'react'
import { useChainId } from '@masknet/web3-shared-evm'
import { Trans } from 'react-i18next'
const useStyles = makeStyles()({
Expand Down Expand Up @@ -60,8 +60,7 @@ export const PluginEntryRender = memo(

function useSetPluginEntryRenderRef(ref: React.ForwardedRef<PluginEntryRenderRef>) {
const pluginRefs = useRef<Record<string, PluginRef | undefined | null>>({})
useImperativeHandle(
ref,
const refItem: PluginEntryRenderRef = useMemo(
() => ({
openPlugin: function openPlugin(id: string, tryTimes = 4) {
const ref = pluginRefs.current[id]
Expand All @@ -74,13 +73,15 @@ function useSetPluginEntryRenderRef(ref: React.ForwardedRef<PluginEntryRenderRef
}),
[],
)
useImperativeHandle(ref, () => refItem, [refItem])
const trackPluginRef = (pluginID: string) => (ref: PluginRef | null) => {
pluginRefs.current = { ...pluginRefs.current, [pluginID]: ref }
}
return [trackPluginRef]
}
function useSetPluginRef(ref: React.ForwardedRef<PluginRef>, onClick: () => void) {
useImperativeHandle(ref, () => ({ open: onClick }), [onClick])
const refItem = useMemo(() => ({ open: onClick }), [onClick])
useImperativeHandle(ref, () => refItem, [refItem])
}

type PluginRef = { open(): void }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@masknet/typed-message'
import { makeStyles } from '@masknet/theme'
import { InputBase, Alert, Button } from '@mui/material'
import { useCallback, useImperativeHandle, useState, useRef, forwardRef, memo } from 'react'
import { useCallback, useImperativeHandle, useState, useRef, forwardRef, memo, useMemo } from 'react'
import { useI18N } from '../../utils'
import { BadgeRenderer } from './BadgeRenderer'

Expand Down Expand Up @@ -81,30 +81,27 @@ export const TypedMessageEditor = memo(
},
[setMessage],
)
useImperativeHandle(
ref,
(): TypedMessageEditorRef => {
return {
get estimatedLength() {
// TODO: we should count metadata into the estimated size
if (isTypedMessageText(currentValue.current)) return currentValue.current.content.length
return 0
},
get value() {
return currentValue.current
},
set value(val) {
setMessage(val)
},
reset: () => setMessage(emptyMessage),
attachMetadata(meta, data) {
setMessage(editTypedMessageMeta(currentValue.current, (map) => map.set(meta, data)))
},
dropMetadata: deleteMetaID,
}
},
[setMessage, deleteMetaID],
)
const refItem = useMemo((): TypedMessageEditorRef => {
return {
get estimatedLength() {
// TODO: we should count metadata into the estimated size
if (isTypedMessageText(currentValue.current)) return currentValue.current.content.length
return 0
},
get value() {
return currentValue.current
},
set value(val) {
setMessage(val)
},
reset: () => setMessage(emptyMessage),
attachMetadata(meta, data) {
setMessage(editTypedMessageMeta(currentValue.current, (map) => map.set(meta, data)))
},
dropMetadata: deleteMetaID,
}
}, [setMessage, deleteMetaID])
useImperativeHandle(ref, () => refItem, [refItem])

if (!isTypedMessageText(value)) {
const reset = () => setAsText('')
Expand Down
7 changes: 4 additions & 3 deletions packages/mask/src/components/DataSource/useNextID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ export const usePersonaBoundPlatform = (personaPublicKey: string) => {
let isOpenedVerifyDialog = false
let isOpenedFromButton = false

const verifyPersona = (personaIdentifier?: PersonaIdentifier) => async () => {
const verifyPersona = (personaIdentifier?: PersonaIdentifier, username?: string) => async () => {
if (!personaIdentifier) return
currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({
status: SetupGuideStep.VerifyOnNextID,
persona: personaIdentifier.toText(),
username,
})
}

Expand Down Expand Up @@ -107,7 +108,7 @@ export function useNextIDConnectStatus() {
isOpenedVerifyDialog = true
isOpenedFromButton = false
return NextIDVerificationStatus.WaitingVerify
}, [username, enableNextID, lastStateRef.value, isOpenedVerifyDialog, currentPersonaIdentifier.value])
}, [username, enableNextID, isOpenedVerifyDialog, currentPersonaIdentifier.value])

return {
isVerified: VerificationStatus === NextIDVerificationStatus.Verified,
Expand All @@ -119,7 +120,7 @@ export function useNextIDConnectStatus() {
},
action:
VerificationStatus === NextIDVerificationStatus.WaitingVerify
? verifyPersona(personaConnectStatus.currentConnectedPersona?.identifier)
? verifyPersona(personaConnectStatus.currentConnectedPersona?.identifier, lastState.username)
: null,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ function SetupGuideUI(props: SetupGuideUIProps) {
lastState.username || (lastRecognized.identifier.isUnknown ? '' : lastRecognized.identifier.userId)
const [username, setUsername] = useState(getUsername)

const disableVerify =
lastRecognized.identifier.isUnknown || !lastState.username
? false
: lastRecognized.identifier.userId !== lastState.username

useEffect(() => {
const handler = (val: SocialNetworkUI.CollectingCapabilities.IdentityResolved) => {
if (username === '' && !val.identifier.isUnknown) setUsername(val.identifier.userId)
Expand Down Expand Up @@ -259,6 +264,7 @@ function SetupGuideUI(props: SetupGuideUIProps) {
onVerify={onVerify}
onDone={onVerifyDone}
onClose={onClose}
disableVerify={disableVerify}
/>
)
case SetupGuideStep.PinExtension:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface VerifyNextIDProps extends Partial<WizardDialogProps> {
personaIdentifier?: PersonaIdentifier
network: string
avatar?: string
disableVerify: boolean
onUsernameChange?: (username: string) => void
onVerify: () => Promise<void>
onDone?: () => void
Expand All @@ -31,6 +32,7 @@ export const VerifyNextID = ({
onDone,
onClose,
network,
disableVerify,
}: VerifyNextIDProps) => {
const { t } = useI18N()

Expand Down Expand Up @@ -86,13 +88,13 @@ export const VerifyNextID = ({
<ActionButtonPromise
className={classes.button}
variant="contained"
init={t('setup_guide_verify')}
init={disableVerify ? t('setup_guide_verify_should_change_profile') : t('setup_guide_verify')}
waiting={t('setup_guide_verifying')}
complete={t('ok')}
failed={t('setup_guide_verifying_failed')}
executor={onVerify}
completeOnClick={onDone}
disabled={!username || !personaName}
disabled={!username || !personaName || disableVerify}
completeIcon={null}
failIcon={null}
failedOnClick="use executor"
Expand Down
Loading