diff --git a/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js b/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js
index 9b848d5b6..d49bf41be 100644
--- a/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js
+++ b/native/account/registration/missing-registration-data/missing-siwe-backup-message.react.js
@@ -1,53 +1,74 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
+import { Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { type SIWEResult } from 'lib/types/siwe-types.js';
+import { isValidEthereumAddress } from 'lib/utils/siwe-utils.js';
import { commCoreModule } from '../../../native-modules.js';
import { type RootNavigationProp } from '../../../navigation/root-navigator.react.js';
import { type NavigationRoute } from '../../../navigation/route-names.js';
+import { useSelector } from '../../../redux/redux-utils.js';
import { useStyles } from '../../../themes/colors.js';
import { CreateSIWEBackupMessageBase } from '../siwe-backup-message-creation.react.js';
type Props = {
+navigation: RootNavigationProp<'CreateMissingSIWEBackupMessage'>,
+route: NavigationRoute<'CreateMissingSIWEBackupMessage'>,
};
function CreateMissingSIWEBackupMessage(props: Props): React.Node {
const styles = useStyles(unboundStyles);
const { goBack } = props.navigation;
+ const currentUserInfo = useSelector(state => state.currentUserInfo);
+ const loggedInEthereumAccountAddress = currentUserInfo?.username;
+
+ invariant(
+ loggedInEthereumAccountAddress &&
+ isValidEthereumAddress(loggedInEthereumAccountAddress),
+ 'current username must be valid ethereum address to attempt ' +
+ 'backup message generation',
+ );
const onSuccessfulWalletSignature = React.useCallback(
(result: SIWEResult) => {
void (async () => {
- const { message, signature } = result;
+ const { message, signature, address } = result;
+ if (loggedInEthereumAccountAddress !== address) {
+ Alert.alert(
+ 'Mismatched Ethereum address',
+ 'You picked a different wallet than the one you use to sign in.',
+ );
+ return;
+ }
+
await commCoreModule.setSIWEBackupSecrets({ message, signature });
goBack();
})();
},
- [goBack],
+ [goBack, loggedInEthereumAccountAddress],
);
return (
);
}
const safeAreaEdges = ['top'];
const unboundStyles = {
container: {
flex: 1,
backgroundColor: 'panelBackground',
justifyContent: 'space-between',
},
};
export default CreateMissingSIWEBackupMessage;
diff --git a/native/account/registration/siwe-backup-message-creation.react.js b/native/account/registration/siwe-backup-message-creation.react.js
index 7e59f1578..35146ee2f 100644
--- a/native/account/registration/siwe-backup-message-creation.react.js
+++ b/native/account/registration/siwe-backup-message-creation.react.js
@@ -1,240 +1,250 @@
// @flow
import Icon from '@expo/vector-icons/MaterialIcons.js';
import invariant from 'invariant';
import * as React from 'react';
-import { View, Text } from 'react-native';
+import { View, Text, Alert } from 'react-native';
import { type SIWEResult, SIWEMessageTypes } from 'lib/types/siwe-types.js';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import { RegistrationContext } from './registration-context.js';
import { type RegistrationNavigationProp } from './registration-navigator.react.js';
import type {
CoolOrNerdMode,
AccountSelection,
AvatarData,
} from './registration-types.js';
import {
type NavigationRoute,
RegistrationTermsRouteName,
} from '../../navigation/route-names.js';
import { useStyles } from '../../themes/colors.js';
import SIWEPanel from '../siwe-panel.react.js';
type PanelState = 'closed' | 'opening' | 'open' | 'closing';
type CreateSIWEBackupMessageBaseProps = {
+onSuccessfulWalletSignature: (result: SIWEResult) => void,
+onExistingWalletSignature?: () => void,
+onSkip?: () => void,
};
const CreateSIWEBackupMessageBase: React.ComponentType =
React.memo(
function CreateSIWEBackupMessageBase(
props: CreateSIWEBackupMessageBaseProps,
): React.Node {
const { onSuccessfulWalletSignature, onExistingWalletSignature, onSkip } =
props;
const styles = useStyles(unboundStyles);
const [panelState, setPanelState] = React.useState('closed');
const openPanel = React.useCallback(() => {
setPanelState('opening');
}, []);
const onPanelClosed = React.useCallback(() => {
setPanelState('closed');
}, []);
const onPanelClosing = React.useCallback(() => {
setPanelState('closing');
}, []);
const siwePanelSetLoading = React.useCallback(
(loading: boolean) => {
if (panelState === 'closing' || panelState === 'closed') {
return;
}
setPanelState(loading ? 'opening' : 'open');
},
[panelState],
);
let siwePanel;
if (panelState !== 'closed') {
siwePanel = (
);
}
const newSignatureButtonText = onExistingWalletSignature
? 'Encrypt with new signature'
: 'Encrypt with Ethereum signature';
const newSignatureButtonVariant = onExistingWalletSignature
? 'outline'
: 'enabled';
let useExistingSignatureButton;
if (onExistingWalletSignature) {
useExistingSignatureButton = (
);
}
let onSkipButton;
if (onSkip) {
onSkipButton = (
);
}
return (
<>
Encrypting your Comm backup
To make sure we can’t see your data, Comm encrypts your backup
using a signature from your wallet.
You can always recover your data as long as you still control
your wallet.
{useExistingSignatureButton}
{onSkipButton}
{siwePanel}
>
);
},
);
export type CreateSIWEBackupMessageParams = {
+userSelections: {
+coolOrNerdMode?: ?CoolOrNerdMode,
+keyserverURL?: ?string,
+farcasterID: ?string,
+accountSelection: AccountSelection,
+avatarData: ?AvatarData,
},
};
type Props = {
+navigation: RegistrationNavigationProp<'CreateSIWEBackupMessage'>,
+route: NavigationRoute<'CreateSIWEBackupMessage'>,
};
function CreateSIWEBackupMessage(props: Props): React.Node {
const { navigate } = props.navigation;
const { params } = props.route;
const { userSelections } = params;
const registrationContext = React.useContext(RegistrationContext);
invariant(registrationContext, 'registrationContext should be set');
const { cachedSelections, setCachedSelections } = registrationContext;
const onSuccessfulWalletSignature = React.useCallback(
(result: SIWEResult) => {
- const { message, signature } = result;
+ const selectedEthereumAddress = userSelections.accountSelection.address;
+ const { message, signature, address } = result;
+
+ if (address !== selectedEthereumAddress) {
+ Alert.alert(
+ 'Mismatched Ethereum address',
+ 'You picked a different wallet than the one you use to sign in.',
+ );
+ return;
+ }
+
const newUserSelections = {
...userSelections,
siweBackupSecrets: { message, signature },
};
setCachedSelections(oldUserSelections => ({
...oldUserSelections,
siweBackupSecrets: { message, signature },
}));
navigate<'RegistrationTerms'>({
name: RegistrationTermsRouteName,
params: { userSelections: newUserSelections },
});
},
[navigate, setCachedSelections, userSelections],
);
const { siweBackupSecrets } = cachedSelections;
const onExistingWalletSignature = React.useCallback(() => {
const registrationTermsParams = {
userSelections: {
...userSelections,
siweBackupSecrets,
},
};
navigate<'RegistrationTerms'>({
name: RegistrationTermsRouteName,
params: registrationTermsParams,
});
}, [navigate, siweBackupSecrets, userSelections]);
if (siweBackupSecrets) {
return (
);
}
return (
);
}
const unboundStyles = {
scrollViewContentContainer: {
flexGrow: 1,
},
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
},
body: {
fontFamily: 'Arial',
fontSize: 15,
lineHeight: 20,
color: 'panelForegroundSecondaryLabel',
paddingBottom: 16,
},
siweBackupIcon: {
color: 'panelForegroundIcon',
},
siweBackupIconContainer: {
flexGrow: 1,
alignItems: 'center',
justifyContent: 'center',
},
};
export { CreateSIWEBackupMessageBase, CreateSIWEBackupMessage };