BlueWallet/screen/wallets/signVerify.js

266 lines
8.5 KiB
JavaScript
Raw Normal View History

2024-05-31 19:18:01 +02:00
import React, { useEffect, useState } from 'react';
2024-05-20 11:54:13 +02:00
import { useRoute } from '@react-navigation/native';
2021-03-23 13:16:32 +01:00
import {
ActivityIndicator,
Keyboard,
KeyboardAvoidingView,
LayoutAnimation,
2021-03-23 13:16:32 +01:00
Platform,
StyleSheet,
TextInput,
TouchableWithoutFeedback,
View,
} from 'react-native';
import { Icon } from 'react-native-elements';
import Share from 'react-native-share';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
2024-05-20 11:54:13 +02:00
import { BlueDoneAndDismissKeyboardInputAccessory, BlueFormLabel, BlueSpacing10, BlueSpacing20, BlueSpacing40 } from '../../BlueComponents';
import presentAlert from '../../components/Alert';
2024-05-20 11:54:13 +02:00
import { FButton, FContainer } from '../../components/FloatButtons';
import SafeArea from '../../components/SafeArea';
import { useTheme } from '../../components/themes';
import loc from '../../loc';
2024-05-31 19:18:01 +02:00
import { useStorage } from '../../hooks/context/useStorage';
2021-03-23 13:16:32 +01:00
const SignVerify = () => {
const { colors } = useTheme();
const { wallets, sleep } = useStorage();
2021-03-23 13:16:32 +01:00
const { params } = useRoute();
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
2021-04-15 19:46:10 +02:00
const [address, setAddress] = useState(params.address ?? '');
const [message, setMessage] = useState(params.message ?? '');
2021-03-23 13:16:32 +01:00
const [signature, setSignature] = useState('');
const [loading, setLoading] = useState(false);
const [messageHasFocus, setMessageHasFocus] = useState(false);
const [isShareVisible, setIsShareVisible] = useState(false);
2021-03-23 13:16:32 +01:00
const wallet = wallets.find(w => w.getID() === params.walletID);
const isToolbarVisibleForAndroid = Platform.OS === 'android' && messageHasFocus && isKeyboardVisible;
useEffect(() => {
Keyboard.addListener(Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow', () => setIsKeyboardVisible(true));
Keyboard.addListener(Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide', () => setIsKeyboardVisible(false));
return () => {
2022-02-11 12:47:06 +01:00
Keyboard.removeAllListeners(Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow');
Keyboard.removeAllListeners(Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide');
2021-03-23 13:16:32 +01:00
};
}, []);
const stylesHooks = StyleSheet.create({
root: {
backgroundColor: colors.elevated,
},
text: {
borderColor: colors.formBorder,
borderBottomColor: colors.formBorder,
backgroundColor: colors.inputBackgroundColor,
color: colors.foregroundColor,
},
});
const handleShare = () => {
const baseUri = 'https://bluewallet.github.io/VerifySignature';
const uri = `${baseUri}?a=${address}&m=${encodeURIComponent(message)}&s=${encodeURIComponent(signature)}`;
Share.open({ message: uri }).catch(error => console.log(error));
};
2021-03-23 13:16:32 +01:00
const handleSign = async () => {
setLoading(true);
await sleep(10); // wait for loading indicator to appear
2021-04-15 19:46:10 +02:00
let newSignature;
2021-03-23 13:16:32 +01:00
try {
2022-01-28 17:56:24 +01:00
newSignature = wallet.signMessage(message, address);
2021-03-23 13:16:32 +01:00
setSignature(newSignature);
setIsShareVisible(true);
2021-03-23 13:16:32 +01:00
} catch (e) {
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
presentAlert({ title: loc.errors.error, message: e.message });
2021-03-23 13:16:32 +01:00
}
2021-04-15 19:46:10 +02:00
2021-03-23 13:16:32 +01:00
setLoading(false);
};
const handleVerify = async () => {
setLoading(true);
await sleep(10); // wait for loading indicator to appear
try {
const res = wallet.verifyMessage(message, address, signature);
presentAlert({
title: res ? loc._.success : loc.errors.error,
message: res ? loc.addresses.sign_signature_correct : loc.addresses.sign_signature_incorrect,
});
2021-03-23 13:16:32 +01:00
if (res) {
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
2021-03-23 13:16:32 +01:00
}
} catch (e) {
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
presentAlert({ title: loc.errors.error, message: e.message });
2021-03-23 13:16:32 +01:00
}
setLoading(false);
};
const handleFocus = value => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setMessageHasFocus(value);
};
2021-03-23 13:16:32 +01:00
if (loading)
return (
2021-03-25 01:27:51 +01:00
<View style={[stylesHooks.root, styles.loading]}>
2021-03-23 13:16:32 +01:00
<ActivityIndicator />
</View>
);
return (
<SafeArea style={[styles.root, stylesHooks.root]}>
2021-03-23 13:16:32 +01:00
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<KeyboardAvoidingView style={[styles.root, stylesHooks.root]}>
{!isKeyboardVisible && (
<>
<BlueSpacing20 />
<BlueFormLabel>{loc.addresses.sign_help}</BlueFormLabel>
<BlueSpacing20 />
</>
)}
<TextInput
multiline
textAlignVertical="top"
blurOnSubmit
placeholder={loc.addresses.sign_placeholder_address}
placeholderTextColor="#81868e"
value={address}
onChangeText={t => setAddress(t.replace('\n', ''))}
testID="Signature"
style={[styles.text, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
editable={!loading}
/>
<BlueSpacing10 />
<TextInput
multiline
textAlignVertical="top"
blurOnSubmit
placeholder={loc.addresses.sign_placeholder_signature}
placeholderTextColor="#81868e"
value={signature}
onChangeText={t => setSignature(t.replace('\n', ''))}
testID="Signature"
style={[styles.text, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
editable={!loading}
/>
<BlueSpacing10 />
<TextInput
multiline
placeholder={loc.addresses.sign_placeholder_message}
placeholderTextColor="#81868e"
value={message}
onChangeText={setMessage}
testID="Message"
inputAccessoryViewID={BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID}
style={[styles.flex, styles.text, styles.textMessage, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
editable={!loading}
onFocus={() => handleFocus(true)}
onBlur={() => handleFocus(false)}
2021-03-23 13:16:32 +01:00
/>
2024-05-11 18:33:55 +02:00
<BlueSpacing40 />
2021-03-23 13:16:32 +01:00
{isShareVisible && !isKeyboardVisible && (
<>
<FContainer inline>
<FButton
onPress={handleShare}
text={loc.multisig.share}
icon={
<View style={styles.buttonsIcon}>
<Icon name="external-link" size={16} type="font-awesome" color={colors.buttonAlternativeTextColor} />
</View>
}
/>
</FContainer>
<BlueSpacing10 />
</>
)}
2021-03-23 13:16:32 +01:00
{!isKeyboardVisible && (
<>
<FContainer inline>
2022-01-27 21:59:46 +01:00
<FButton onPress={handleSign} text={loc.addresses.sign_sign} disabled={loading} />
2021-03-23 13:16:32 +01:00
<FButton onPress={handleVerify} text={loc.addresses.sign_verify} disabled={loading} />
</FContainer>
<BlueSpacing10 />
</>
)}
{Platform.select({
ios: (
<BlueDoneAndDismissKeyboardInputAccessory
onClearTapped={() => setMessage('')}
onPasteTapped={text => {
setMessage(text);
Keyboard.dismiss();
}}
/>
),
android: isToolbarVisibleForAndroid && (
<BlueDoneAndDismissKeyboardInputAccessory
onClearTapped={() => {
setMessage('');
Keyboard.dismiss();
}}
onPasteTapped={text => {
setMessage(text);
Keyboard.dismiss();
}}
/>
),
})}
</KeyboardAvoidingView>
</TouchableWithoutFeedback>
</SafeArea>
2021-03-23 13:16:32 +01:00
);
};
export default SignVerify;
const styles = StyleSheet.create({
root: {
flex: 1,
},
text: {
paddingHorizontal: 8,
paddingVertical: 8,
marginTop: 5,
marginHorizontal: 20,
borderWidth: 1,
borderBottomWidth: 0.5,
borderRadius: 4,
textAlignVertical: 'top',
},
textMessage: {
minHeight: 50,
},
flex: {
flex: 1,
},
loading: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center',
},
});