Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/wallet/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ PODS:
- React-logger (= 0.71.14)
- React-perflogger (= 0.71.14)
- RecaptchaInterop (100.0.0)
- RNAppleAuthentication (2.3.0):
- React-Core
- RNCClipboard (1.13.2):
- React-Core
- RNCustomAuthSdk (4.0.1):
Expand Down Expand Up @@ -686,6 +688,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../../../node_modules/react-native/Libraries/Vibration`)
- React-runtimeexecutor (from `../../../node_modules/react-native/ReactCommon/runtimeexecutor`)
- ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`)
- "RNAppleAuthentication (from `../../../node_modules/@invertase/react-native-apple-authentication`)"
- "RNCClipboard (from `../../../node_modules/@react-native-clipboard/clipboard`)"
- "RNCustomAuthSdk (from `../../../node_modules/@toruslabs/customauth-react-native-sdk`)"
- RNDeviceInfo (from `../../../node_modules/react-native-device-info`)
Expand Down Expand Up @@ -836,6 +839,8 @@ EXTERNAL SOURCES:
:path: "../../../node_modules/react-native/ReactCommon/runtimeexecutor"
ReactCommon:
:path: "../../../node_modules/react-native/ReactCommon"
RNAppleAuthentication:
:path: "../../../node_modules/@invertase/react-native-apple-authentication"
RNCClipboard:
:path: "../../../node_modules/@react-native-clipboard/clipboard"
RNCustomAuthSdk:
Expand Down Expand Up @@ -957,6 +962,7 @@ SPEC CHECKSUMS:
React-runtimeexecutor: ffe826b7b1cfbc32a35ed5b64d5886c0ff75f501
ReactCommon: 6f0ee30fda78283c31310e585f7236748e13330d
RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21
RNAppleAuthentication: e99eaf3c4c01ad8ecb6125dd6f0cfd98871685b5
RNCClipboard: 60fed4b71560d7bfe40e9d35dea9762b024da86d
RNCustomAuthSdk: e1db0c850b41deaf38fdc8fe5433b3287db29c55
RNDeviceInfo: db5c64a060e66e5db3102d041ebe3ef307a85120
Expand Down
2 changes: 2 additions & 0 deletions apps/wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@craftzdog/pouchdb-collate-react-native": "^7.3.0",
"@craftzdog/react-native-buffer": "^6.0.5",
"@dreson4/react-native-quick-bip39": "0.0.5",
"@invertase/react-native-apple-authentication": "^2.3.0",
"@metacraft/cli-web3-polyfills": "^0.0.7",
"@metaplex-foundation/js": "^0.19.4",
"@mysten/sui.js": "0.34.0",
Expand Down Expand Up @@ -75,6 +76,7 @@
"pouchdb-mapreduce": "^8.0.1",
"pouchdb-replication": "^8.0.1",
"react": "^18.2.0",
"react-apple-signin-auth": "^1.1.0",
"react-dom": "^18.2.0",
"react-native": "0.71.14",
"react-native-biometrics": "^3.0.1",
Expand Down
40 changes: 33 additions & 7 deletions apps/wallet/src/screens/Authentication/Login/SignInInner.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
import type { FC } from 'react';
import { Fragment } from 'react';
import { ActivityIndicator, StyleSheet } from 'react-native';
import { appleAuthAndroid } from '@invertase/react-native-apple-authentication';
import { runtime } from '@walless/core';
import { Button, Text, View } from '@walless/gui';
import { Google } from '@walless/icons';
import { Apple, Google } from '@walless/icons';

interface Props {
onGoogleSignIn?: () => void;
onAppleSignIn?: () => void;
loading?: boolean;
onGetInvitationCode?: () => void;
}

const SignInInner: FC<Props> = ({ onGoogleSignIn, loading }) => {
const SignInInner: FC<Props> = ({ onGoogleSignIn, onAppleSignIn, loading }) => {
const isAppleSignInSupported = runtime.isIOS || appleAuthAndroid.isSupported;

return (
<View style={styles.container}>
<View style={styles.commandContainer}>
{loading ? (
<ActivityIndicator color="white" />
) : (
<Button style={styles.signInButton} onPress={onGoogleSignIn}>
<Google />
<Text style={styles.buttonText}>Sign in with Google</Text>
</Button>
<Fragment>
<Button style={styles.signInButton} onPress={onGoogleSignIn}>
<Google />
<Text style={styles.buttonText}>Sign in with Google</Text>
</Button>

{isAppleSignInSupported && (
<Button
style={[styles.signInButton, styles.appleButton]}
onPress={onAppleSignIn}
>
<Apple color="black" />
<Text style={[styles.buttonText, styles.appleButtonText]}>
Sign in with Apple
</Text>
</Button>
)}
</Fragment>
)}
</View>

Expand Down Expand Up @@ -50,17 +70,23 @@ const styles = StyleSheet.create({
},
commandContainer: {
justifyContent: 'center',
gap: 24,
},
signInButton: {
flexDirection: 'row',
backgroundColor: '#0694D3',
gap: 8,
},
buttonText: {
fontSize: 16,
fontWeight: '500',
color: 'white',
},
appleButton: {
backgroundColor: 'white',
},
appleButtonText: {
color: 'black',
},
advancedModeContainer: {
gap: 24,
},
Expand Down
140 changes: 140 additions & 0 deletions apps/wallet/src/screens/Authentication/Login/SignInInner.web.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import type { FC } from 'react';
import { Fragment } from 'react';
import AppleSignin from 'react-apple-signin-auth';
import { ActivityIndicator, StyleSheet } from 'react-native';
import { logger } from '@walless/core';
import { Button, Text, View } from '@walless/gui';
import { Apple, Google } from '@walless/icons';

interface Props {
onGoogleSignIn?: () => void;
onAppleSignIn?: () => void;
loading?: boolean;
onGetInvitationCode?: () => void;
}

const SignInInner: FC<Props> = ({ onGoogleSignIn, loading }) => {
return (
<View style={styles.container}>
<View style={styles.commandContainer}>
{loading ? (
<ActivityIndicator color="white" />
) : (
<Fragment>
<Button style={styles.signInButton} onPress={onGoogleSignIn}>
<Google />
<Text style={styles.buttonText}>Sign in with Google</Text>
</Button>

<AppleSignin
authOptions={{
clientId: 'Config.APPLE_SIGNIN_CLIENT_ID',
redirectURI: 'metacraft://walless/auth',
scope: 'email name',
state: crypto.randomUUID(),
nonce: crypto.randomUUID(),
usePopup: true,
}}
onSuccess={(response) => {
// Response
// {
// "authorization": {
// "state": "[STATE]",
// "code": "[CODE]",
// "id_token": "[ID_TOKEN]"
// },
// "user": {
// "email": "[EMAIL]",
// "name": {
// "firstName": "[FIRST_NAME]",
// "lastName": "[LAST_NAME]"
// }
// }
// }

console.log('--> apple sign-in on web', response);
}}
onError={(e) => logger.error(e)}
uiType="light"
render={({ onClick }) => (
<Button
style={[styles.signInButton, styles.appleButton]}
onPress={onClick}
>
<Apple color="black" />
<Text style={[styles.buttonText, styles.appleButtonText]}>
Sign in with Apple
</Text>
</Button>
)}
/>
</Fragment>
)}
</View>

<View style={styles.advancedModeContainer}>
<View style={styles.separateContainer}>
<View style={styles.line} />
<Text style={styles.subText}>Advanced mode</Text>
<View style={styles.line} />
</View>

<Button
style={styles.seedPhraseButton}
disabled
title="Create or Import"
titleStyle={styles.buttonText}
/>
</View>
</View>
);
};

export default SignInInner;

const styles = StyleSheet.create({
container: {
gap: 28,
paddingHorizontal: 36,
},
commandContainer: {
justifyContent: 'center',
gap: 24,
},
signInButton: {
flexDirection: 'row',
gap: 8,
},
buttonText: {
fontSize: 16,
fontWeight: '500',
color: 'white',
},
appleButton: {
backgroundColor: 'white',
},
appleButtonText: {
color: 'black',
},
advancedModeContainer: {
gap: 24,
},
separateContainer: {
flexDirection: 'row',
alignItems: 'center',
gap: 16,
},
line: {
flex: 1,
height: 1,
backgroundColor: '#2A333C',
},
seedPhraseButton: {
backgroundColor: '#243F56',
},
subText: {
fontSize: 14,
color: '#566674',
fontWeight: '400',
},
});
15 changes: 11 additions & 4 deletions apps/wallet/src/screens/Authentication/Login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { appState } from 'state/app';
import assets from 'utils/assets';
import { useSafeAreaInsets, useSnapshot } from 'utils/hooks';

import { signIn } from './internal';
import { signIn, SignInMethod } from './internal';
import SignInHeader from './SignInHeader';
import SignInInner from './SignInInner';

Expand All @@ -20,17 +20,24 @@ export const LoginScreen: FC = () => {
};
const logoSize = 120;

const handleGoogleSignIn = async () => {
const handleSignIn = async (method: SignInMethod) => {
setLoading(true);
await signIn(invitationCode);
await signIn(invitationCode, method);
setLoading(false);
};

return (
<View style={[styles.container, containerStyle]}>
<View />

<SignInHeader logoSrc={assets.misc.walless} logoSize={logoSize} />
<SignInInner onGoogleSignIn={handleGoogleSignIn} loading={loading} />

<SignInInner
onGoogleSignIn={() => handleSignIn(SignInMethod.Google)}
onAppleSignIn={() => handleSignIn(SignInMethod.Apple)}
loading={loading}
/>

<View style={styles.footerContainer}>
<View style={styles.helpContainer}>
<Text>Having issues with log in? Visit </Text>
Expand Down
22 changes: 19 additions & 3 deletions apps/wallet/src/screens/Authentication/Login/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,36 @@ import { logger } from '@walless/core';
import { showError } from 'modals/Error';
import {
checkInvitationCode,
signInWithApple,
signInWithGoogle,
signInWithTorusKey,
ThresholdResult,
} from 'utils/auth';
import type { FirebaseUser } from 'utils/firebase';
import { navigate } from 'utils/navigation';

export const signIn = async (invitationCode?: string) => {
export enum SignInMethod {
Google = 'Google',
Apple = 'Apple',
}

export const signIn = async (
invitationCode?: string,
method: SignInMethod = SignInMethod.Google,
) => {
let user: FirebaseUser;

try {
user = await signInWithGoogle();
if (method === SignInMethod.Google) {
user = await signInWithGoogle();
} else if (method === SignInMethod.Apple) {
user = await signInWithApple();
} else {
throw new Error('Unsupported sign-in method');
}
} catch (error) {
showError({ errorText: 'Something went wrong' });
logger.error('Error when sign-in with google', error);
logger.error(`Error when sign-in with ${method}`, error);
return;
}

Expand Down
2 changes: 2 additions & 0 deletions apps/wallet/src/utils/auth/signIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CustomAuth, initServiceProvider } from './w3a/tkey';
import { initBySeedPhraseModule } from './keys';
import { initAndRegisterWallet } from './recovery';
import { signInWithGoogle } from './signInGoogle';
import { signInWithApple } from './signInWithApple';
import {
customAuthArgs,
importAvailableShares,
Expand Down Expand Up @@ -88,6 +89,7 @@ const signInWithPasscode = async (

export {
checkInvitationCode,
signInWithApple,
signInWithGoogle,
signInWithPasscode,
signInWithTorusKey,
Expand Down
Loading