Skip to content

Commit

Permalink
fix: bugfix for backup (#10421)
Browse files Browse the repository at this point in the history
* fix: bugfix for backup

* chore: reply reivew
  • Loading branch information
nuanyang233 committed Aug 16, 2023
1 parent 0f2a0a3 commit 93b1fc0
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 38 deletions.
1 change: 1 addition & 0 deletions packages/dashboard/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
"settings_backup_preview_contacts": "Contacts",
"settings_backup_preview_file": "File",
"settings_backup_preview_wallets": "Mask Wallet",
"settings_backup_preview_set_payment_password": "You need to set a password to enable the wallet functionality before you can back up the wallet. <settings> Go to settings </settings>",
"settings_backup_preview_created_at": "Backup Time",
"settings_language_title": "Language",
"settings_language_desc": "Select the language you would like to use",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ export interface BackupContentCheckedStatus {
export interface BackupContentSelectorProps {
json: BackupSummary
onChange(data: BackupContentCheckedStatus): void
hasPassword?: boolean
}

export default function BackupContentSelector({ json, onChange }: BackupContentSelectorProps) {
export default function BackupContentSelector({ json, onChange, hasPassword }: BackupContentSelectorProps) {
const t = useDashboardI18N()
const records = [
{
name: t.settings_backup_preview_personas(),
value: json.personas,
value: json.personas.length,
},
{
name: t.settings_backup_preview_associated_accounts(),
Expand Down Expand Up @@ -95,17 +96,18 @@ export default function BackupContentSelector({ json, onChange }: BackupContentS
</Box>
</SelectItem>
{json.wallets ? (
<SelectItem>
<SelectItem sx={{ opacity: !hasPassword ? '0.5' : undefined }}>
<CheckboxContainer>
<Checkbox
disabled={!hasPassword}
checked={walletChecked}
onChange={(event) => setWalletChecked(event.target.checked)}
name="wallet"
/>
</CheckboxContainer>
<BackupItem sx={{ flex: 1 }}>
<Typography variant="body2">{t.settings_backup_preview_wallets()}</Typography>
<Typography variant="body2">{json.wallets}</Typography>
<Typography variant="body2">{json.wallets.length}</Typography>
</BackupItem>
</SelectItem>
) : null}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useContext, useEffect, useMemo, useState } from 'react'
import { useAsync, useAsyncFn } from 'react-use'
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { useAsync, useAsyncFn, useAsyncRetry } from 'react-use'
import formatDateTime from 'date-fns/format'
import { Box } from '@mui/material'
import { Box, Link, Typography } from '@mui/material'
import { encryptBackup } from '@masknet/backup-format'
import { MimeType } from '@masknet/shared-base'
import { CrossIsolationMessages, MimeType, PopupRoutes } from '@masknet/shared-base'
import { MaskDialog, useCustomSnackbar } from '@masknet/theme'
import { encode } from '@msgpack/msgpack'
import { WalletServiceRef } from '@masknet/plugin-infra/dom'
Expand All @@ -12,7 +12,7 @@ import { LoadingButton } from '../../../../components/LoadingButton/index.js'
import { MaskAlert } from '../../../../components/MaskAlert/index.js'
import PasswordFiled from '../../../../components/PasswordField/index.js'
import { LoadingCard } from '../../../../components/LoadingCard/index.js'
import { useDashboardI18N } from '../../../../locales/index.js'
import { DashboardTrans, useDashboardI18N } from '../../../../locales/index.js'
import { fetchUploadLink, uploadBackupValue, type VerifyCodeRequest } from '../../api.js'
import { UserContext } from '../../hooks/UserContext.js'
import BackupContentSelector, { type BackupContentCheckedStatus } from '../BackupContentSelector.js'
Expand Down Expand Up @@ -41,6 +41,8 @@ export default function BackupDialog({ local = true, params, open, merged, onClo

const { value: previewInfo, loading: searching } = useAsync(() => Services.Backup.generateBackupPreviewInfo())

const { value: hasPassword, retry } = useAsyncRetry(WalletServiceRef.value.hasPassword, [])

const [{ loading }, handleBackup] = useAsyncFn(async () => {
if (backupPassword !== user.backupPassword) {
setIncorrectBackupPassword(true)
Expand Down Expand Up @@ -100,6 +102,12 @@ export default function BackupDialog({ local = true, params, open, merged, onClo
})
}

const onSetupPaymentPassword = useCallback(async () => {
await Services.Helper.openPopupWindow(hasPassword ? PopupRoutes.Wallet : PopupRoutes.SetPaymentPassword, {
isCreating: true,
})
}, [hasPassword])

const backupDisabled = useMemo(() => {
return !backupPassword || (showPassword.wallet && !paymentPassword) || loading
}, [backupPassword, paymentPassword, loading])
Expand All @@ -112,6 +120,10 @@ export default function BackupDialog({ local = true, params, open, merged, onClo
setIncorrectPaymentPassword(false)
}, [paymentPassword])

useEffect(() => {
return CrossIsolationMessages.events.passwordStatusUpdated.on(retry)
}, [retry])

return (
<MaskDialog maxWidth="xs" title={title} open={open} onClose={onClose}>
{searching ? (
Expand All @@ -126,7 +138,13 @@ export default function BackupDialog({ local = true, params, open, merged, onClo
</Box>
) : null}

{previewInfo ? <BackupContentSelector json={previewInfo} onChange={handleContentChange} /> : null}
{previewInfo ? (
<BackupContentSelector
hasPassword={hasPassword}
json={previewInfo}
onChange={handleContentChange}
/>
) : null}

<PasswordFiled
fullWidth
Expand All @@ -150,6 +168,21 @@ export default function BackupDialog({ local = true, params, open, merged, onClo
/>
) : null}

{!hasPassword ? (
<Typography sx={{ fontSize: 13, lineHeight: '20px', mb: 2 }}>
<DashboardTrans.settings_backup_preview_set_payment_password
components={{
settings: (
<Link
sx={{ fontWeight: 700, color: 'inherit', cursor: 'pointer' }}
onClick={onSetupPaymentPassword}
/>
),
}}
/>
</Typography>
) : null}

<LoadingButton fullWidth disabled={backupDisabled} onClick={handleBackup} loading={loading}>
{t.settings_button_backup()}
</LoadingButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,28 @@ import * as wallet_ts from /* webpackDefer: true */ 'wallet.ts'
import { isNonNull } from '@masknet/kit'
import { isSameAddress } from '@masknet/web3-shared-base'
import type { NormalizedBackup } from '@masknet/backup-format'
import { WalletServiceRef } from '@masknet/plugin-infra/dom'
import {
toBase64URL,
type EC_Public_JsonWebKey,
type EC_Private_JsonWebKey,
type LegacyWalletRecord,
} from '@masknet/shared-base'
import type { WalletRecord } from '../../../shared/definitions/wallet.js'
import { exportMnemonicWords, exportPrivateKey, getLegacyWallets, getWallets } from '../wallet/services/index.js'

export async function internal_wallet_backup() {
const wallet = await Promise.all([backupAllWallets(), backupAllLegacyWallets()])
return wallet.flat()
}

async function backupAllWallets(): Promise<NormalizedBackup.WalletBackup[]> {
const wallets = await WalletServiceRef.value.getWallets()
const wallets = await getWallets()
const allSettled = await Promise.allSettled(
wallets.map(async (wallet) => {
return {
...wallet,
mnemonic: wallet.derivationPath
? await WalletServiceRef.value.exportMnemonicWords(wallet.address)
: undefined,
privateKey: wallet.derivationPath
? undefined
: await WalletServiceRef.value.exportPrivateKey(wallet.address),
mnemonic: wallet.derivationPath ? await exportMnemonicWords(wallet.address) : undefined,
privateKey: wallet.derivationPath ? undefined : await exportPrivateKey(wallet.address),
}
}),
)
Expand All @@ -39,7 +35,7 @@ async function backupAllWallets(): Promise<NormalizedBackup.WalletBackup[]> {
}

async function backupAllLegacyWallets(): Promise<NormalizedBackup.WalletBackup[]> {
const x = await WalletServiceRef.value.getLegacyWallets()
const x = await getLegacyWallets()
return x.map(LegacyWalletRecordToJSONFormat)
}
function WalletRecordToJSONFormat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,25 @@ import {
isK256PrivateKey,
generateNewWalletName,
} from '@masknet/shared-base'
import { WalletServiceRef } from '@masknet/plugin-infra/dom'
import {
getDerivableAccounts,
getWallets,
recoverWalletFromMnemonicWords,
recoverWalletFromPrivateKey,
} from '../wallet/services/index.js'

export async function internal_wallet_restore(backup: NormalizedBackup.WalletBackup[]) {
for (const wallet of backup) {
try {
const wallets = await WalletServiceRef.value.getWallets()
const wallets = await getWallets()
const name = wallet.name || generateNewWalletName(wallets)
if (wallet.privateKey.some)
await WalletServiceRef.value.recoverWalletFromPrivateKey(
name,
await JWKToKey(wallet.privateKey.val, 'private'),
)
await recoverWalletFromPrivateKey(name, await JWKToKey(wallet.privateKey.val, 'private'))
else if (wallet.mnemonic.some) {
// fix a backup bug of pre-v2.2.2 versions
const accounts = await WalletServiceRef.value.getDerivableAccounts(wallet.mnemonic.val.words, 1, 5)
const accounts = await getDerivableAccounts(wallet.mnemonic.val.words, 1, 5)
const index = accounts.findIndex(currySameAddress(wallet.address))
await WalletServiceRef.value.recoverWalletFromMnemonicWords(
await recoverWalletFromMnemonicWords(
name,
wallet.mnemonic.val.words,
index > -1 ? `${HD_PATH_WITHOUT_INDEX_ETHEREUM}/${index}` : wallet.mnemonic.val.path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export const LogoutUI = memo<LogoutUIProps>(

const onConfirm = useCallback(async () => {
if (!backupPassword && !!manageWallets.length) {
modalNavigate(PopupModalRoutes.SetBackupPassword)
modalNavigate(PopupModalRoutes.SetBackupPassword, { to: PopupRoutes.ExportPrivateKey })
return
}
if (manageWallets.length && paymentPassword) {
Expand Down Expand Up @@ -294,11 +294,11 @@ export const LogoutUI = memo<LogoutUIProps>(
</Button>
<ActionButton
variant="contained"
color={backupPassword ? 'error' : 'primary'}
color={!backupPassword && manageWallets.length ? 'primary' : 'error'}
fullWidth
onClick={onConfirm}
disabled={disabled}>
{backupPassword && manageWallets.length ? t('popups_log_out') : t('backup')}
{!backupPassword && manageWallets.length ? t('backup') : t('popups_log_out')}
</ActionButton>
</BottomController>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ async function resolveLastRecognizedIdentityInner(
cancel: AbortSignal,
) {
const assign = async () => {
const handle = selfInfoSelectors().handle.evaluate()
const avatar = selfInfoSelectors().avatar.evaluate()
const handle = selfInfoSelectors().handle
const avatar = selfInfoSelectors().avatar

ref.value = {
identifier: ProfileIdentifier.of(mindsBase.networkIdentifier, handle).unwrapOr(undefined),
Expand Down
9 changes: 3 additions & 6 deletions packages/mask/src/site-adaptors/minds.com/utils/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ export const postEditorDraftContentSelector = () => {
return querySelector<HTMLElement>('m-composer__modal m-composer__textarea textarea.m-composerTextarea__message')
}

export const handleSelector = () => querySelector<HTMLScriptElement>('.m-sidebarNavigation ul > li:nth-child(8) a span')
export const handleSelector = () => querySelector('.m-sidebarNavigation__item--user > a > div > span')

export const selfInfoSelectors = () => ({
handle: handleSelector().map((x) => x.innerText.replace(/@/, '').trim()),
avatar: querySelector<HTMLScriptElement>('.m-user-menu .minds-avatar').map((x) =>
// get everything between the parens (the url)
x.style.backgroundImage.match(/\((.*?)\)/)![1].replaceAll(/('|")/g, ''),
),
handle: handleSelector().evaluate()?.innerText.trim(),
avatar: querySelector<HTMLImageElement>('.m-sidebarNavigation__item--user > a > div > img').evaluate()?.src,
})

export const inpageAvatarSelector = () =>
Expand Down

0 comments on commit 93b1fc0

Please sign in to comment.