feat(vault): show mnemonic flow will show at first time ; or user reset vault state;
This commit is contained in:
@@ -25,6 +25,8 @@ import { VaultAsset, VaultAssetType, Heir } from '../types';
|
||||
import BiometricModal from '../components/common/BiometricModal';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { useVaultAssets } from '../hooks/useVaultAssets';
|
||||
import { VAULT_STORAGE_KEYS } from '../config';
|
||||
import { mnemonicToEntropy, splitSecret, serializeShare } from '../utils/sss';
|
||||
|
||||
// Asset type configuration with nautical theme
|
||||
const assetTypeConfig: Record<VaultAssetType, { icon: string; iconType: 'ionicons' | 'feather' | 'material' | 'fontawesome5'; label: string }> = {
|
||||
@@ -168,6 +170,7 @@ export default function VaultScreen() {
|
||||
const [accountProvider, setAccountProvider] = useState<'bank' | 'steam' | 'facebook' | 'custom'>('bank');
|
||||
const [showMnemonic, setShowMnemonic] = useState(false);
|
||||
const [showLegacyAssignCta, setShowLegacyAssignCta] = useState(false);
|
||||
const [hasS0, setHasS0] = useState<boolean | null>(null);
|
||||
const [mnemonicWords, setMnemonicWords] = useState<string[]>([]);
|
||||
const [mnemonicParts, setMnemonicParts] = useState<string[][]>([]);
|
||||
const [mnemonicStep, setMnemonicStep] = useState<1 | 2 | 3 | 4 | 5>(1);
|
||||
@@ -185,15 +188,31 @@ export default function VaultScreen() {
|
||||
const mnemonicRef = useRef<View>(null);
|
||||
const progressTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
// Detect S0 (TEE/SE): if present, later open shows biometric only; if not, mnemonic flow
|
||||
useEffect(() => {
|
||||
if (!isUnlocked) {
|
||||
const timer = setTimeout(() => {
|
||||
setShowBiometric(true);
|
||||
}, 500);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
let cancelled = false;
|
||||
AsyncStorage.getItem(VAULT_STORAGE_KEYS.SHARE_DEVICE)
|
||||
.then((v) => {
|
||||
if (!cancelled) setHasS0(!!v);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) setHasS0(false);
|
||||
});
|
||||
return () => { cancelled = true; };
|
||||
}, []);
|
||||
|
||||
// Only when S0 exists and vault not unlocked: show biometric after short delay.
|
||||
// When hasS0 is false or null, never show biometric — go straight to mnemonic flow.
|
||||
useEffect(() => {
|
||||
if (hasS0 !== true) {
|
||||
setShowBiometric(false);
|
||||
return;
|
||||
}
|
||||
if (isUnlocked) return;
|
||||
const timer = setTimeout(() => setShowBiometric(true), 500);
|
||||
return () => clearTimeout(timer);
|
||||
}, [isUnlocked, hasS0]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isUnlocked) {
|
||||
Animated.timing(fadeAnim, {
|
||||
@@ -335,28 +354,49 @@ export default function VaultScreen() {
|
||||
|
||||
const handleHeirDecision = (share: boolean) => {
|
||||
// Placeholder for future heir flow
|
||||
setShowMnemonic(false);
|
||||
setIsUnlocked(true);
|
||||
finishMnemonicThenShowBiometric();
|
||||
};
|
||||
|
||||
const handleSubmitAssignment = () => {
|
||||
// Placeholder for submitting assignment to API
|
||||
setShowMnemonic(false);
|
||||
setIsUnlocked(true);
|
||||
finishMnemonicThenShowBiometric();
|
||||
};
|
||||
|
||||
const handleHeirYes = () => {
|
||||
setShowMnemonic(false);
|
||||
setIsUnlocked(true);
|
||||
finishMnemonicThenShowBiometric();
|
||||
setShowLegacyAssignCta(true);
|
||||
};
|
||||
|
||||
const handleHeirNo = () => {
|
||||
setShowMnemonic(false);
|
||||
setIsUnlocked(true);
|
||||
finishMnemonicThenShowBiometric();
|
||||
setShowLegacyAssignCta(true);
|
||||
};
|
||||
|
||||
/** After mnemonic flow: persist S0 (simulated TEE/SE via AsyncStorage), then show biometric; unlock on success */
|
||||
const finishMnemonicThenShowBiometric = async () => {
|
||||
try {
|
||||
const wordList = bip39.wordlists.english;
|
||||
const entropy = mnemonicToEntropy(mnemonicWords, wordList);
|
||||
const shares = splitSecret(entropy);
|
||||
const s0 = shares[0]; // device share (S0)
|
||||
// S0 is stored in AsyncStorage under SHARE_DEVICE — app-level storage, not hardware TEE/SE
|
||||
await AsyncStorage.setItem(VAULT_STORAGE_KEYS.SHARE_DEVICE, serializeShare(s0));
|
||||
await AsyncStorage.setItem(VAULT_STORAGE_KEYS.INITIALIZED, '1');
|
||||
setHasS0(true);
|
||||
setShowMnemonic(false);
|
||||
setShowBiometric(true);
|
||||
} catch (e) {
|
||||
if (__DEV__) console.warn('finishMnemonicThenShowBiometric', e);
|
||||
setShowMnemonic(false);
|
||||
setShowBiometric(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBiometricSuccess = () => {
|
||||
setShowBiometric(false);
|
||||
setIsUnlocked(true);
|
||||
};
|
||||
|
||||
const handleOpenLegacyAssign = () => {
|
||||
setSelectedHeir(null);
|
||||
setSelectedHeirAsset(null);
|
||||
@@ -888,7 +928,7 @@ export default function VaultScreen() {
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.unlockButton}
|
||||
onPress={() => setShowBiometric(true)}
|
||||
onPress={hasS0 ? () => setShowBiometric(true) : handleUnlock}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<LinearGradient
|
||||
@@ -897,8 +937,10 @@ export default function VaultScreen() {
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
>
|
||||
<Ionicons name="finger-print" size={20} color={colors.vault.background} />
|
||||
<Text style={styles.unlockButtonText}>Captain's Verification</Text>
|
||||
<Ionicons name={hasS0 ? 'finger-print' : 'key'} size={20} color={colors.vault.background} />
|
||||
<Text style={styles.unlockButtonText}>
|
||||
{hasS0 === true ? "Captain's Verification" : hasS0 === false ? 'Enter Vault' : 'Loading…'}
|
||||
</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@@ -906,8 +948,8 @@ export default function VaultScreen() {
|
||||
</LinearGradient>
|
||||
|
||||
<BiometricModal
|
||||
visible={showBiometric}
|
||||
onSuccess={handleUnlock}
|
||||
visible={hasS0 === true && showBiometric}
|
||||
onSuccess={handleBiometricSuccess}
|
||||
onCancel={() => setShowBiometric(false)}
|
||||
title="Enter the Vault"
|
||||
message="Verify your identity to access your treasures"
|
||||
|
||||
Reference in New Issue
Block a user