Generate wallet and sign message (#4)

* Store mnemonic and private key seperately

* Change variable names

* Refactor code in seperate components

* Display wallet details

* Remove unnecessary imports

* Make review changes

* Add method to reset wallet

* Make component self closing

* separate imports

---------

Co-authored-by: Adw8 <adwait@deepstacksoft.com>
This commit is contained in:
shreerang6921 2024-02-08 18:42:30 +05:30 committed by GitHub
parent 5dd97e3860
commit 3d40de966d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 137 additions and 73 deletions

125
App.tsx
View File

@ -12,48 +12,24 @@ import {
View,
} from 'react-native';
import { Colors } from 'react-native/Libraries/NewAppScreen';
import { HDNode } from 'ethers/lib/utils';
import { generateWallet, resetWallet, signMessage } from './utils';
import styles from './styles/stylesheet';
import { generateWallet, signMessage } from './utils';
type SectionProps = PropsWithChildren<{
title: string;
}>;
const Section = ({children, title}: SectionProps): React.JSX.Element => {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.sectionContainer}>
<Text
style={[
styles.sectionTitle,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
{title}
</Text>
<Text
style={[
styles.sectionDescription,
{
color: isDarkMode ? Colors.light : Colors.dark,
},
]}>
{children}
</Text>
</View>
);
};
import { Section } from './components/Section';
const App = (): React.JSX.Element => {
const [message, setMessage] = useState('');
const [isWalletCreated, setIsWalletCreated] = useState(false);
const [isWalletCreated, setIsWalletCreated] = useState<boolean>(false);
const [wallet, setWallet] = useState<HDNode | null>();
const createWallet = async () => {
Alert.alert('Creating Wallet...');
await generateWallet();
setIsWalletCreated(true);
const wallet = await generateWallet();
if (wallet) {
setWallet(wallet);
setIsWalletCreated(true);
}
};
const isDarkMode = useColorScheme() === 'dark';
@ -81,16 +57,62 @@ const App = (): React.JSX.Element => {
<View>
{isWalletCreated ? (
<View>
<Section title="Generate Wallet">Wallet Created! </Section>
<Section title="Wallet Details" />
<View style={{ marginTop: 32, paddingHorizontal: 24 }}>
<Text style={{ fontSize: 16, color: 'black' }}>
Address: {wallet && wallet.address.toString()}
</Text>
<Text style={{ fontSize: 16, color: 'black' }}>
Public Key: {wallet && wallet.publicKey.toString()}
</Text>
</View>
<Section title="Sign a message" />
<View>
<TextInput
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
margin: 10,
padding: 5,
}}
placeholder="Enter your message"
onChangeText={text => setMessage(text)}
value={message}
/>
<View
style={{ marginTop: 20, width: 150, alignSelf: 'center' }}>
<Button
title="Sign Message"
color="#841584"
onPress={() => {
signMessage(message);
}}
/>
</View>
</View>
<Section title="" />
<View>
<View
style={{ marginTop: 20, width: 150, alignSelf: 'center' }}>
<Button
title="Reset Wallet"
color="#D30000"
onPress={async () => {
await resetWallet();
setIsWalletCreated(false);
setWallet(null);
}}
/>
</View>
</View>
</View>
) : (
<View>
<Section title="Generate Wallet">
Click the button to generate the wallet
</Section>
<View style={{marginTop: 20, width: 150, alignSelf: 'center'}}>
<Section title="Create Wallet" />
<View style={{ marginTop: 20, width: 150, alignSelf: 'center' }}>
<Button
title="Initialise Wallet"
title="Create"
color="#841584"
onPress={createWallet}
/>
@ -98,29 +120,6 @@ const App = (): React.JSX.Element => {
</View>
)}
</View>
<View>
<TextInput
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
margin: 10,
padding: 5,
}}
placeholder="Enter your message"
onChangeText={text => setMessage(text)}
value={message}
/>
<View style={{marginTop: 20, width: 150, alignSelf: 'center'}}>
<Button
title="Sign Message"
color="#841584"
onPress={() => {
signMessage(message);
}}
/>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>

23
components/Header.tsx Normal file
View File

@ -0,0 +1,23 @@
import React from 'react';
import { View, Text, useColorScheme } from 'react-native';
import { Colors } from 'react-native/Libraries/NewAppScreen';
import styles from '../styles/stylesheet';
const Header = () => {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.headerContainer}>
<Text
style={[
styles.headerText,
{color: isDarkMode ? Colors.light : Colors.dark},
]}>
Laconic Wallet
</Text>
</View>
);
};
export { Header };

29
components/Section.tsx Normal file
View File

@ -0,0 +1,29 @@
import { PropsWithChildren } from "react";
import { Text, View, useColorScheme } from "react-native";
import { Colors } from "react-native/Libraries/NewAppScreen";
import styles from "../styles/stylesheet";
type SectionProps = PropsWithChildren<{
title: string;
}>;
const Section = ({ children, title }: SectionProps): React.JSX.Element => {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.sectionContainer}>
<Text
style={[
styles.sectionTitle,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
{title}
<Text style={styles.sectionDescription} />
</Text>
</View>
);
};
export { Section };

View File

@ -8,7 +8,7 @@ const styles = StyleSheet.create({
},
headerText: {
color: 'black',
fontSize: 22,
fontSize: 26,
fontWeight: 'bold',
},
sectionContainer: {
@ -16,7 +16,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontSize: 22,
fontWeight: '600',
},
sectionDescription: {

View File

@ -3,14 +3,22 @@ import '@ethersproject/shims';
import { Wallet, utils } from 'ethers';
import { HDNode } from 'ethers/lib/utils';
import { Alert } from 'react-native';
import { getGenericPassword, setGenericPassword } from 'react-native-keychain';
import {
setInternetCredentials,
getInternetCredentials,
resetInternetCredentials,
} from 'react-native-keychain';
const generateWallet = async () => {
const generateWallet = async (): Promise<HDNode | undefined> => {
try {
const mnemonic = utils.entropyToMnemonic(utils.randomBytes(32));
const hdNode = HDNode.fromMnemonic(mnemonic);
await setGenericPassword(mnemonic, hdNode.privateKey);
Alert.alert('Wallet stored successfully with address:', hdNode.address);
await setInternetCredentials('keyServer', 'key', hdNode.privateKey);
await setInternetCredentials('mnemonicServer', 'mnemonic', mnemonic);
Alert.alert('Wallet created successfully ');
return hdNode;
} catch (error) {
console.error('Error creating wallet ', error);
}
@ -18,11 +26,11 @@ const generateWallet = async () => {
const signMessage = async (message: string) => {
try {
const creds = await getGenericPassword();
const wallet = creds && new Wallet(creds.password);
const keyCred = await getInternetCredentials('keyServer');
const wallet = keyCred && new Wallet(keyCred.password);
const signature = wallet && (await wallet.signMessage(message));
if (typeof signature === 'string') {
Alert.alert('Message signed successfully with signature', signature);
Alert.alert('Message signature: ', signature);
} else {
Alert.alert('Message signing failed. Please try again.');
}
@ -31,4 +39,9 @@ const signMessage = async (message: string) => {
}
};
export { generateWallet, signMessage };
const resetWallet = async () => {
await resetInternetCredentials('keyServer');
await resetInternetCredentials('mnemonicServer');
};
export { generateWallet, signMessage, resetWallet };