@@ -52,6 +52,7 @@ const passkeyIconError = (
52
52
/>
53
53
</ svg >
54
54
) ;
55
+
55
56
interface AuthProps {
56
57
onAuthSuccess : ( ) => Promise < void > ;
57
58
onError : ( errorMessage : string ) => void ;
@@ -62,6 +63,7 @@ interface AuthProps {
62
63
appleEnabled : boolean ;
63
64
facebookEnabled : boolean ;
64
65
googleEnabled : boolean ;
66
+ walletEnabled : boolean ;
65
67
sessionLengthSeconds ?: number ; // Desired expiration time in seconds for the generated API key
66
68
googleClientId ?: string ; // will default to NEXT_PUBLIC_GOOGLE_CLIENT_ID
67
69
appleClientId ?: string ; // will default to NEXT_PUBLIC_APPLE_CLIENT_ID
@@ -80,7 +82,8 @@ const Auth: React.FC<AuthProps> = ({
80
82
customSmsMessage,
81
83
customAccounts,
82
84
} ) => {
83
- const { passkeyClient, authIframeClient, turnkey } = useTurnkey ( ) ;
85
+ const { passkeyClient, authIframeClient, walletClient, turnkey } =
86
+ useTurnkey ( ) ;
84
87
const [ email , setEmail ] = useState < string > ( "" ) ;
85
88
const [ phone , setPhone ] = useState < string > ( "" ) ;
86
89
const [ otpId , setOtpId ] = useState < string | null > ( null ) ;
@@ -92,6 +95,7 @@ const Auth: React.FC<AuthProps> = ({
92
95
const [ passkeySignupError , setPasskeySignupError ] = useState ( "" ) ;
93
96
const [ loading , setLoading ] = useState ( true ) ;
94
97
const [ passkeyCreated , setPasskeyCreated ] = useState ( false ) ;
98
+ const [ walletLoading , setWalletLoading ] = useState ( false ) ;
95
99
96
100
const handleResendCode = async ( ) => {
97
101
if ( step === OtpType . Email ) {
@@ -304,6 +308,63 @@ const Auth: React.FC<AuthProps> = ({
304
308
}
305
309
} ;
306
310
311
+ const handleLoginWithWallet = async ( ) => {
312
+ setWalletLoading ( true ) ;
313
+ try {
314
+ if ( ! walletClient ) {
315
+ throw new Error ( "Wallet client not initialized" ) ;
316
+ }
317
+
318
+ const publicKey = await walletClient . getPublicKey ( ) ;
319
+
320
+ if ( ! publicKey ) {
321
+ throw new Error ( authErrors . wallet . noPublicKey ) ;
322
+ }
323
+
324
+ const { type } = walletClient . getWalletInterface ( ) ;
325
+
326
+ const resp = await server . getOrCreateSuborg ( {
327
+ filterType : FilterType . PublicKey ,
328
+ filterValue : publicKey ,
329
+ additionalData : {
330
+ wallet : {
331
+ publicKey,
332
+ type,
333
+ } ,
334
+ } ,
335
+ } ) ;
336
+
337
+ const suborgIds = resp ?. subOrganizationIds ;
338
+ if ( ! suborgIds || suborgIds . length === 0 ) {
339
+ onError ( authErrors . wallet . loginFailed ) ;
340
+ return ;
341
+ }
342
+
343
+ const suborgId = suborgIds [ 0 ] ;
344
+
345
+ const sessionResponse = await walletClient . createReadWriteSession ( {
346
+ targetPublicKey : authIframeClient ?. iframePublicKey ! ,
347
+ ...( suborgId && { organizationId : suborgId } ) ,
348
+ ...( authConfig . sessionLengthSeconds !== undefined && {
349
+ expirationSeconds : authConfig . sessionLengthSeconds . toString ( ) ,
350
+ } ) ,
351
+ } ) ;
352
+
353
+ if ( sessionResponse ?. credentialBundle ) {
354
+ await handleAuthSuccess (
355
+ sessionResponse . credentialBundle ,
356
+ authConfig . sessionLengthSeconds ?. toString ( ) ,
357
+ ) ;
358
+ } else {
359
+ throw new Error ( authErrors . wallet . loginFailed ) ;
360
+ }
361
+ } catch ( error : any ) {
362
+ onError ( error . message || authErrors . wallet . loginFailed ) ;
363
+ } finally {
364
+ setWalletLoading ( false ) ;
365
+ }
366
+ } ;
367
+
307
368
const renderBackButton = ( ) => (
308
369
< ChevronLeftIcon
309
370
onClick = { ( ) => {
@@ -475,6 +536,28 @@ const Auth: React.FC<AuthProps> = ({
475
536
</ div >
476
537
) : null ;
477
538
539
+ case "wallet" :
540
+ return authConfig . walletEnabled && ! otpId ? (
541
+ < div className = { styles . passkeyContainer } >
542
+ < button
543
+ className = { styles . authButton }
544
+ type = "button"
545
+ onClick = { handleLoginWithWallet }
546
+ disabled = { walletLoading }
547
+ >
548
+ { walletLoading ? (
549
+ < CircularProgress
550
+ size = { 24 }
551
+ thickness = { 4 }
552
+ className = { styles . buttonProgress || "" }
553
+ />
554
+ ) : (
555
+ "Continue with Wallet"
556
+ ) }
557
+ </ button >
558
+ </ div >
559
+ ) : null ;
560
+
478
561
case "socials" :
479
562
return authConfig . googleEnabled ||
480
563
authConfig . appleEnabled ||
0 commit comments