1
+ import { useState } from 'react'
1
2
import { Turnstile } from '@marsidev/react-turnstile'
2
- import { BigHeading , ButtonText , H3 , Paragraph , SubmitButton , XStack , YStack } from '@my/ui'
3
+ import {
4
+ BigHeading ,
5
+ ButtonText ,
6
+ H3 ,
7
+ Paragraph ,
8
+ SubmitButton ,
9
+ XStack ,
10
+ YStack ,
11
+ useToastController ,
12
+ } from '@my/ui'
3
13
import { TRPCClientError } from '@trpc/client'
14
+ import { bytesToHex , hexToBytes } from 'viem'
15
+ import { useRouter } from 'solito/router'
16
+ import { z } from 'zod'
17
+ import { FormProvider , useForm } from 'react-hook-form'
18
+ import { RecoveryOptions } from '@my/api/src/routers/account-recovery/types'
4
19
import { VerifyCode } from 'app/features/auth/components/VerifyCode'
5
20
import { SchemaForm , formFields } from 'app/utils/SchemaForm'
6
21
import { api } from 'app/utils/api'
7
- import { useState } from 'react'
8
- import { FormProvider , useForm } from 'react-hook-form'
9
- import { useRouter } from 'solito/router'
10
- import { z } from 'zod'
11
- import { SignInButton } from '../components/SignInButton'
12
- import { formatErrorMessage } from 'app/features/splash/screen'
22
+ import { formatErrorMessage } from 'app/utils/formatErrorMessage'
23
+ import { signChallenge } from 'app/utils/signChallenge'
24
+ import { useAuthScreenParams } from 'app/routers/params'
13
25
14
26
const SignUpSchema = z . object ( {
15
27
countrycode : formFields . countrycode ,
@@ -20,8 +32,51 @@ export const SignUpForm = () => {
20
32
const form = useForm < z . infer < typeof SignUpSchema > > ( )
21
33
const signInWithOtp = api . auth . signInWithOtp . useMutation ( )
22
34
const router = useRouter ( )
35
+ const [ queryParams ] = useAuthScreenParams ( )
36
+ const { redirectUri } = queryParams
37
+ const toast = useToastController ( )
23
38
const [ captchaToken , setCaptchaToken ] = useState < string | undefined > ( )
24
39
const [ signInError , setSignInError ] = useState < Error | null > ( null )
40
+ const [ isSigningIn , setIsSigningIn ] = useState ( false )
41
+
42
+ const { mutateAsync : getChallengeMutateAsync } = api . challenge . getChallenge . useMutation ( {
43
+ retry : false ,
44
+ } )
45
+ const { mutateAsync : validateSignatureMutateAsync } = api . challenge . validateSignature . useMutation (
46
+ { retry : false }
47
+ )
48
+
49
+ const handleSignIn = async ( ) => {
50
+ setIsSigningIn ( true )
51
+ try {
52
+ const challengeData = await getChallengeMutateAsync ( )
53
+
54
+ const rawIdsB64 : { id : string ; userHandle : string } [ ] = [ ]
55
+ const { encodedWebAuthnSig, accountName, keySlot } = await signChallenge (
56
+ challengeData . challenge as `0x${string } `,
57
+ rawIdsB64
58
+ )
59
+
60
+ const encodedWebAuthnSigBytes = hexToBytes ( encodedWebAuthnSig )
61
+ const newEncodedWebAuthnSigBytes = new Uint8Array ( encodedWebAuthnSigBytes . length + 1 )
62
+ newEncodedWebAuthnSigBytes [ 0 ] = keySlot
63
+ newEncodedWebAuthnSigBytes . set ( encodedWebAuthnSigBytes , 1 )
64
+
65
+ await validateSignatureMutateAsync ( {
66
+ recoveryType : RecoveryOptions . WEBAUTHN ,
67
+ signature : bytesToHex ( newEncodedWebAuthnSigBytes ) ,
68
+ challengeId : challengeData . id ,
69
+ identifier : `${ accountName } .${ keySlot } ` ,
70
+ } )
71
+
72
+ router . push ( redirectUri ?? '/' )
73
+ } catch ( error ) {
74
+ toast . show ( 'Failed to sign in' , { preset : 'error' , isUrgent : true } )
75
+ setSignInError ( error as Error )
76
+ } finally {
77
+ setIsSigningIn ( false )
78
+ }
79
+ }
25
80
26
81
async function signUpWithPhone ( { phone, countrycode } : z . infer < typeof SignUpSchema > ) {
27
82
const { error } = await signInWithOtp
@@ -134,16 +189,11 @@ export const SignUpForm = () => {
134
189
< Paragraph size = "$2" color = "$color11" >
135
190
Already have an account?
136
191
</ Paragraph >
137
- < SignInButton
138
- setError = { setSignInError }
139
- unstyled
140
- color = "$color11"
141
- renderButtonText = { ( isSigningIn ) => (
142
- < ButtonText textDecorationLine = "underline" >
143
- { isSigningIn ? 'Signing in...' : 'Sign in' }
144
- </ ButtonText >
145
- ) }
146
- />
192
+ < SubmitButton onPress = { handleSignIn } disabled = { isSigningIn } unstyled >
193
+ < ButtonText color = "$color11" size = "$2" textDecorationLine = "underline" >
194
+ { isSigningIn ? 'Signing in...' : 'Sign in' }
195
+ </ ButtonText >
196
+ </ SubmitButton >
147
197
</ XStack >
148
198
149
199
{ signInError && (
0 commit comments