/* global alert */ import React, { useState, useEffect } from 'react'; import { Text, ScrollView, ActivityIndicator, Keyboard, KeyboardAvoidingView, Platform, View, StatusBar, TextInput, StyleSheet, } from 'react-native'; import AsyncStorage from '@react-native-community/async-storage'; import { BlueTextCenteredHooks, BlueTextHooks, BlueListItem, LightningButton, BitcoinButton, BlueFormLabel, BlueButtonHook, BlueNavigationStyle, BlueButtonLinkHook, BlueSpacing20, } from '../../BlueComponents'; import { HDSegwitBech32Wallet, SegwitP2SHWallet, HDSegwitP2SHWallet, LightningCustodianWallet, AppStorage } from '../../class'; import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; import { useTheme, useNavigation } from '@react-navigation/native'; import { Chain } from '../../models/bitcoinUnits'; import loc from '../../loc'; const EV = require('../../blue_modules/events'); const A = require('../../blue_modules/analytics'); const BlueApp: AppStorage = require('../../BlueApp'); const styles = StyleSheet.create({ loading: { flex: 1, paddingTop: 20, }, label: { flexDirection: 'row', borderWidth: 1, borderBottomWidth: 0.5, minHeight: 44, height: 44, marginHorizontal: 20, alignItems: 'center', marginVertical: 16, borderRadius: 4, }, textInputCommon: { flex: 1, marginHorizontal: 8, color: '#81868e', }, buttons: { flexDirection: 'row', justifyContent: 'space-between', paddingTop: 10, marginHorizontal: 20, borderWidth: 0, minHeight: 100, }, button: { width: '45%', height: 88, }, or: { borderWidth: 0, justifyContent: 'center', marginHorizontal: 8, alignSelf: 'center', }, orCenter: { color: '#0c2550', }, advanced: { marginHorizontal: 20, }, advancedText: { fontWeight: '500', }, lndUri: { flexDirection: 'row', borderWidth: 1, borderBottomWidth: 0.5, minHeight: 44, height: 44, alignItems: 'center', marginVertical: 16, borderRadius: 4, }, createButton: { flex: 1, marginTop: 32, }, import: { marginBottom: 0, marginTop: 24, }, noPadding: { paddingHorizontal: 0, }, }); const WalletsAdd = () => { const { colors } = useTheme(); const [isLoading, setIsLoading] = useState(true); const [walletBaseURI, setWalletBaseURI] = useState(); const [selectedIndex, setSelectedIndex] = useState(0); const [label, setLabel] = useState(''); const [isAdvancedOptionsEnabled, setIsAdvancedOptionsEnabled] = useState(false); const [selectedWalletType, setSelectedWalletType] = useState(false); const { navigate, goBack } = useNavigation(); const [entropy, setEntropy] = useState(); const [entropyButtonText, setEntropyButtonText] = useState(loc.wallets.add_entropy_provide); const stylesHook = { advancedText: { color: colors.feeText, }, label: { borderColor: colors.formBorder, borderBottomColor: colors.formBorder, backgroundColor: colors.inputBackgroundColor, }, noPadding: { backgroundColor: colors.elevated, }, root: { backgroundColor: colors.elevated, }, lndUri: { borderColor: colors.formBorder, borderBottomColor: colors.formBorder, backgroundColor: colors.inputBackgroundColor, }, }; useEffect(() => { AsyncStorage.getItem(AppStorage.LNDHUB) .then(setWalletBaseURI) .catch(() => setWalletBaseURI('')); BlueApp.isAdancedModeEnabled() .then(setIsAdvancedOptionsEnabled) .finally(() => setIsLoading(false)); }, [isAdvancedOptionsEnabled]); const entropyGenerated = newEntropy => { let entropyTitle; if (!newEntropy) { entropyTitle = loc.wallets.add_entropy_provide; } else if (newEntropy.length < 32) { entropyTitle = loc.formatString(loc.wallets.add_entropy_remain, { gen: newEntropy.length, rem: 32 - newEntropy.length, }); } else { entropyTitle = loc.formatString(loc.wallets.add_entropy_generated, { gen: newEntropy.length, }); } setEntropy(newEntropy); setEntropyButtonText(entropyTitle); }; const createWallet = async () => { setIsLoading(true); let w; if (selectedWalletType === Chain.OFFCHAIN) { createLightningWallet(w); } else if (selectedWalletType === Chain.ONCHAIN) { if (selectedIndex === 2) { // zero index radio - HD segwit w = new HDSegwitP2SHWallet(); w.setLabel(label || loc.wallets.details_title); } else if (selectedIndex === 1) { // btc was selected // index 1 radio - segwit single address w = new SegwitP2SHWallet(); w.setLabel(label || loc.wallets.details_title); } else { // btc was selected // index 2 radio - hd bip84 w = new HDSegwitBech32Wallet(); w.setLabel(label || loc.wallets.details_title); } if (selectedWalletType === Chain.ONCHAIN) { if (entropy) { try { await w.generateFromEntropy(entropy); } catch (e) { console.log(e.toString()); alert(e.toString()); goBack(); return; } } else { await w.generate(); } BlueApp.wallets.push(w); await BlueApp.saveToDisk(); setTimeout(() => EV(EV.enum.WALLETS_COUNT_CHANGED), 500); // heavy task; hopefully will be executed while user is staring at backup screen A(A.ENUM.CREATED_WALLET); ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); if (w.type === HDSegwitP2SHWallet.type || w.type === HDSegwitBech32Wallet.type) { navigate('PleaseBackup', { secret: w.getSecret(), }); } else { goBack(); } } } }; const createLightningWallet = async wallet => { wallet = new LightningCustodianWallet(); wallet.setLabel(label || loc.wallets.details_title); try { const lndhub = walletBaseURI && walletBaseURI.trim().length > 0 ? walletBaseURI : LightningCustodianWallet.defaultBaseUri; if (lndhub) { const isValidNodeAddress = await LightningCustodianWallet.isValidNodeAddress(lndhub); if (isValidNodeAddress) { wallet.setBaseURI(lndhub); wallet.init(); } else { throw new Error('The provided node address is not valid LNDHub node.'); } } await wallet.createAccount(); await wallet.authorize(); } catch (Err) { setIsLoading(false); console.warn('lnd create failure', Err); return alert(Err); // giving app, not adding anything } A(A.ENUM.CREATED_LIGHTNING_WALLET); await wallet.generate(); BlueApp.wallets.push(wallet); await BlueApp.saveToDisk(); EV(EV.enum.WALLETS_COUNT_CHANGED); A(A.ENUM.CREATED_WALLET); ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); navigate('PleaseBackupLNDHub', { wallet, }); }; const navigateToEntropy = () => { navigate('ProvideEntropy', { onGenerated: entropyGenerated }); }; const navigateToImportWallet = () => { navigate('ImportWallet'); }; const handleOnBitcoinButtonPressed = () => { Keyboard.dismiss(); setSelectedWalletType(Chain.ONCHAIN); }; const handleOnLightningButtonPressed = () => { Keyboard.dismiss(); setSelectedWalletType(Chain.OFFCHAIN); }; return ( {loc.wallets.add_wallet_name} {loc.wallets.add_wallet_type} {loc.wallets.add_or} {(() => { if (selectedWalletType === Chain.ONCHAIN && isAdvancedOptionsEnabled) { return ( {loc.settings.advanced_options} setSelectedIndex(0)} title={HDSegwitBech32Wallet.typeReadable} {...(selectedIndex === 0 ? { rightIcon: { name: 'check', type: 'octaicon', color: '#0070FF' }, } : { hideChevron: true })} /> setSelectedIndex(1)} title={SegwitP2SHWallet.typeReadable} {...(selectedIndex === 1 ? { rightIcon: { name: 'check', type: 'octaicon', color: '#0070FF' }, } : { hideChevron: true })} /> setSelectedIndex(2)} title={HDSegwitP2SHWallet.typeReadable} {...(selectedIndex === 2 ? { rightIcon: { name: 'check', type: 'octaicon', color: '#0070FF' }, } : { hideChevron: true })} /> ); } else if (selectedWalletType === Chain.OFFCHAIN && isAdvancedOptionsEnabled) { return ( <> {loc.settings.advanced_options} Connect to your LNDHub ); } })()} {!isLoading ? ( ) : ( )} {!isLoading && ( )} {isAdvancedOptionsEnabled && !isLoading && ( )} ); }; WalletsAdd.navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), headerTitle: loc.wallets.add_title, headerLeft: null, }); export default WalletsAdd;