Skip to content

Commit 97e8b4a

Browse files
committed
chore: merge main and make enc wallet work with bio only
1 parent e2b535c commit 97e8b4a

File tree

6 files changed

+84
-46
lines changed

6 files changed

+84
-46
lines changed

src/lib/miden/back/actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export function decryptCiphertexts(accPublicKey: string, cipherTexts: string[])
158158

159159
export function revealViewKey(accPublicKey: string, password: string) {}
160160

161-
export function revealMnemonic(password: string) {
161+
export function revealMnemonic(password: string | undefined) {
162162
return withUnlocked(() => Vault.revealMnemonic(password));
163163
}
164164

src/lib/miden/back/vault.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,19 @@ export class Vault {
190190
}
191191
}
192192

193+
private static async getVaultKey(password?: string): Promise<CryptoKey> {
194+
// If password is not provided, try hardware unlock first
195+
if (!password) {
196+
const vault = await Vault.tryHardwareUnlock();
197+
if (vault) {
198+
return vault.vaultKey;
199+
}
200+
throw new PublicError('Password required');
201+
}
202+
// Password-based unlock
203+
return Vault.unlockWithPassword(password);
204+
}
205+
193206
/**
194207
* Legacy password unlock for wallets created before vault key model
195208
* This maintains backward compatibility with existing wallets
@@ -525,8 +538,8 @@ export class Vault {
525538

526539
async revealViewKey(accPublicKey: string) {}
527540

528-
static async revealMnemonic(password: string) {
529-
const vaultKey = await Vault.unlockWithPassword(password);
541+
static async revealMnemonic(password: string | undefined) {
542+
const vaultKey = await Vault.getVaultKey(password);
530543
return withError('Failed to reveal seed phrase', async () => {
531544
const mnemonic = await fetchAndDecryptOneWithLegacyFallBack<string>(mnemonicStrgKey, vaultKey);
532545
const mnemonicPattern = /^(\b\w+\b\s?){12}$/;

src/lib/miden/front/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export const [MidenContextProvider, useMidenContext] = constate(() => {
135135
);
136136

137137
const revealMnemonic = useCallback(
138-
async (password: string) => {
138+
async (password: string | undefined) => {
139139
return storeRevealMnemonic(password);
140140
},
141141
[storeRevealMnemonic]

src/lib/store/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export interface WalletActions {
108108
createAccount: (walletType: WalletType, name?: string) => Promise<void>;
109109
updateCurrentAccount: (accountPublicKey: string) => Promise<void>;
110110
editAccountName: (accountPublicKey: string, name: string) => Promise<void>;
111-
revealMnemonic: (password: string) => Promise<string>;
111+
revealMnemonic: (password: string | undefined) => Promise<string>;
112112

113113
// Settings actions
114114
updateSettings: (newSettings: Partial<WalletSettings>) => Promise<void>;

src/screens/encrypted-file-flow/EncryptedWalletFileWalletPassword.tsx

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useMemo, useState } from 'react';
1+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
22

33
import { useForm } from 'react-hook-form';
44
import { useTranslation } from 'react-i18next';
@@ -58,6 +58,22 @@ const EncryptedWalletFileWalletPassword: React.FC<EncryptedWalletFileWalletPassw
5858
const onPasswordVisibilityToggle = useCallback(() => {
5959
setIsPasswordVisible(prev => !prev);
6060
}, []);
61+
const [loading, setLoading] = useState(true);
62+
const [showPassword, setShowPassword] = useState(false);
63+
64+
useEffect(() => {
65+
const checkIfPasswordShouldBeShown = async () => {
66+
try {
67+
const { Vault } = await import('lib/miden/back/vault');
68+
setShowPassword(await Vault.hasPasswordProtector());
69+
} catch (e) {
70+
console.error('Error checking vault password protector:', e);
71+
} finally {
72+
setLoading(false);
73+
}
74+
};
75+
checkIfPasswordShouldBeShown();
76+
}, []);
6177

6278
const [timeleft, setTimeleft] = useState(getTimeLeft(timelock, lockLevel));
6379

@@ -69,7 +85,7 @@ const EncryptedWalletFileWalletPassword: React.FC<EncryptedWalletFileWalletPassw
6985
clearErrors('password');
7086
try {
7187
if (attempt > LAST_ATTEMPT) await new Promise(res => setTimeout(res, Math.random() * 2000 + 1000));
72-
await unlock(walletPassword!);
88+
await unlock(walletPassword);
7389

7490
setAttempt(1);
7591
onGoNext();
@@ -100,49 +116,59 @@ const EncryptedWalletFileWalletPassword: React.FC<EncryptedWalletFileWalletPassw
100116
<div className="flex-1 flex flex-col">
101117
<NavigationHeader title={t('encryptedWalletFile')} onBack={goBack} mode="back" />
102118
<div className="flex flex-col flex-1 p-4 md:w-[460px] md:mx-auto">
103-
<div className="flex-1 flex flex-col justify-stretch gap-y-4">
104-
<p className="text-sm">{t('encryptedWalletFileDescription')}</p>
105-
<div className="flex flex-col gap-y-2">
106-
<Input
107-
type={isPasswordVisible ? 'text' : 'password'}
108-
label={t('password')}
109-
value={walletPassword}
110-
disabled={isDisabled}
111-
placeholder={t('enterPassword')}
112-
icon={
113-
<button className="flex-1" onClick={onPasswordVisibilityToggle}>
114-
<Icon name={isPasswordVisible ? IconName.EyeOff : IconName.Eye} fill="black" />
115-
</button>
116-
}
117-
onChange={onPasswordChange}
118-
onKeyDown={handleEnterKey}
119-
autoFocus
120-
/>
121-
{errors.password && <p className="h-4 text-red-500 text-xs">{errors.password.message}</p>}
119+
{loading ? (
120+
<div className="flex-1 flex items-center justify-center">
121+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
122122
</div>
123-
<div className="flex gap-x-2 text-sm text-left">
124-
<button className="flex mt-3 gap-x-2 text-left" onClick={() => setConfirmed(!confirmed)}>
125-
<Checkbox id="help-us" value={confirmed} />
126-
<span className="text-black cursor-pointer text-left mt-[-4px]">
127-
{t('encryptedWalletFileConfirmation')}
128-
</span>
129-
</button>
123+
) : (
124+
<div className="flex-1 flex flex-col justify-stretch gap-y-4">
125+
<p className="text-sm">{t('encryptedWalletFileDescription')}</p>
126+
<div className="flex flex-col gap-y-2">
127+
{showPassword && (
128+
<>
129+
<Input
130+
type={isPasswordVisible ? 'text' : 'password'}
131+
label={t('password')}
132+
value={walletPassword}
133+
disabled={isDisabled}
134+
placeholder={t('enterPassword')}
135+
icon={
136+
<button className="flex-1" onClick={onPasswordVisibilityToggle}>
137+
<Icon name={isPasswordVisible ? IconName.EyeOff : IconName.Eye} fill="black" />
138+
</button>
139+
}
140+
onChange={onPasswordChange}
141+
onKeyDown={handleEnterKey}
142+
autoFocus
143+
/>
144+
{errors.password && <p className="h-4 text-red-500 text-xs">{errors.password.message}</p>}
145+
</>
146+
)}
147+
</div>
148+
<div className="flex gap-x-2 text-sm text-left">
149+
<button className="flex mt-3 gap-x-2 text-left" onClick={() => setConfirmed(!confirmed)}>
150+
<Checkbox id="help-us" value={confirmed} />
151+
<span className="text-black cursor-pointer text-left mt-[-4px]">
152+
{t('encryptedWalletFileConfirmation')}
153+
</span>
154+
</button>
155+
</div>
156+
{isDisabled && (
157+
<Alert
158+
type="error"
159+
title={t('error')}
160+
description={`${t('unlockPasswordErrorDelay')} ${timeleft}`}
161+
className="mt-8 rounded-lg text-black mx-auto"
162+
style={{ width: '80%' }}
163+
/>
164+
)}
130165
</div>
131-
{isDisabled && (
132-
<Alert
133-
type="error"
134-
title={t('error')}
135-
description={`${t('unlockPasswordErrorDelay')} ${timeleft}`}
136-
className="mt-8 rounded-lg text-black mx-auto"
137-
style={{ width: '80%' }}
138-
/>
139-
)}
140-
</div>
166+
)}
141167
<Button
142168
className="w-full justify-center mt-6"
143169
variant={ButtonVariant.Primary}
144170
title={t('continue')}
145-
disabled={isDisabled || !confirmed}
171+
disabled={isDisabled || !confirmed || loading}
146172
onClick={onSubmit}
147173
isLoading={isSubmitting}
148174
/>

src/screens/encrypted-file-flow/ExportFileComplete.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface ExportFileCompleteProps {
2121
onDone: () => void;
2222
filePassword: string;
2323
fileName: string;
24-
walletPassword: string;
24+
walletPassword?: string;
2525
}
2626

2727
const EXTENSION = '.json';
@@ -36,7 +36,6 @@ const ExportFileComplete: React.FC<ExportFileCompleteProps> = ({
3636
const { t } = useTranslation();
3737
const { revealMnemonic, accounts } = useMidenContext();
3838
const { fullPage } = useAppEnv();
39-
4039
const getExportFile = useCallback(async () => {
4140
// Wrap WASM client operations in a lock to prevent concurrent access
4241
const midenClientDbDump = await withWasmClientLock(async () => {

0 commit comments

Comments
 (0)