Skip to content
Open
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
5 changes: 4 additions & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
"newArchEnabled": true,
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.moldy530.testfreshapp2"
"bundleIdentifier": "com.moldy530.testfreshapp2",
"associatedDomains": [
"webcredentials:wallets-example.florrdv.workers.dev"
]
},
"android": {
"adaptiveIcon": {
Expand Down
9 changes: 9 additions & 0 deletions app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ export default function TabLayout() {
),
}}
/>
<Tabs.Screen
name="passkey"
options={{
title: "Passkey",
tabBarIcon: ({ color }) => (
<IconSymbol size={28} name="faceid" color={color} />
),
}}
/>
</Tabs>
);
}
154 changes: 154 additions & 0 deletions app/(tabs)/passkey.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import {
useAuthenticate,
useLogout,
useSignerStatus,
useUser,
} from "@account-kit/react-native";
import { useState } from "react";
import {
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";

export default function PasskeyScreen() {
const { authenticateAsync } = useAuthenticate();
const { isConnected } = useSignerStatus();
const user = useUser();
const { logout } = useLogout();
const [isAuthenticating, setIsAuthenticating] = useState(false);

const handleCreatePasskey = async () => {
setIsAuthenticating(true);
try {
await authenticateAsync({
type: "passkey",
createNew: true,
username: "passkey"
});
} catch (error) {
console.error("Failed to create passkey:", error);
} finally {
setIsAuthenticating(false);
}
};

const handleSignInWithPasskey = async () => {
setIsAuthenticating(true);
try {
await authenticateAsync({
type: "passkey",
createNew: false,
});
} catch (error) {
console.error("Failed to sign in with passkey:", error);
} finally {
setIsAuthenticating(false);
}
};

return (
<View style={styles.container}>
{!user ? (
<>
<Text style={styles.title}>Passkey Authentication</Text>
<Text style={styles.subtitle}>
Sign in or create an account using biometric authentication
</Text>

<TouchableOpacity
style={[styles.button, styles.primaryButton]}
onPress={handleSignInWithPasskey}
disabled={isAuthenticating}
>
<Text style={styles.buttonText}>
{isAuthenticating ? "Authenticating..." : "Sign In with Passkey"}
</Text>
</TouchableOpacity>

<TouchableOpacity
style={[styles.button, styles.secondaryButton]}
onPress={handleCreatePasskey}
disabled={isAuthenticating}
>
<Text style={styles.secondaryButtonText}>
{isAuthenticating ? "Creating..." : "Create New Passkey"}
</Text>
</TouchableOpacity>
</>
) : (
<>
<Text style={styles.title}>Authenticated</Text>
<Text style={styles.userText}>User ID: {user.userId}</Text>
<Text style={styles.userText}>Org ID: {user.orgId}</Text>
{user.email && (
<Text style={styles.userText}>Email: {user.email}</Text>
)}

<TouchableOpacity
style={[styles.button, styles.primaryButton]}
onPress={() => logout()}
>
<Text style={styles.buttonText}>Sign Out</Text>
</TouchableOpacity>
</>
)}
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#FFFFFF",
paddingHorizontal: 20,
},
title: {
fontSize: 28,
fontWeight: "bold",
marginBottom: 10,
color: "#333",
},
subtitle: {
fontSize: 16,
color: "#666",
textAlign: "center",
marginBottom: 40,
paddingHorizontal: 20,
},
button: {
width: "100%",
maxWidth: 300,
padding: 16,
borderRadius: 12,
alignItems: "center",
justifyContent: "center",
marginTop: 15,
},
primaryButton: {
backgroundColor: "rgb(147, 197, 253)",
},
secondaryButton: {
backgroundColor: "white",
borderWidth: 2,
borderColor: "rgb(147, 197, 253)",
},
buttonText: {
color: "white",
fontWeight: "600",
fontSize: 16,
},
secondaryButtonText: {
color: "rgb(147, 197, 253)",
fontWeight: "600",
fontSize: 16,
},
userText: {
marginBottom: 10,
fontSize: 16,
color: "#333",
},
});
1 change: 1 addition & 0 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const config = createConfig({
),
policyId: process.env.EXPO_PUBLIC_SOLANA_SPONSORSHIP_POLICY, // Optional - gas/rent sponsorship policy ID: https://dashboard.alchemy.com/gas-manager
},
rpId: "wallets-example.florrdv.workers.dev", // Your domain for passkey support
});

const queryClient = new QueryClient();
Expand Down
34 changes: 24 additions & 10 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- account-kit-react-native-signer (4.59.1):
- account-kit-react-native-signer (4.60.0):
- Base58Swift
- DoubleConversion
- glog
Expand Down Expand Up @@ -120,9 +120,9 @@ PODS:
- FBLazyVector (0.79.5)
- fmt (11.0.2)
- glog (0.3.5)
- hermes-engine (0.79.4):
- hermes-engine/Pre-built (= 0.79.4)
- hermes-engine/Pre-built (0.79.4)
- hermes-engine (0.79.5):
- hermes-engine/Pre-built (= 0.79.5)
- hermes-engine/Pre-built (0.79.5)
- libavif/core (0.11.1)
- libavif/libdav1d (0.11.1):
- libavif/core
Expand Down Expand Up @@ -179,6 +179,7 @@ PODS:
- React-RCTText (= 0.79.5)
- React-RCTVibration (= 0.79.5)
- React-callinvoker (0.79.5)
- React-Codegen (0.1.0)
- React-Core (0.79.5):
- glog
- hermes-engine
Expand Down Expand Up @@ -1490,6 +1491,13 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-passkey (3.1.0):
- RCT-Folly
- RCTRequired
- RCTTypeSafety
- React-Codegen
- React-Core
- ReactCommon/turbomodule/core
- react-native-safe-area-context (5.4.0):
- DoubleConversion
- glog
Expand Down Expand Up @@ -2112,9 +2120,9 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1)
- SDWebImage (5.21.2):
- SDWebImage/Core (= 5.21.2)
- SDWebImage/Core (5.21.2)
- SDWebImageAVIFCoder (0.11.0):
- libavif/core (>= 0.11.0)
- SDWebImage (~> 5.10)
Expand Down Expand Up @@ -2187,6 +2195,7 @@ DEPENDENCIES:
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
- react-native-mmkv (from `../node_modules/react-native-mmkv`)
- react-native-passkey (from `../node_modules/react-native-passkey`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- react-native-webview (from `../node_modules/react-native-webview`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
Expand Down Expand Up @@ -2233,6 +2242,7 @@ SPEC REPOS:
- libavif
- libdav1d
- libwebp
- React-Codegen
- SDWebImage
- SDWebImageAVIFCoder
- SDWebImageSVGCoder
Expand Down Expand Up @@ -2357,6 +2367,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-get-random-values"
react-native-mmkv:
:path: "../node_modules/react-native-mmkv"
react-native-passkey:
:path: "../node_modules/react-native-passkey"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
react-native-webview:
Expand Down Expand Up @@ -2435,7 +2447,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
account-kit-react-native-signer: ef67301dcbfadeb4a03e7e19a9b7ff5918ed4ce4
account-kit-react-native-signer: 6b690095050094b91ae2fa8d71ea89d77754ad40
Base58Swift: 53d551f0b33d9478fa63b3445e453a772d6b31a7
BigInt: 74b4d88367b0e819d9f77393549226d36faeb0d8
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
Expand All @@ -2461,7 +2473,7 @@ SPEC CHECKSUMS:
FBLazyVector: d2a9cd223302b6c9aa4aa34c1a775e9db609eb52
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: 8b5a5eb386b990287d072fd7b6f6ebd9544dd251
hermes-engine: f03b0e06d3882d71e67e45b073bb827da1a21aae
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
Expand All @@ -2471,6 +2483,7 @@ SPEC CHECKSUMS:
RCTTypeSafety: cc4740278c2a52cbf740592b0a0a40df1587c9ab
React: 6393ae1807614f017a84805bf2417e3497f518a6
React-callinvoker: c34f666f551f05a325b87e7e3e6df0e082fa3d99
React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a
React-Core: 1ba9acdf7accbd46ccaae99999443ae2722c82b7
React-CoreModules: 3c3cf4a91257f138e3feb47169a2d7fe341b5495
React-cxxreact: 444d518a5d3a933e029b5e5ca6d8127c2e43255c
Expand Down Expand Up @@ -2498,6 +2511,7 @@ SPEC CHECKSUMS:
React-microtasksnativemodule: bda561d2648e1e52bd9e5a87f8889836bdbde2e2
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
react-native-mmkv: fb6fdab2e83b892959e32586b7814078fe6c1a6a
react-native-passkey: 3aac247c18127443ef4a002b59d8e12dc7e99f2e
react-native-safe-area-context: 562163222d999b79a51577eda2ea8ad2c32b4d06
react-native-webview: 520bcb79c3f2af91e157cdd695732a34ab5f25c8
React-NativeModulesApple: 1ecb83880dd11baf2228f8dd89d8419c387e03ad
Expand Down Expand Up @@ -2535,7 +2549,7 @@ SPEC CHECKSUMS:
RNInAppBrowser: 6d3eb68d471b9834335c664704719b8be1bfdb20
RNReanimated: 2313402fe27fecb7237619e9c6fcee3177f08a65
RNScreens: 482e9707f9826230810c92e765751af53826d509
SDWebImage: f29024626962457f3470184232766516dee8dfea
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
Expand Down
Loading