IdentityNew.tsx 5.45 KB
Newer Older
Hanwen Cheng's avatar
Hanwen Cheng committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

17
import React, { useContext, useEffect, useRef, useState } from 'react';
18
import { StyleSheet, View } from 'react-native';
Hanwen Cheng's avatar
Hanwen Cheng committed
19

20
import { KeyboardAwareContainer } from 'modules/unlock/components/Container';
21
import testIDs from 'e2e/testIDs';
22
23
import { AccountsContext } from 'stores/AccountsContext';
import { AlertStateContext } from 'stores/alertContext';
24
25
import Button from 'components/Button';
import TextInput from 'components/TextInput';
26
import { NavigationProps } from 'types/props';
27
28
29
30
31
import { emptyIdentity } from 'utils/identitiesUtils';
import colors from 'styles/colors';
import { validateSeed } from 'utils/account';
import AccountSeed from 'components/AccountSeed';
import { navigateToNewIdentityNetwork, setPin } from 'utils/navigationHelpers';
32
import {
33
	alertError,
34
35
	alertIdentityCreationError,
	alertRisks
36
37
38
39
} from 'utils/alertUtils';
import ScreenHeading from 'components/ScreenHeading';
import { brainWalletAddress } from 'utils/native';
import { debounce } from 'utils/debounce';
40
import { useNewSeedRef } from 'utils/seedRefHooks';
Hanwen Cheng's avatar
Hanwen Cheng committed
41

42
function IdentityNew({
43
44
	navigation,
	route
45
46
}: NavigationProps<'IdentityNew'>): React.ReactElement {
	const accountsStore = useContext(AccountsContext);
47
	const defaultSeedValidObject = validateSeed('', false);
48
	const isRecoverDefaultValue = route.params?.isRecover ?? false;
Hanwen Cheng's avatar
Hanwen Cheng committed
49
	const [isRecover, setIsRecover] = useState(isRecoverDefaultValue);
50
	const [isSeedValid, setIsSeedValid] = useState(defaultSeedValidObject);
Hanwen Cheng's avatar
Hanwen Cheng committed
51
	const [seedPhrase, setSeedPhrase] = useState('');
52
	const { setAlert } = useContext(AlertStateContext);
53
	const createSeedRefWithNewSeed = useNewSeedRef();
54
55
56
	const clearIdentity = useRef(() =>
		accountsStore.updateNewIdentity(emptyIdentity())
	);
Hanwen Cheng's avatar
Hanwen Cheng committed
57

58
	useEffect((): (() => void) => {
59
60
61
		clearIdentity.current();
		return clearIdentity.current;
	}, [clearIdentity]);
Hanwen Cheng's avatar
Hanwen Cheng committed
62

63
	const updateName = (name: string): void => {
64
		accountsStore.updateNewIdentity({ name });
Hanwen Cheng's avatar
Hanwen Cheng committed
65
66
	};

67
	const onSeedTextInput = (inputSeedPhrase: string): void => {
68
		setSeedPhrase(inputSeedPhrase);
69
		const addressGeneration = (): Promise<void> =>
70
			brainWalletAddress(inputSeedPhrase.trimEnd())
71
72
73
				.then(({ bip39 }) => {
					setIsSeedValid(validateSeed(inputSeedPhrase, bip39));
				})
74
				.catch(() => setIsSeedValid(defaultSeedValidObject));
75
76
77
78
		const debouncedAddressGeneration = debounce(addressGeneration, 200);
		debouncedAddressGeneration();
	};

79
	const onRecoverIdentity = async (): Promise<void> => {
Hanwen Cheng's avatar
Hanwen Cheng committed
80
81
		const pin = await setPin(navigation);
		try {
82
			if (isSeedValid.bip39) {
83
				await accountsStore.saveNewIdentity(
84
85
86
87
					seedPhrase.trimEnd(),
					pin,
					createSeedRefWithNewSeed
				);
88
			} else {
89
				await accountsStore.saveNewIdentity(
90
91
92
93
					seedPhrase,
					pin,
					createSeedRefWithNewSeed
				);
94
			}
Hanwen Cheng's avatar
Hanwen Cheng committed
95
96
97
			setSeedPhrase('');
			navigateToNewIdentityNetwork(navigation);
		} catch (e) {
98
			alertIdentityCreationError(setAlert, e.message);
Hanwen Cheng's avatar
Hanwen Cheng committed
99
100
101
		}
	};

102
	const onRecoverConfirm = (): void | Promise<void> => {
103
104
		if (!isSeedValid.valid) {
			if (isSeedValid.accountRecoveryAllowed) {
105
				return alertRisks(setAlert, `${isSeedValid.reason}`, onRecoverIdentity);
106
			} else {
107
				return alertError(setAlert, `${isSeedValid.reason}`);
108
109
110
111
112
			}
		}
		return onRecoverIdentity();
	};

113
	const onCreateNewIdentity = (): void => {
Hanwen Cheng's avatar
Hanwen Cheng committed
114
115
116
117
118
119
		setSeedPhrase('');
		navigation.navigate('IdentityBackup', {
			isNew: true
		});
	};

120
	const renderRecoverView = (): React.ReactElement => (
Hanwen Cheng's avatar
Hanwen Cheng committed
121
122
123
		<>
			<AccountSeed
				testID={testIDs.IdentityNew.seedInput}
124
				onChangeText={onSeedTextInput}
125
126
127
				onSubmitEditing={onRecoverConfirm}
				returnKeyType="done"
				valid={isSeedValid.valid}
Hanwen Cheng's avatar
Hanwen Cheng committed
128
129
130
			/>
			<View style={styles.btnBox}>
				<Button
131
132
133
134
135
136
137
					title="Recover"
					testID={testIDs.IdentityNew.recoverButton}
					onPress={onRecoverConfirm}
					small={true}
				/>
				<Button
					title="or create new identity"
138
					onPress={(): void => {
Hanwen Cheng's avatar
Hanwen Cheng committed
139
140
141
142
143
144
145
146
147
						setIsRecover(false);
					}}
					small={true}
					onlyText={true}
				/>
			</View>
		</>
	);

148
	const renderCreateView = (): React.ReactElement => (
Hanwen Cheng's avatar
Hanwen Cheng committed
149
150
151
152
153
154
155
		<View style={styles.btnBox}>
			<Button
				title="Create"
				testID={testIDs.IdentityNew.createButton}
				onPress={onCreateNewIdentity}
				small={true}
			/>
156
157
158
159
160
161
			<Button
				title="or recover existing identity"
				onPress={(): void => setIsRecover(true)}
				small={true}
				onlyText={true}
			/>
Hanwen Cheng's avatar
Hanwen Cheng committed
162
163
164
165
		</View>
	);

	return (
166
		<KeyboardAwareContainer>
Hanwen Cheng's avatar
Hanwen Cheng committed
167
168
169
170
			<ScreenHeading title={'New Identity'} />
			<TextInput
				onChangeText={updateName}
				testID={testIDs.IdentityNew.nameInput}
171
				value={accountsStore.state.newIdentity.name}
Hanwen Cheng's avatar
Hanwen Cheng committed
172
173
174
				placeholder="Identity Name"
			/>
			{isRecover ? renderRecoverView() : renderCreateView()}
175
		</KeyboardAwareContainer>
Hanwen Cheng's avatar
Hanwen Cheng committed
176
177
178
	);
}

179
export default IdentityNew;
Hanwen Cheng's avatar
Hanwen Cheng committed
180
181
182

const styles = StyleSheet.create({
	body: {
183
		backgroundColor: colors.background.app,
Hanwen Cheng's avatar
Hanwen Cheng committed
184
185
186
187
188
189
190
191
		flex: 1,
		overflow: 'hidden'
	},
	btnBox: {
		alignContent: 'center',
		marginTop: 32
	}
});