PathDerivation.tsx 4.91 KB
Newer Older
Hanwen Cheng's avatar
Hanwen Cheng committed
// 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/>.

import React, { useRef, useState, useMemo } from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';

import testIDs from 'e2e/testIDs';
import { defaultNetworkKey, UnknownNetworkKeys } from 'constants/networkSpecs';
import { NavigationAccountProps } from 'types/props';
import { withAccountStore } from 'utils/HOC';
import TextInput from 'components/TextInput';
import ButtonMainAction from 'components/ButtonMainAction';
import { getNetworkKey, validateDerivedPath } from 'utils/identitiesUtils';
import { navigateToPathsList, unlockSeedPhrase } from 'utils/navigationHelpers';
import { alertPathDerivationError } from 'utils/alertUtils';
import Separator from 'components/Separator';
import ScreenHeading from 'components/ScreenHeading';
import colors from 'styles/colors';
import PathCard from 'components/PathCard';
import KeyboardScrollView from 'components/KeyboardScrollView';
import { NetworkSelector, NetworkOptions } from 'components/NetworkSelector';
function PathDerivation({
	accounts,
	navigation,
	route
}: NavigationAccountProps<'PathDerivation'>): React.ReactElement {
	const [derivationPath, setDerivationPath] = useState('');
	const [keyPairsName, setKeyPairsName] = useState('');
	const [isPathValid, setIsPathValid] = useState(true);
	const [modalVisible, setModalVisible] = useState(false);
	const pathNameInput = useRef<TextInput>(null);
	const parentPath = route.params.parentPath;
	const parentNetworkKey = useMemo(
		() => getNetworkKey(parentPath, accounts.state.currentIdentity!),
		[parentPath, accounts.state.currentIdentity]
	);

	const [customNetworkKey, setCustomNetworkKey] = useState(
		parentNetworkKey === UnknownNetworkKeys.UNKNOWN
			? defaultNetworkKey
	const completePath = `${parentPath}${derivationPath}`;
	const enableCustomNetwork = parentPath === '';
	const currentNetworkKey = enableCustomNetwork
		? customNetworkKey
		: parentNetworkKey;
	const onPathDerivation = async (): Promise<void> => {
Hanwen Cheng's avatar
Hanwen Cheng committed
		if (!validateDerivedPath(derivationPath)) {
			return setIsPathValid(false);
		}
		const seedPhrase = await unlockSeedPhrase(navigation);
Hanwen Cheng's avatar
Hanwen Cheng committed
		const derivationSucceed = await accounts.deriveNewPath(
			completePath,
Hanwen Cheng's avatar
Hanwen Cheng committed
			keyPairsName
		);
		if (derivationSucceed) {
			navigateToPathsList(navigation, currentNetworkKey);
Hanwen Cheng's avatar
Hanwen Cheng committed
		} else {
			setIsPathValid(false);
			alertPathDerivationError();
		}
	};

	return (
		<View style={styles.container}>
			<KeyboardScrollView extraHeight={Platform.OS === 'ios' ? 250 : 180}>
				<ScreenHeading
					title="Derive Account"
					subtitle={parentPath}
					hasSubtitleIcon={true}
				/>
Hanwen Cheng's avatar
Hanwen Cheng committed
				{!isPathValid && <Text>Invalid Path</Text>}
				<TextInput
					autoCorrect={false}
Hanwen Cheng's avatar
Hanwen Cheng committed
					label="Path"
					onChangeText={setDerivationPath}
					onSubmitEditing={(): void => pathNameInput.current?.input?.focus()}
Hanwen Cheng's avatar
Hanwen Cheng committed
					placeholder="//hard/soft"
					returnKeyType="next"
Hanwen Cheng's avatar
Hanwen Cheng committed
					testID={testIDs.PathDerivation.pathInput}
					value={derivationPath}
Hanwen Cheng's avatar
Hanwen Cheng committed
				/>
				<TextInput
					autoCorrect={false}
Hanwen Cheng's avatar
Hanwen Cheng committed
					label="Display Name"
					onChangeText={(keyParisName: string): void =>
						setKeyPairsName(keyParisName)
					}
					onSubmitEditing={onPathDerivation}
					ref={pathNameInput}
					returnKeyType="done"
Hanwen Cheng's avatar
Hanwen Cheng committed
					testID={testIDs.PathDerivation.nameInput}
					value={keyPairsName}
				/>
				{enableCustomNetwork && (
					<NetworkSelector
						networkKey={customNetworkKey}
						setVisible={setModalVisible}
					/>
				)}
Hanwen Cheng's avatar
Hanwen Cheng committed
				<Separator style={{ height: 0 }} />
				<PathCard
					identity={accounts.state.currentIdentity!}
Hanwen Cheng's avatar
Hanwen Cheng committed
					name={keyPairsName}
					path={completePath}
					networkKey={currentNetworkKey}
Hanwen Cheng's avatar
Hanwen Cheng committed
				<ButtonMainAction
					disabled={!validateDerivedPath(derivationPath)}
					bottom={false}
					style={{ marginTop: 8 }}
Hanwen Cheng's avatar
Hanwen Cheng committed
					testID={testIDs.PathDerivation.deriveButton}
					onPress={onPathDerivation}
				{enableCustomNetwork && (
					<NetworkOptions
						setNetworkKey={setCustomNetworkKey}
						visible={modalVisible}
						setVisible={setModalVisible}
					/>
				)}
Hanwen Cheng's avatar
Hanwen Cheng committed
			</KeyboardScrollView>
		</View>
	);
}

const styles = StyleSheet.create({
	container: {
		backgroundColor: colors.bg,
		flex: 1
	}
});

export default withAccountStore(PathDerivation);