diff --git a/CHANGELOG.md b/CHANGELOG.md index 568fd125..03dc171e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### vNext - Added multi-chain signature API to the wallet client and SDK +- Let users enter an encryption password during account export ### v1.37.0 diff --git a/packages/ui/src/theme/index.ts b/packages/ui/src/theme/index.ts index f336b3d6..73cd22ce 100644 --- a/packages/ui/src/theme/index.ts +++ b/packages/ui/src/theme/index.ts @@ -203,6 +203,22 @@ export const createTheme = ({ whiteLabel, isGame }: any = {}): Theme => { }, styleOverrides: { + root: ({ theme, ownerState: props }) => { + const color = props.color === 'inherit' ? undefined : theme.palette[props.color || 'primary']; + const disabledColor = color && alpha(color.main, theme.palette.action.disabledOpacity); + const textColor = color && color.contrastText; + + return ( + color && { + '&.Mui-disabled': { + borderColor: disabledColor, + backgroundColor: props.variant === 'contained' ? disabledColor : undefined, + color: props.variant === 'contained' ? textColor : color?.main, + }, + } + ); + }, + contained: { backgroundColor: isGame && '#F32758', borderRadius: isGame ? 4 : 30, diff --git a/src/routes/Settings/Settings.tsx b/src/routes/Settings/Settings.tsx index d55749ca..9537f468 100644 --- a/src/routes/Settings/Settings.tsx +++ b/src/routes/Settings/Settings.tsx @@ -10,6 +10,7 @@ import { Typography, styled, useIsMobile, + TextField, } from '@cere-wallet/ui'; import { useEffect, useState } from 'react'; @@ -24,17 +25,37 @@ const SectionHeader = styled(CardHeader)({ const SectionButton = styled(Button)({ minWidth: 250, - height: 44, + whiteSpace: 'nowrap', + height: 42, }) as typeof Button; +const downloadFile = (url: string, filename: string) => { + const link = document.createElement('a'); + + link.href = url; + link.download = filename; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + // Clean up by revoking the Blob URL + URL.revokeObjectURL(url); +}; + export const Settings = () => { const isMobile = useIsMobile(); const accountStore = useAccountStore(); const authenticationStore = useAuthenticationStore(); const { accountUrl } = useOpenLoginStore(); const [accountLink, setAccountLink] = useState(); - const walletDownloadUrl = accountStore.exportAccount('ed25519'); const cereAddress = accountStore.getAccount('ed25519')?.address; + const [exportPassword, setExportPassword] = useState(''); + + const handleExportAccount = () => { + downloadFile(accountStore.exportAccount('ed25519', exportPassword), `${cereAddress}.json`); + setExportPassword(''); + }; useEffect(() => { authenticationStore @@ -74,7 +95,7 @@ export const Settings = () => { @@ -82,21 +103,37 @@ export const Settings = () => { } /> - + + + This downloadable file lets you restore your account or use it with Cere Tools, even if you can't + connect directly to Cere Wallet. To ensure maximum security, the file will be encrypted with a password + you create. + + - JSON backup file lets you restore your account or use it with Cere Tools, even if a direct connection to - Cere Wallet isn't available. Please keep it confidential and don't share it with third parties. + Please keep your password confidential and do not share it with anyone. Sharing your password could + compromise your account security. - - Download - + + setExportPassword(event.target.value)} + /> + + + Export Account + + diff --git a/src/stores/AccountStore/AccountStore.ts b/src/stores/AccountStore/AccountStore.ts index 09f9cb93..a77bd7b1 100644 --- a/src/stores/AccountStore/AccountStore.ts +++ b/src/stores/AccountStore/AccountStore.ts @@ -63,9 +63,6 @@ export class AccountStore { throw new Error('No private key found!'); } - /** - * TODO: Implement passphrase UI to not hardcode it here to be empty string ('') - */ const keyData = exportAccountToJson({ privateKey: this.privateKey, type, passphrase: passphrase || '' }); const accountBlob = new Blob([JSON.stringify(keyData)], { type: 'application/json',