import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useRoute } from '@react-navigation/native'; import { ActivityIndicator, FlatList, LayoutAnimation, StyleSheet, View } from 'react-native'; import IdleTimerManager from 'react-native-idle-timer'; import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback'; import { BlueButtonLink, BlueFormLabel, BlueSpacing10, BlueSpacing20 } from '../../BlueComponents'; import { HDSegwitBech32Wallet } from '../../class'; import startImport from '../../class/wallet-import'; import presentAlert from '../../components/Alert'; import Button from '../../components/Button'; import SafeArea from '../../components/SafeArea'; import { useTheme } from '../../components/themes'; import WalletToImport from '../../components/WalletToImport'; import prompt from '../../helpers/prompt'; import loc from '../../loc'; import { useExtendedNavigation } from '../../hooks/useExtendedNavigation'; import { useStorage } from '../../hooks/context/useStorage'; const ImportWalletDiscovery = () => { const navigation = useExtendedNavigation(); const { colors } = useTheme(); const route = useRoute(); const { importText, askPassphrase, searchAccounts } = route.params; const task = useRef(); const { addAndSaveWallet } = useStorage(); const [loading, setLoading] = useState(true); const [wallets, setWallets] = useState([]); const [password, setPassword] = useState(); const [selected, setSelected] = useState(0); const [progress, setProgress] = useState(); const importing = useRef(false); const bip39 = useMemo(() => { const hd = new HDSegwitBech32Wallet(); hd.setSecret(importText); return hd.validateMnemonic(); }, [importText]); const stylesHook = StyleSheet.create({ root: { backgroundColor: colors.elevated, }, center: { backgroundColor: colors.elevated, }, }); const saveWallet = wallet => { if (importing.current) return; importing.current = true; addAndSaveWallet(wallet); navigation.getParent().pop(); }; useEffect(() => { const onProgress = data => setProgress(data); const onWallet = wallet => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); const id = wallet.getID(); let subtitle; try { subtitle = wallet.getDerivationPath?.(); } catch (e) {} setWallets(w => [...w, { wallet, subtitle, id }]); }; const onPassword = async (title, subtitle) => { try { const pass = await prompt(title, subtitle); setPassword(pass); return pass; } catch (e) { if (e.message === 'Cancel Pressed') { navigation.goBack(); } throw e; } }; IdleTimerManager.setIdleTimerDisabled(true); task.current = startImport(importText, askPassphrase, searchAccounts, onProgress, onWallet, onPassword); task.current.promise .then(({ cancelled, wallets: w }) => { if (cancelled) return; if (w.length === 1) saveWallet(w[0]); // instantly save wallet if only one has been discovered if (w.length === 0) { triggerHapticFeedback(HapticFeedbackTypes.ImpactLight); } }) .catch(e => { console.warn('import error', e); presentAlert({ title: 'Import error', message: e.message }); }) .finally(() => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); setLoading(false); IdleTimerManager.setIdleTimerDisabled(false); }); return () => task.current.stop(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleCustomDerivation = () => { task.current.stop(); navigation.navigate('ImportCustomDerivationPath', { importText, password }); }; const renderItem = ({ item, index }) => ( { setSelected(index); triggerHapticFeedback(HapticFeedbackTypes.Selection); }} /> ); const keyExtractor = w => w.id; return ( {loc.wallets.import_discovery_subtitle} {!loading && wallets.length === 0 ? ( {loc.wallets.import_discovery_no_wallets} ) : ( )} {loading && ( <> {progress} )} {bip39 && ( )}