added the option to change the wallet's password

This commit is contained in:
PhilReact 2025-04-26 10:34:15 +03:00
parent 9a227e4e53
commit 4e8eb3b2c3
10 changed files with 302 additions and 134 deletions

View File

@ -31,7 +31,13 @@
"return_to_list": "zurück zur Liste",
"wallet": {
"password_confirmation": "Wallet-Passwort bestätigen",
"password": "Wallet-Passwort"
"password": "Wallet-Passwort",
"keep_password": "aktuelles Passwort beibehalten",
"new_password": "neues Passwort",
"error": {
"missing_new_password": "bitte neues Passwort eingeben",
"missing_password": "bitte Passwort eingeben"
}
},
"welcome": "willkommen bei"
}

View File

@ -31,7 +31,13 @@
"return_to_list": "return to list",
"wallet": {
"password_confirmation": "confirm wallet password",
"password": "wallet password"
"password": "wallet password",
"keep_password": "keep current password",
"new_password": "new password",
"error": {
"missing_new_password": "please enter a new password",
"missing_password": "please enter your password"
}
},
"welcome": "welcome to"
}

View File

@ -31,7 +31,13 @@
"return_to_list": "volver a la lista",
"wallet": {
"password_confirmation": "confirmar contraseña del monedero",
"password": "contraseña del monedero"
"password": "contraseña del monedero",
"keep_password": "mantener la contraseña actual",
"new_password": "nueva contraseña",
"error": {
"missing_new_password": "por favor ingresa una nueva contraseña",
"missing_password": "por favor ingresa tu contraseña"
}
},
"welcome": "bienvenido a"
}

View File

@ -31,7 +31,13 @@
"return_to_list": "retour à la liste",
"wallet": {
"password_confirmation": "confirmer le mot de passe du portefeuille",
"password": "mot de passe du portefeuille"
"password": "mot de passe du portefeuille",
"keep_password": "garder le mot de passe actuel",
"new_password": "nouveau mot de passe",
"error": {
"missing_new_password": "veuillez entrer un nouveau mot de passe",
"missing_password": "veuillez entrer votre mot de passe"
}
},
"welcome": "bienvenue sur"
}

View File

@ -30,7 +30,13 @@
"password": "password",
"wallet": {
"password_confirmation": "conferma la password del wallet",
"password": "password del wallet"
"password": "password del wallet",
"keep_password": "mantieni la password attuale",
"new_password": "nuova password",
"error": {
"missing_new_password": "per favore inserisci una nuova password",
"missing_password": "per favore inserisci la tua password"
}
},
"return_to_list": "ritorna alla lista",
"welcome": "benvenuto in"

View File

@ -31,7 +31,13 @@
"return_to_list": "вернуться к списку",
"wallet": {
"password_confirmation": "подтвердите пароль кошелька",
"password": "пароль кошелька"
"password": "пароль кошелька",
"keep_password": "сохранить текущий пароль",
"new_password": "новый пароль",
"error": {
"missing_new_password": "пожалуйста, введите новый пароль",
"missing_password": "пожалуйста, введите ваш пароль"
}
},
"welcome": "добро пожаловать в"
}

View File

@ -137,6 +137,7 @@ import { GeneralNotifications } from './components/GeneralNotifications';
import { PdfViewer } from './common/PdfViewer';
import ThemeSelector from './components/Theme/ThemeSelector.tsx';
import { useTranslation } from 'react-i18next';
import { DownloadWallet } from './components/Auth/DownloadWallet.tsx';
type extStates =
| 'not-authenticated'
@ -919,27 +920,6 @@ function App() {
}
}, [authenticatedMode]);
const confirmPasswordToDownload = async () => {
try {
setWalletToBeDownloadedError('');
if (!walletToBeDownloadedPassword) {
setSendPaymentError('Please enter your password');
return;
}
setIsLoading(true);
await new Promise<void>((res) => {
setTimeout(() => {
res();
}, 250);
});
const res = await saveWalletFunc(walletToBeDownloadedPassword);
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
} finally {
setIsLoading(false);
}
};
const saveFileToDiskFunc = async () => {
try {
await saveFileToDisk(
@ -1676,7 +1656,7 @@ function App() {
textTransform: 'uppercase',
}}
>
{t('core:wallet_other')}
{t('core:wallet.wallet_other')}
</span>
}
placement="left"
@ -2692,110 +2672,14 @@ function App() {
</>
)}
{extState === 'download-wallet' && (
<>
<Spacer height="22px" />
<Box
sx={{
boxSizing: 'border-box',
display: 'flex',
justifyContent: 'flex-start',
maxWidth: '700px',
paddingLeft: '22px',
width: '100%',
}}
>
<Return
style={{
cursor: 'pointer',
height: '24px',
}}
onClick={returnToMain}
/>
</Box>
<Spacer height="10px" />
<div
className="image-container"
style={{
width: '136px',
height: '154px',
}}
>
<img src={Logo1Dark} className="base-image" />
</div>
<Spacer height="35px" />
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
}}
>
<TextP
sx={{
textAlign: 'start',
lineHeight: '24px',
fontSize: '20px',
fontWeight: 600,
}}
>
{t('auth:download_account', { postProcess: 'capitalize' })}
</TextP>
</Box>
<Spacer height="35px" />
{!walletToBeDownloaded && (
<>
<CustomLabel htmlFor="standard-adornment-password">
{t('auth:wallet.password_confirmation', {
postProcess: 'capitalize',
})}
</CustomLabel>
<Spacer height="5px" />
<PasswordField
id="standard-adornment-password"
value={walletToBeDownloadedPassword}
onChange={(e) =>
setWalletToBeDownloadedPassword(e.target.value)
}
/>
<Spacer height="20px" />
<CustomButton onClick={confirmPasswordToDownload}>
{t('auth:password_confirmation', {
postProcess: 'capitalize',
})}
</CustomButton>
<ErrorText>{walletToBeDownloadedError}</ErrorText>
</>
)}
{walletToBeDownloaded && (
<>
<CustomButton
onClick={async () => {
await saveFileToDiskFunc();
await showInfo({
message: t('auth:keep_secure', {
postProcess: 'capitalize',
}),
});
}}
>
{t('auth:download_account', {
postProcess: 'capitalize',
})}
</CustomButton>
</>
)}
</>
<DownloadWallet
returnToMain={returnToMain}
setIsLoading={setIsLoading}
showInfo={showInfo}
rawWallet={rawWallet}
setWalletToBeDownloaded={setWalletToBeDownloaded}
walletToBeDownloaded={walletToBeDownloaded}
/>
)}
{extState === 'create-wallet' && (
<>

View File

@ -703,7 +703,7 @@ export const NotAuthenticated = ({
visibility: importedApiKey ? 'visible' : 'hidden',
}}
>
{t('auth:apikey.key', { postProcess: 'capitalize' })}: $
{t('auth:apikey.key', { postProcess: 'capitalize' })}:{' '}
{importedApiKey}
</Typography>
</>

View File

@ -0,0 +1,248 @@
import { Box, Checkbox, FormControlLabel, Typography } from '@mui/material';
import { Spacer } from '../../common/Spacer';
import { Return } from '../../assets/Icons/Return';
import { CustomButton, CustomLabel, TextP } from '../../styles/App-styles';
import { PasswordField } from '../PasswordField/PasswordField';
import { ErrorText } from '../ErrorText/ErrorText';
import Logo1Dark from '../../assets/svgs/Logo1Dark.svg';
import { useTranslation } from 'react-i18next';
import { saveFileToDisk } from '../../utils/generateWallet/generateWallet';
import { useState } from 'react';
import { decryptStoredWallet } from '../../utils/decryptWallet';
import PhraseWallet from '../../utils/generateWallet/phrase-wallet';
import { crypto, walletVersion } from '../../constants/decryptWallet';
export const DownloadWallet = ({
returnToMain,
setIsLoading,
showInfo,
rawWallet,
setWalletToBeDownloaded,
walletToBeDownloaded,
}) => {
const [walletToBeDownloadedPassword, setWalletToBeDownloadedPassword] =
useState<string>('');
const [newPassword, setNewPassword] = useState<string>('');
const [keepCurrentPassword, setKeepCurrentPassword] = useState<boolean>(true);
const [walletToBeDownloadedError, setWalletToBeDownloadedError] =
useState<string>('');
const { t } = useTranslation(['auth']);
const saveFileToDiskFunc = async () => {
try {
await saveFileToDisk(
walletToBeDownloaded.wallet,
walletToBeDownloaded.qortAddress
);
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
}
};
const saveWalletFunc = async (password: string, newPassword) => {
let wallet = structuredClone(rawWallet);
const res = await decryptStoredWallet(password, wallet);
const wallet2 = new PhraseWallet(res, wallet?.version || walletVersion);
const passwordToUse = newPassword || password;
wallet = await wallet2.generateSaveWalletData(
passwordToUse,
crypto.kdfThreads,
() => {}
);
setWalletToBeDownloaded({
wallet,
qortAddress: rawWallet.address0,
});
return {
wallet,
qortAddress: rawWallet.address0,
};
};
const confirmPasswordToDownload = async () => {
try {
setWalletToBeDownloadedError('');
if (!keepCurrentPassword && !newPassword) {
setWalletToBeDownloadedError(
t('auth:wallet.error.missing_new_password', {
postProcess: 'capitalize',
})
);
return;
}
if (!walletToBeDownloadedPassword) {
setWalletToBeDownloadedError(
t('auth:wallet.error.missing_password', { postProcess: 'capitalize' })
);
return;
}
setIsLoading(true);
await new Promise<void>((res) => {
setTimeout(() => {
res();
}, 250);
});
const newPasswordForWallet = !keepCurrentPassword ? newPassword : null;
const res = await saveWalletFunc(
walletToBeDownloadedPassword,
newPasswordForWallet
);
} catch (error: any) {
setWalletToBeDownloadedError(error?.message);
} finally {
setIsLoading(false);
}
};
return (
<>
<Spacer height="22px" />
<Box
sx={{
boxSizing: 'border-box',
display: 'flex',
justifyContent: 'flex-start',
maxWidth: '700px',
paddingLeft: '22px',
width: '100%',
}}
>
<Return
style={{
cursor: 'pointer',
height: '24px',
}}
onClick={returnToMain}
/>
</Box>
<Spacer height="10px" />
<div
className="image-container"
style={{
width: '136px',
height: '154px',
}}
>
<img src={Logo1Dark} className="base-image" />
</div>
<Spacer height="35px" />
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
}}
>
<TextP
sx={{
textAlign: 'start',
lineHeight: '24px',
fontSize: '20px',
fontWeight: 600,
}}
>
{t('auth:download_account', { postProcess: 'capitalize' })}
</TextP>
</Box>
<Spacer height="35px" />
{!walletToBeDownloaded && (
<>
<CustomLabel htmlFor="standard-adornment-password">
{t('auth:wallet.password_confirmation', {
postProcess: 'capitalize',
})}
</CustomLabel>
<Spacer height="5px" />
<PasswordField
id="standard-adornment-password"
value={walletToBeDownloadedPassword}
onChange={(e) => setWalletToBeDownloadedPassword(e.target.value)}
/>
<Spacer height="20px" />
<FormControlLabel
sx={{
margin: 0,
}}
control={
<Checkbox
onChange={(e) => setKeepCurrentPassword(e.target.checked)}
checked={keepCurrentPassword}
edge="start"
tabIndex={-1}
disableRipple
/>
}
label={
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography sx={{ fontSize: '14px' }}>
{t('auth:wallet.keep_password', {
postProcess: 'capitalize',
})}
</Typography>
</Box>
}
/>
<Spacer height="20px" />
{!keepCurrentPassword && (
<>
<CustomLabel htmlFor="standard-adornment-password">
{t('auth:wallet.new_password', {
postProcess: 'capitalize',
})}
</CustomLabel>
<Spacer height="5px" />
<PasswordField
id="standard-adornment-password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
/>
<Spacer height="20px" />
</>
)}
<CustomButton onClick={confirmPasswordToDownload}>
{t('auth:password_confirmation', {
postProcess: 'capitalize',
})}
</CustomButton>
<ErrorText>{walletToBeDownloadedError}</ErrorText>
</>
)}
{walletToBeDownloaded && (
<>
<CustomButton
onClick={async () => {
await saveFileToDiskFunc();
await showInfo({
message: t('auth:keep_secure', {
postProcess: 'capitalize',
}),
});
}}
>
{t('auth:download_account', {
postProcess: 'capitalize',
})}
</CustomButton>
</>
)}
</>
);
};

View File

@ -124,7 +124,7 @@ export const Explore = ({ setDesktopViewMode }) => {
fontSize: '1rem',
}}
>
{t('core:wallet_other', { postProcess: 'capitalize' })}
{t('core:wallet.wallet_other', { postProcess: 'capitalize' })}
</Typography>
</ButtonBase>
</Box>