Skip to content

Commit

Permalink
Email Waas Upgrade (#107)
Browse files Browse the repository at this point in the history
* Updating sequence to v1.10.0

* Updating sequence.js to 1.10.3

* Support legacy and modern versions of waas email authentication

* Fixing sendChallengeAnswer function

* Adding emailAuthVersion optional param to getDefaultConnectors params and emailWaas params

* Removing toast error messages, we don't want to include additional ui components to a dapp, include the error message inline

* Updating docs to include emailAuthVersion

* Adding onEmailConflict to useWaasEmailAuth

* email v2 auth working with onEmailAuthCodeRequired and onEmailConflict

* Refactoring onSuccess

* Fix persisting WaasActiveLoginType

* Remove nonce related code

* Refactor SequenceWaasProvider args

* Adding email conflict handling

* Updating sequence.js to v1.10.7

* Refactored Email waas verification

* Add FormattedEmailConflictInfo

---------

Co-authored-by: Tolgahan Arikan <[email protected]>
  • Loading branch information
corbanbrook and tolgahan-arikan authored Aug 2, 2024
1 parent 6cfb2d3 commit 84c8340
Show file tree
Hide file tree
Showing 35 changed files with 619 additions and 410 deletions.
35 changes: 26 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,44 @@ import { mainnet, polygon, Chain } from 'wagmi/chains'
const queryClient = new QueryClient()

function App() {
const projectAccessKey = '<your-project-access-key>'

const chains = getDefaultChains(/* optional array of chain ids to filter */)

const projectAccessKey = 'xyz'
const transports = {}

chains.forEach(chain => {
transports[chain.id] = http()
})

// Universal wallet configuration
const connectors = getDefaultConnectors({
walletConnectProjectId: 'wallet-connect-id',
projectAccessKey,
walletConnectProjectId: '<your-wallet-connect-id>',
defaultChainId: 137,
appName: 'demo app',
projectAccessKey
appName: 'Demo Dapp'
})

const transports = {}
/*
// ...or for Embedded wallet configuration
const connectors = getDefaultWaasConnectors({
projectAccessKey,
walletConnectProjectId: '<your-wallet-connect-id>',
defaultChainId: 137,
appName: 'Demo Dapp',
chains.forEach(chain => {
transports[chain.id] = http()
waasConfigKey: '<your-waas-config-key>',
googleClientId,
appleClientId,
appleRedirectUrl,
emailAuthVersion // (default 2), 1 for legacy
})
*/

const config = createConfig({
chains,
transports,
connectors,
chains
connectors
})

return (
Expand Down
2 changes: 1 addition & 1 deletion examples/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"peerDependencies": {
"@0xsequence/design-system": ">= 1.7.3",
"@0xsequence/network": ">= 1.9.37",
"@0xsequence/network": ">= 1.10.7",
"wagmi": "*"
},
"private": true
Expand Down
2 changes: 1 addition & 1 deletion examples/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@0xsequence/kit-checkout": "workspace:*",
"@0xsequence/kit-wallet": "workspace:*",
"@0xsequence/kit-example-shared-components": "workspace:*",
"@0xsequence/network": "^1.9.37",
"@0xsequence/network": "^1.10.7",
"@tanstack/react-query": "^5.37.1",
"next": "14.2.3",
"react": "^18.3.1",
Expand Down
2 changes: 1 addition & 1 deletion examples/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@0xsequence/kit-checkout": "workspace:*",
"@0xsequence/kit-wallet": "workspace:*",
"@0xsequence/kit-example-shared-components": "workspace:*",
"@0xsequence/network": "^1.9.37",
"@0xsequence/network": "^1.10.7",
"@tanstack/react-query": "^5.37.1",
"framer-motion": "^8.5.2",
"react": "^18.3.1",
Expand Down
1 change: 1 addition & 0 deletions examples/react/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const getWaasConnectors = () => {
appleRedirectURI,
appName: 'Kit Demo',
projectAccessKey,
// emailAuthVersion: 1,
enableConfirmationModal: localStorage.getItem('confirmationEnabled') === 'true',
isDev: isDebugMode
})
Expand Down
10 changes: 5 additions & 5 deletions packages/checkout/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@0xsequence/api": "^1.9.37",
"@0xsequence/indexer": "^1.9.37",
"@0xsequence/metadata": "^1.9.37",
"@0xsequence/network": "^1.9.37",
"@0xsequence/api": "^1.10.7",
"@0xsequence/indexer": "^1.10.7",
"@0xsequence/metadata": "^1.10.7",
"@0xsequence/network": "^1.10.7",
"@paperxyz/react-client-sdk": "^1.1.3",
"@tanstack/react-query": "^5.37.1",
"0xsequence": "^1.9.37",
"0xsequence": "^1.10.7",
"react-copy-to-clipboard": "^5.1.0"
},
"peerDependencies": {
Expand Down
22 changes: 11 additions & 11 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,22 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@0xsequence/api": "^1.9.37",
"@0xsequence/auth": "^1.9.37",
"@0xsequence/core": "^1.9.37",
"@0xsequence/api": "^1.10.7",
"@0xsequence/auth": "^1.10.7",
"@0xsequence/core": "^1.10.7",
"@0xsequence/design-system": "^1.7.3",
"@0xsequence/ethauth": "^0.8.1",
"@0xsequence/indexer": "^1.9.37",
"@0xsequence/metadata": "^1.9.37",
"@0xsequence/network": "^1.9.37",
"@0xsequence/provider": "^1.9.37",
"@0xsequence/utils": "^1.9.37",
"@0xsequence/indexer": "^1.10.7",
"@0xsequence/metadata": "^1.10.7",
"@0xsequence/network": "^1.10.7",
"@0xsequence/provider": "^1.10.7",
"@0xsequence/utils": "^1.10.7",
"framer-motion": "^8.5.2",
"uuid": "^10.0.0"
},
"peerDependencies": {
"0xsequence": ">= 1.9.37",
"@0xsequence/waas": ">= 1.9.37",
"0xsequence": ">= 1.10.7",
"@0xsequence/waas": ">= 1.10.7",
"@react-oauth/google": ">= 0.11.1",
"@tanstack/react-query": ">= 5.0.0",
"ethers": ">= 5.7.2 < 6",
Expand All @@ -62,7 +62,7 @@
"wagmi": ">= 2.0.0"
},
"devDependencies": {
"0xsequence": "^1.9.37",
"0xsequence": "^1.10.7",
"@tanstack/react-query": "^5.37.1",
"@types/uuid": "^9.0.8",
"ethers": "5.7.2",
Expand Down
1 change: 1 addition & 0 deletions packages/kit/src/components/CollectibleTileImage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CollectibleTileImage } from './CollectibleTileImage'
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Box, Image } from '@0xsequence/design-system'
import React from 'react'

import { KitConfig } from '../../../types'
import { KitConfig } from '../../types'

interface BannerProps {
config: KitConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,44 @@ import {
TextInput,
Spinner,
Image,
IconButton,
PINCodeInput
IconButton
} from '@0xsequence/design-system'
import React, { useState, useEffect } from 'react'
import { appleAuthHelpers, useScript } from 'react-apple-signin-auth'
import { useConnect, useAccount } from 'wagmi'

import { LocalStorageKey } from '../../../constants'
import { useStorage } from '../../../hooks/useStorage'
import { useEmailAuth } from '../../../hooks/useWaasEmailAuth'
import { ExtendedConnector, KitConfig, LogoProps } from '../../../types'
import { isEmailValid } from '../../../utils/helpers'
import { AppleWaasConnectButton, ConnectButton, EmailConnectButton, GoogleWaasConnectButton } from '../../ConnectButton'
import { KitConnectProviderProps } from '../index'
import { LocalStorageKey } from '../../constants'
import { useStorage } from '../../hooks/useStorage'
import { useEmailAuth } from '../../hooks/useWaasEmailAuth'
import { FormattedEmailConflictInfo } from '../../hooks/useWaasEmailConflict'
import { ExtendedConnector, KitConfig, LogoProps } from '../../types'
import { isEmailValid } from '../../utils/helpers'
import { AppleWaasConnectButton, ConnectButton, EmailConnectButton, GoogleWaasConnectButton } from '../ConnectButton'
import { KitConnectProviderProps } from '../KitProvider/KitProvider'
import { PoweredBySequence } from '../SequenceLogo'

import { Banner } from './Banner'
import { EmailWaasVerify } from './EmailWaasVerify'
import { ExtendedWalletList } from './ExtendedWalletList'

interface ConnectWalletContentProps extends KitConnectProviderProps {
openConnectModal: boolean
setOpenConnectModal: React.Dispatch<React.SetStateAction<boolean>>
emailConflictInfo?: FormattedEmailConflictInfo | null
onClose: () => void
}

export const ConnectWalletContent = (props: ConnectWalletContentProps) => {
export const Connect = (props: ConnectWalletContentProps) => {
useScript(appleAuthHelpers.APPLE_SCRIPT_SRC)

const storage = useStorage()
const { isConnected } = useAccount()
const { config = {} } = props
const { onClose, emailConflictInfo, config = {} } = props
const { signIn = {} } = config as KitConfig

const { openConnectModal, setOpenConnectModal } = props
const { isConnected } = useAccount()
const storage = useStorage()

const [email, setEmail] = useState('')
const [showEmailInput, setShowEmailInput] = useState<boolean>(false)
const [showEmailWaasPinInput, setShowEmailWaasPinInput] = useState(false)
const [showExtendedList, setShowExtendedList] = useState<boolean>(false)
const [waasEmailPinCode, setWaasEmailPinCode] = useState<string[]>([])
const { connectors, connect } = useConnect()

const hasInjectedSequenceConnector = connectors.some(c => c.id === 'app.sequence')

const baseWalletConnectors = (connectors as ExtendedConnector[])
Expand Down Expand Up @@ -105,26 +103,12 @@ export const ConnectWalletContent = (props: ConnectWalletContentProps) => {
setEmail(ev.target.value)
}

const {
inProgress: emailAuthInProgress,
loading: emailAuthLoading,
initiateAuth: initiateEmailAuth,
sendChallengeAnswer
} = useEmailAuth({
connector: socialAuthConnectors.find(c => c._wallet.id === 'email-waas'),
onSuccess: async idToken => {
storage?.setItem(LocalStorageKey.WaasEmailIdToken, idToken)
if (emailConnector) {
connect({ connector: emailConnector })
}
}
})

// Close after successful connection
useEffect(() => {
if (isConnected && openConnectModal) {
setOpenConnectModal(false)
if (isConnected) {
onClose()
}
}, [isConnected, openConnectModal])
}, [isConnected])

const onConnect = (connector: ExtendedConnector) => {
if (signIn.useMock && mockConnector) {
Expand Down Expand Up @@ -170,31 +154,37 @@ export const ConnectWalletContent = (props: ConnectWalletContentProps) => {
}
}

const {
inProgress: emailAuthInProgress,
loading: emailAuthLoading,
error: emailAuthError,
initiateAuth: initiateEmailAuth,
sendChallengeAnswer
} = useEmailAuth({
connector: emailConnector,
onSuccess: async result => {
console.log('Successfult email auth', result)

if (emailConnector) {
if (result.version === 1) {
// Store the version 1 idToken so that it can be used to authenticate during a refresh
storage?.setItem(LocalStorageKey.WaasEmailIdToken, result.idToken)
}

connect({ connector: emailConnector })
}
}
})

// Hide the email input if there is an email conflict
useEffect(() => {
if (emailConflictInfo) {
setShowEmailWaasPinInput(false)
}
}, [emailConflictInfo])

if (showEmailWaasPinInput) {
return (
<>
<Box paddingY="6" alignItems="center" justifyContent="center" flexDirection="column">
<Text marginTop="5" marginBottom="4" variant="normal" color="text80">
Enter code received in email.
</Text>
<PINCodeInput value={waasEmailPinCode} digits={6} onChange={setWaasEmailPinCode} />

<Box gap="2" marginY="4" alignItems="center" justifyContent="center" style={{ height: '44px' }}>
{emailAuthLoading ? (
<Spinner />
) : (
<Button
variant="primary"
disabled={waasEmailPinCode.includes('')}
label="Verify"
onClick={() => sendChallengeAnswer?.(waasEmailPinCode.join(''))}
data-id="verifyButton"
/>
)}
</Box>
</Box>
</>
)
return <EmailWaasVerify error={emailAuthError} isLoading={emailAuthLoading} onConfirm={sendChallengeAnswer} />
}

if (showExtendedList) {
Expand Down Expand Up @@ -268,6 +258,7 @@ export const ConnectWalletContent = (props: ConnectWalletContentProps) => {
</Box>
</>
)}

<Box marginTop="2" gap="2" flexDirection="row" justifyContent="center" alignItems="center">
{walletConnectors.slice(0, 7).map(connector => {
return <ConnectButton key={connector.uid} connector={connector} onConnect={onConnect} />
Expand All @@ -290,6 +281,8 @@ export const ConnectWalletContent = (props: ConnectWalletContentProps) => {
</>
)}
</Box>

<PoweredBySequence />
</>
)
}
42 changes: 42 additions & 0 deletions packages/kit/src/components/Connect/EmailWaasVerify.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Box, Button, PINCodeInput, Spinner, Text } from '@0xsequence/design-system'
import { useState } from 'react'

interface EmailWaasVerifyProps {
isLoading: boolean
error?: Error
onConfirm: (answer: string) => void
}

export const EmailWaasVerify = (props: EmailWaasVerifyProps) => {
const { isLoading, error, onConfirm } = props
const [waasEmailPinCode, setWaasEmailPinCode] = useState<string[]>([])

return (
<>
<Box paddingY="6" alignItems="center" justifyContent="center" flexDirection="column">
<Text marginTop="5" marginBottom="4" variant="normal" color="text80">
Enter code received in email.
</Text>
<PINCodeInput value={waasEmailPinCode} digits={6} group={3} onChange={setWaasEmailPinCode} disabled={isLoading} />

<Box gap="4" marginTop="4" alignItems="center" justifyContent="center" flexDirection="column">
<Button
variant="primary"
disabled={waasEmailPinCode.includes('') || isLoading}
label="Confirm"
onClick={() => onConfirm(waasEmailPinCode.join(''))}
data-id="verifyButton"
/>

{isLoading && <Spinner />}

{error && (
<Text variant="small" color="negative" textAlign="center">
{error.message}
</Text>
)}
</Box>
</Box>
</>
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Box, Button, Text, useTheme } from '@0xsequence/design-system'
import React from 'react'
import { useConnect } from 'wagmi'

import { ExtendedConnector } from '../../../types'
import { ExtendedConnector } from '../../types'

interface ExtendedWalletListProps {
onConnect: (connector: ExtendedConnector) => void
Expand Down
1 change: 1 addition & 0 deletions packages/kit/src/components/Connect/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Connect } from './Connect'
Loading

0 comments on commit 84c8340

Please sign in to comment.