added create mnemonic ui

This commit is contained in:
Michele Balistreri 2024-10-09 15:01:40 +02:00
parent 3ce5608be3
commit 13a197f8aa
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
1 changed files with 133 additions and 7 deletions

View File

@ -1,5 +1,5 @@
import {FC, useState } from "react";
import { KeyboardAvoidingView, Linking, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
import {FC, useRef, useState } from "react";
import { FlatList, KeyboardAvoidingView, Linking, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
import * as bip39 from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english';
import Button from "../Button";
@ -10,6 +10,7 @@ import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
enum LoadMnemonicSteps {
Home,
CreateMnemonic,
ConfirmMnemonic,
InsertMnemonic,
InsertPin
}
@ -27,9 +28,12 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
const [showMnemonic, setShowMnemonic] = useState(false);
const [isValid, setIsValid] = useState(false);
const [step, setStep] = useState(LoadMnemonicSteps.Home);
const [currentIndex, setCurrentIndex] = useState(0);
const shuffledWords = useRef([] as string[]);
const verifyIndexes = useRef([] as number[]);
const cleanMnemonic = (str: string) => {
return str.split(' ').filter((el: string) => el != "").map((word: string) => word.trim().toLowerCase()).join(' ');
return str.replaceAll("\n", " ").split(' ').filter((el: string) => el != "").map((word: string) => word.trim().toLowerCase()).join(' ');
}
const updateMnemonic = (str: string) => {
@ -58,7 +62,9 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
const generateMnemonic = () => {
setIsValid(true);
setMnemonic(bip39.generateMnemonic(wordlist));
const mn = bip39.generateMnemonic(wordlist, 128);
shuffledWords.current = mn.split(' ');
setMnemonic(mn);
setStep(LoadMnemonicSteps.CreateMnemonic);
}
@ -68,10 +74,49 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
setStep(LoadMnemonicSteps.Home);
}
const confirmMnemonic = () => {
shuffle(shuffledWords.current);
verifyIndexes.current = [...Array(12).keys()];
setCurrentIndex(0);
shuffle(verifyIndexes.current);
setStep(LoadMnemonicSteps.ConfirmMnemonic);
}
const resetConfirm = () => {
shuffledWords.current = mnemonic.split(' ');
setStep(LoadMnemonicSteps.CreateMnemonic);
}
const toggleVisibility = () => {
setShowMnemonic(!showMnemonic);
}
const shuffle = (array: any[]) => {
var currentIndex = array.length;
while (currentIndex != 0) {
var randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}
}
const wordAt = (idx: number) => {
return mnemonic.split(' ')[idx];
}
const verifyWord = (selected: number) => {
if (shuffledWords[selected] == wordAt(currentIndex)) {
if (currentIndex == 2) {
submitMnemonic();
} else {
setCurrentIndex(currentIndex + 1);
}
} else {
resetConfirm();
}
}
return (
<View style={Styles.container}>
{ step == LoadMnemonicSteps.Home &&
@ -89,7 +134,7 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
}
{ step == LoadMnemonicSteps.InsertMnemonic &&
<View style={Styles.container}>
<View style={{paddingTop: 30}}>
<View style={{paddingTop: 45}}>
<Text style={Styles.heading}> Import from Seed</Text>
<View style={styles.mnemonicInputContainer}>
<Text style={styles.mnemonicInputPlaceholder}>Seed phrase</Text>
@ -112,10 +157,41 @@ const MnemonicScreen: FC<MnemonicScreenProps> = props => {
</View>
}
{ step == LoadMnemonicSteps.CreateMnemonic &&
<View style={Styles.container}>
<View style={{flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingTop: 55}}>
<View style={styles.currentStep}></View>
<View style={styles.nextStep}></View>
</View>
<Text style={[Styles.heading, {paddingTop: 25, paddingBottom: 30, width: '65%', marginHorizontal: '17.5%'}]}>Write Down Your Seed Phrase</Text>
<Text style={styles.createMnemonicText}>This is your seed phrase. Write it down on a paper and keep it in a safe place. You'll be asked to re-enter this phrase (in order) on the next step.</Text>
<FlatList
data={shuffledWords.current}
numColumns={3}
style={styles.mnemonicList}
renderItem={({ item, index }) =>
<View style={styles.mnemonicWordContainer}>
<Text style={styles.mnemonicIndex}>{index + 1}</Text>
<Text style={styles.mnemonicWord}> {item}</Text>
</View>
}
/>
<View style={Styles.footer}>
<View style={Styles.navContainer}>
<Button type="cancel" disabled={false} onChangeFunc={goBack}></Button>
<Button label="Continue" disabled={false} onChangeFunc={confirmMnemonic}></Button>
</View>
</View>
</View>
}
{ step == LoadMnemonicSteps.ConfirmMnemonic &&
<View style={Styles.container}>
<Text> {mnemonic}</Text>
<Button type="cancel" disabled={false} onChangeFunc={goBack}></Button>
<Button label="Next" disabled={false} onChangeFunc={submitMnemonic}></Button>
<View style={Styles.footer}>
<View style={Styles.navContainer}>
<Button type="cancel" disabled={false} onChangeFunc={resetConfirm}></Button>
<Button label="Next" disabled={false} onChangeFunc={submitMnemonic}></Button>
</View>
</View>
</View>
}
{ step == LoadMnemonicSteps.InsertPin && <Dialpad pinRetryCounter={pinRetryCounter} prompt={"Enter PIN"} onCancelFunc={() => setStep(LoadMnemonicSteps.InsertMnemonic)} onNextFunc={submitPin}></Dialpad>}
@ -166,6 +242,56 @@ const styles = StyleSheet.create({
top: '42%',
zIndex: 1,
padding: 10
},
createMnemonicText: {
fontSize: 12,
lineHeight: 16,
fontFamily: "Inter",
color: "white",
width: "80%",
marginHorizontal: '10%',
textAlign: 'center'
},
mnemonicList: {
width: '80%',
marginHorizontal: '10%',
marginVertical: 55
},
mnemonicWordContainer: {
width: '30%',
textAlign: 'center',
borderWidth: 1,
borderColor: 'white',
padding: 10,
margin: '1.65%'
},
mnemonicIndex: {
fontFamily: 'Inter',
fontSize: 12,
lineHeight: 16,
color: 'white',
paddingBottom: 6
},
mnemonicWord: {
textAlign: 'center',
fontFamily: 'Inter',
fontSize: 14,
lineHeight: 20,
color: 'white'
},
currentStep: {
width: 50,
backgroundColor: 'white',
height: 5,
borderRadius: 5,
marginHorizontal: 2
},
nextStep: {
width: 50,
backgroundColor: 'grey',
height: 5,
borderRadius: 5,
marginHorizontal: 2
}
});