Skip to content

Commit

Permalink
Show toast error for AccountAlreadyLinked, minor UI fixes (#31)
Browse files Browse the repository at this point in the history
* Show toast error for AccountAlreadyLinked, minor UI fixes

* Remove all session hash related code (except old email login)
  • Loading branch information
tolgahan-arikan authored Jul 18, 2024
1 parent 0f563e1 commit 95eef90
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 99 deletions.
91 changes: 42 additions & 49 deletions src/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import { router, sequence } from './main'
import { PINCodeInput } from './components/PINCodeInput'
import { Logo } from './components/Logo'
import { EmailConflictWarning } from './components/views/EmailConflictWarningView.tsx'
import { StytchLogin } from './components/StytchLogin.tsx'

import { randomName } from './utils/indexer'
import { useEmailAuth } from './utils/useEmailAuth.ts'
import { useSessionHash } from './utils/useSessionHash.ts'
import { useEmailAuthV2 } from './utils/useEmailAuthV2.ts'
import { StytchLogin } from './components/StytchLogin.tsx'

function Login() {
const { sessionHash } = useSessionHash()
const [email, setEmail] = useState('')
const inputRef = useRef<HTMLInputElement | null>(null)
const isEmailValid = inputRef.current?.validity.valid
Expand Down Expand Up @@ -55,10 +53,10 @@ function Login() {
console.log('Sequence response:', seqRes)
router.navigate('/')
} catch (e) {
console.error(e)
console.error('Error: ' + JSON.stringify(error))
}
} else if (error) {
console.log('Error: ' + JSON.stringify(error))
console.error('Error: ' + JSON.stringify(error))
}
}
)
Expand Down Expand Up @@ -262,61 +260,56 @@ function Login() {

<Divider background="buttonGlass" />

<Box paddingY="4" gap="4" flexDirection="column" width="fit">
{!emailAuthInProgress && !!sessionHash && (
<Box paddingY="4" gap="4" flexDirection="column" width="full">
{!emailAuthInProgress && (
<>
<Box marginBottom="4">
<Box marginBottom="2">
<Text variant="large" color="text100" fontWeight="bold">
Social Login
</Text>
</Box>
{import.meta.env.VITE_GOOGLE_CLIENT_ID && (
<Box>
<GoogleLogin
key={'google-' + sessionHash}
onSuccess={handleGoogleLogin}
shape="circle"
width={230}
nonce={sessionHash}
<Box gap="4" flexDirection="column" width="fit">
{import.meta.env.VITE_GOOGLE_CLIENT_ID && (
<Box>
<GoogleLogin key="google" onSuccess={handleGoogleLogin} shape="circle" width={230} />
</Box>
)}
{import.meta.env.VITE_APPLE_CLIENT_ID && (
<AppleSignin
key="apple"
authOptions={{
clientId: import.meta.env.VITE_APPLE_CLIENT_ID,
scope: 'openid email',
redirectURI: appleRedirectUri,
usePopup: true
}}
onError={(error: any) => console.error(error)}
onSuccess={handleAppleLogin}
uiType="dark"
/>
)}
</Box>

<Divider background="buttonGlass" width="full" />

{import.meta.env.VITE_PLAYFAB_TITLE_ID && (
<Box>
<Box marginBottom="4">
<Text variant="large" color="text100" fontWeight="bold">
Playfab login
</Text>
</Box>

<Box>
<Button label="Login with Google (through Playfab)" onClick={handleGooglePlayfabLogin} />
</Box>
</Box>
)}
{import.meta.env.VITE_APPLE_CLIENT_ID && (
<AppleSignin
key={'apple-' + sessionHash}
authOptions={{
clientId: import.meta.env.VITE_APPLE_CLIENT_ID,
scope: 'openid email',
redirectURI: appleRedirectUri,
usePopup: true,
nonce: sessionHash
}}
onError={(error: any) => console.error(error)}
onSuccess={handleAppleLogin}
uiType="dark"
/>
)}

{import.meta.env.VITE_STYTCH_PUBLIC_TOKEN && <StytchLogin />}
</>
)}
</Box>

<Divider background="buttonGlass" />

{import.meta.env.VITE_PLAYFAB_TITLE_ID && (
<Box paddingY="4">
<Box marginBottom="4">
<Text variant="large" color="text100" fontWeight="bold">
Playfab login
</Text>
</Box>

<Box>
<Button label="Login with Google (through Playfab)" onClick={handleGooglePlayfabLogin} />
</Box>
</Box>
)}

{import.meta.env.VITE_STYTCH_PUBLIC_TOKEN && <StytchLogin />}
</Box>

{isEmailConflictModalOpen && (
Expand Down
68 changes: 56 additions & 12 deletions src/components/views/ListAccountsView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, Button, Checkbox, Divider, PINCodeInput, Spinner, Text, TextInput } from '@0xsequence/design-system'
import {SetStateAction, useEffect, useRef, useState} from 'react'
import { Box, Button, Checkbox, Divider, PINCodeInput, Spinner, Text, TextInput, useToast } from '@0xsequence/design-system'
import { SetStateAction, useEffect, useRef, useState } from 'react'
import { Account, IdentityType } from '@0xsequence/waas'
import { CredentialResponse, GoogleLogin, useGoogleLogin } from '@react-oauth/google'
import AppleSignin from 'react-apple-signin-auth'
Expand All @@ -8,18 +8,31 @@ import { sequence } from '../../main'

import { useEmailAuthV2 } from '../../utils/useEmailAuthV2'
import { randomName } from '../../utils/indexer'
import { isAccountAlreadyLinkedError } from '../../utils/error'

export function accountToName(acc: Account) {
if (acc.type === IdentityType.Email) {
return <>Email ({acc.email})</>
return (
<Text variant="normal" color="text100">
({acc.email})
</Text>
)
}

if (acc.type === IdentityType.Guest) {
return <>Guest account</>
return (
<Text variant="normal" color="text100">
Guest account
</Text>
)
}

if (acc.type === IdentityType.PlayFab) {
return <>PlayFab account ({acc.email})</>
return (
<Text variant="normal" color="text100">
({acc.email})
</Text>
)
}

switch (acc.issuer) {
Expand Down Expand Up @@ -53,6 +66,8 @@ export function accountToName(acc: Account) {
}

export function ListAccountsView() {
const toast = useToast()

const [currentAccount, setCurrentAccount] = useState<Account>()
const [accounts, setAccounts] = useState<Account[]>()
const [loading, setLoading] = useState<boolean>(true)
Expand Down Expand Up @@ -98,33 +113,54 @@ export function ListAccountsView() {

const handleGoogleLogin = async (tokenResponse: CredentialResponse) => {
const challenge = await sequence.initAuth({ idToken: tokenResponse.credential! })
const linkResponse = await sequence.linkAccount(challenge)
setAccounts(accounts => [...(accounts || []), linkResponse.account])

try {
const linkResponse = await sequence.linkAccount(challenge)
setAccounts(accounts => [...(accounts || []), linkResponse.account])
} catch (e) {
if (isAccountAlreadyLinkedError(e)) {
toast({
title: 'Account already linked',
description: 'This account is already linked to another wallet',
variant: 'error'
})
}
}
}

const appleRedirectUri =
'https://' + window.location.host + (window.location.host.includes('github.io') ? '/demo-waas-auth' : '/')
const handleAppleLogin = async (response: { authorization: { id_token: string } }) => {
const challenge = await sequence.initAuth({ idToken: response.authorization.id_token })
const linkResponse = await sequence.linkAccount(challenge)
setAccounts(accounts => [...(accounts || []), linkResponse.account])
try {
const linkResponse = await sequence.linkAccount(challenge)
setAccounts(accounts => [...(accounts || []), linkResponse.account])
} catch (e) {
if (isAccountAlreadyLinkedError(e)) {
toast({
title: 'Account already linked',
description: 'This account is already linked to another wallet',
variant: 'error'
})
}
}
}

const handleGooglePlayfabLogin = useGoogleLogin({
flow: 'implicit',
onSuccess: tokenResponse => {
(window as any).PlayFabClientSDK.LoginWithGoogleAccount(
;(window as any).PlayFabClientSDK.LoginWithGoogleAccount(
{
AccessToken: tokenResponse.access_token, // This access token is generated after a user has signed into Google
CreateAccount: true,
TitleId: import.meta.env.VITE_PLAYFAB_TITLE_ID,
TitleId: import.meta.env.VITE_PLAYFAB_TITLE_ID
},
async (response?: { data: { SessionTicket: string } }, error?: Error) => {
if (response) {
try {
const challange = await sequence.initAuth({
playFabTitleId: import.meta.env.VITE_PLAYFAB_TITLE_ID,
playFabSessionTicket: response.data.SessionTicket,
playFabSessionTicket: response.data.SessionTicket
})

const linkResponse = await sequence.linkAccount(challange)
Expand All @@ -134,6 +170,14 @@ export function ListAccountsView() {
setAccounts(accounts => [...(accounts || []), linkResponse.account])
} catch (e) {
console.error(e)

if (isAccountAlreadyLinkedError(e)) {
toast({
title: 'Account already linked',
description: 'This account is already linked to another wallet',
variant: 'error'
})
}
}
} else if (error) {
console.log('Error: ' + JSON.stringify(error))
Expand Down
22 changes: 11 additions & 11 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import '@0xsequence/design-system/styles.css'
import { ThemeProvider } from '@0xsequence/design-system'
import {createHashRouter, RouterProvider} from 'react-router-dom'
import { ThemeProvider, ToastProvider } from '@0xsequence/design-system'
import { createHashRouter, RouterProvider } from 'react-router-dom'

import Login from './Login.tsx'
import { GoogleOAuthProvider } from '@react-oauth/google'
import { SequenceWaaS } from '@0xsequence/waas'
import App from './App.tsx'
import { ethers } from 'ethers'
import './main.css'
import {MaybeWithStytch} from "./components/MaybeWithStytch.tsx";
import { MaybeWithStytch } from './components/MaybeWithStytch.tsx'

const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID
const GOOGLE_CLIENT_ID_DEV = import.meta.env.VITE_GOOGLE_CLIENT_ID_DEV
Expand Down Expand Up @@ -40,7 +40,7 @@ if (targetEnv === 'dev') {
export const sequence = new SequenceWaaS({
network: 'polygon',
projectAccessKey: projectAccessKey,
waasConfigKey: waasConfigKey,
waasConfigKey: waasConfigKey
})

export const router = createHashRouter([
Expand All @@ -57,13 +57,13 @@ export const router = createHashRouter([
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<ThemeProvider>
<GoogleOAuthProvider clientId={googleClientId}>
<MaybeWithStytch>
<RouterProvider router={router} />
</MaybeWithStytch>
</GoogleOAuthProvider>
<ToastProvider>
<GoogleOAuthProvider clientId={googleClientId}>
<MaybeWithStytch>
<RouterProvider router={router} />
</MaybeWithStytch>
</GoogleOAuthProvider>
</ToastProvider>
</ThemeProvider>
</React.StrictMode>
)


3 changes: 3 additions & 0 deletions src/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const isAccountAlreadyLinkedError = (e: any) => {
return e.name === 'AccountAlreadyLinked'
}
16 changes: 15 additions & 1 deletion src/utils/useEmailAuthV2.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useEffect, useState } from 'react'
import { sequence } from '../main'
import { Challenge } from '@0xsequence/waas'
import { isAccountAlreadyLinkedError } from './error'
import { useToast } from '@0xsequence/design-system'

export function useEmailAuthV2({
onSuccess,
Expand All @@ -11,6 +13,8 @@ export function useEmailAuthV2({
sessionName: string
linkAccount?: boolean
}) {
const toast = useToast()

const [error, setError] = useState<unknown>()
const [loading, setLoading] = useState(false)
const [inProgress, setInProgress] = useState(false)
Expand Down Expand Up @@ -50,7 +54,17 @@ export function useEmailAuthV2({
const sendChallengeAnswer = async (answer: string) => {
if (linkAccount && challenge) {
//completeAuth(challenge.withAnswer(answer), { sessionName })
await sequence.linkAccount(challenge.withAnswer(answer))
try {
await sequence.linkAccount(challenge.withAnswer(answer))
} catch (e) {
if (isAccountAlreadyLinkedError(e)) {
toast({
title: 'Account already linked',
description: 'This account is already linked to another wallet',
variant: 'error'
})
}
}
setLoading(false)
setInProgress(false)
return
Expand Down
26 changes: 0 additions & 26 deletions src/utils/useSessionHash.ts

This file was deleted.

0 comments on commit 95eef90

Please sign in to comment.