Skip to content

Commit 4c333ed

Browse files
stormcloud266youngkidwarrior
authored andcommitted
remove sign-in page
1 parent 4e1ef47 commit 4c333ed

File tree

6 files changed

+151
-107
lines changed

6 files changed

+151
-107
lines changed

packages/app/features/auth/components/SignInButton.tsx

-74
This file was deleted.

packages/app/features/auth/sign-up/sign-up-form.tsx

+67-17
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
1+
import { useState } from 'react'
12
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'
313
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'
419
import { VerifyCode } from 'app/features/auth/components/VerifyCode'
520
import { SchemaForm, formFields } from 'app/utils/SchemaForm'
621
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'
1325

1426
const SignUpSchema = z.object({
1527
countrycode: formFields.countrycode,
@@ -20,8 +32,51 @@ export const SignUpForm = () => {
2032
const form = useForm<z.infer<typeof SignUpSchema>>()
2133
const signInWithOtp = api.auth.signInWithOtp.useMutation()
2234
const router = useRouter()
35+
const [queryParams] = useAuthScreenParams()
36+
const { redirectUri } = queryParams
37+
const toast = useToastController()
2338
const [captchaToken, setCaptchaToken] = useState<string | undefined>()
2439
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+
}
2580

2681
async function signUpWithPhone({ phone, countrycode }: z.infer<typeof SignUpSchema>) {
2782
const { error } = await signInWithOtp
@@ -134,16 +189,11 @@ export const SignUpForm = () => {
134189
<Paragraph size="$2" color="$color11">
135190
Already have an account?
136191
</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>
147197
</XStack>
148198

149199
{signInError && (

packages/app/features/splash/screen.tsx

+59-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
Button,
3+
ButtonText,
34
H1,
45
LinearGradient,
56
Paragraph,
@@ -18,14 +19,14 @@ import { SolitoImage } from 'solito/image'
1819
import { useLink } from 'solito/link'
1920
import { AnimationLayout } from '../../components/layout/animation-layout'
2021
import { useState } from 'react'
21-
import { SignInButton } from '../auth/components/SignInButton'
22-
23-
export const formatErrorMessage = (error: Error) => {
24-
if (error.message.startsWith('The operation either timed out or was not allowed')) {
25-
return 'Passkey Authentication Failed'
26-
}
27-
return error.message
28-
}
22+
import { formatErrorMessage } from 'app/utils/formatErrorMessage'
23+
import { RecoveryOptions } from '@my/api/src/routers/account-recovery/types'
24+
import { SubmitButton, useToastController } from '@my/ui'
25+
import { api } from 'app/utils/api'
26+
import { signChallenge } from 'app/utils/signChallenge'
27+
import { useRouter } from 'solito/router'
28+
import { bytesToHex, hexToBytes } from 'viem'
29+
import { useAuthScreenParams } from 'app/routers/params'
2930

3031
export function SplashScreen() {
3132
return (
@@ -149,7 +150,7 @@ function Hero() {
149150
height={isWeb ? '100dvh' : '100%'}
150151
>
151152
<Stack
152-
bc="$black"
153+
bc="$color1"
153154
pos="absolute"
154155
top={0}
155156
left={0}
@@ -243,8 +244,52 @@ function Hero() {
243244
}
244245

245246
function AuthButtons() {
246-
const [signInError, setSignInError] = useState<Error | null>(null)
247+
const [queryParams] = useAuthScreenParams()
248+
const { redirectUri } = queryParams
249+
const toast = useToastController()
250+
const router = useRouter()
247251
const signUpLink = useLink({ href: '/auth/sign-up' })
252+
const [signInError, setSignInError] = useState<Error | null>(null)
253+
const [isSigningIn, setIsSigningIn] = useState(false)
254+
255+
const { mutateAsync: getChallengeMutateAsync } = api.challenge.getChallenge.useMutation({
256+
retry: false,
257+
})
258+
const { mutateAsync: validateSignatureMutateAsync } = api.challenge.validateSignature.useMutation(
259+
{ retry: false }
260+
)
261+
262+
const handleSignIn = async () => {
263+
setIsSigningIn(true)
264+
try {
265+
const challengeData = await getChallengeMutateAsync()
266+
267+
const rawIdsB64: { id: string; userHandle: string }[] = []
268+
const { encodedWebAuthnSig, accountName, keySlot } = await signChallenge(
269+
challengeData.challenge as `0x${string}`,
270+
rawIdsB64
271+
)
272+
273+
const encodedWebAuthnSigBytes = hexToBytes(encodedWebAuthnSig)
274+
const newEncodedWebAuthnSigBytes = new Uint8Array(encodedWebAuthnSigBytes.length + 1)
275+
newEncodedWebAuthnSigBytes[0] = keySlot
276+
newEncodedWebAuthnSigBytes.set(encodedWebAuthnSigBytes, 1)
277+
278+
await validateSignatureMutateAsync({
279+
recoveryType: RecoveryOptions.WEBAUTHN,
280+
signature: bytesToHex(newEncodedWebAuthnSigBytes),
281+
challengeId: challengeData.id,
282+
identifier: `${accountName}.${keySlot}`,
283+
})
284+
285+
router.push(redirectUri ?? '/')
286+
} catch (error) {
287+
toast.show('Failed to sign in', { preset: 'error', isUrgent: true })
288+
setSignInError(error as Error)
289+
} finally {
290+
setIsSigningIn(false)
291+
}
292+
}
248293

249294
return (
250295
<XStack
@@ -256,7 +301,10 @@ function AuthButtons() {
256301
w="100%"
257302
alignSelf="center"
258303
>
259-
<SignInButton setError={setSignInError} size="$4" w="$12" />
304+
<SubmitButton size="$4" w="$12" onPress={handleSignIn} disabled={isSigningIn}>
305+
<ButtonText>{isSigningIn ? 'SIGNING IN...' : 'SIGN-IN'}</ButtonText>
306+
</SubmitButton>
307+
260308
<Button {...signUpLink} borderColor="$primary" variant="outlined" size="$4" w="$12">
261309
<Button.Text color="$white" $gtMd={{ color: '$color12' }}>
262310
SIGN-UP

packages/app/features/unknown/screen.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
import { Button, Container, H1, H2, YStack } from '@my/ui'
2-
import { Link } from 'solito/link'
1+
import { Container, H1, H2, YStack, LinkableButton } from '@my/ui'
32

43
export function UnknownScreen() {
54
return (
65
<Container>
76
<YStack jc={'center'} alignItems="center" f={1} gap="$6">
87
<H1>Not found.</H1>
98
<H2>Send, Instant Payments.</H2>
10-
<Link href="/">
11-
<Button>Need to sign in?</Button>
12-
</Link>
9+
<LinkableButton href="/">Need to sign in?</LinkableButton>
1310
</YStack>
1411
</Container>
1512
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { formatErrorMessage } from './formatErrorMessage'
2+
3+
describe('formatErrorMessage', () => {
4+
it('should return "Passkey Authentication Failed"', () => {
5+
const error = new Error(
6+
'The operation either timed out or was not allowed due to security reasons'
7+
)
8+
const result = formatErrorMessage(error)
9+
expect(result).toBe('Passkey Authentication Failed')
10+
})
11+
12+
it('should return the original error message', () => {
13+
const error = new Error('Some other error message')
14+
const result = formatErrorMessage(error)
15+
expect(result).toBe('Some other error message')
16+
})
17+
})
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const formatErrorMessage = (error: Error) => {
2+
if (error.message.startsWith('The operation either timed out or was not allowed')) {
3+
return 'Passkey Authentication Failed'
4+
}
5+
return error.message
6+
}

0 commit comments

Comments
 (0)