UNPKG

@0xsequence/connect

Version:
129 lines â€Ē 9.85 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { Button, Divider, PINCodeInput, Spinner, Text, TextInput, useToast } from '@0xsequence/design-system'; import { GoogleLogin } from '@react-oauth/google'; import { ethers } from 'ethers'; import { useEffect, useRef, useState } from 'react'; import AppleSignin from 'react-apple-signin-auth'; import { LocalStorageKey } from '../../constants/localStorage.js'; import { useSequenceWaaS } from '../../hooks/useSequenceWaaS.js'; import { useStorageItem } from '../../hooks/useStorage.js'; import { isAccountAlreadyLinkedError, useEmailAuth } from '../../utils/useEmailAuth.js'; import { AccountName } from './AccountName.js'; export function SocialLink() { const toast = useToast(); const [currentAccount, setCurrentAccount] = useState(); const [accounts, setAccounts] = useState(); const [loading, setLoading] = useState(true); const [error, setError] = useState(); const [email, setEmail] = useState(''); const inputRef = useRef(null); const isEmailValid = inputRef.current?.validity.valid; const [showEmailWarning, setEmailWarning] = useState(false); const [code, setCode] = useState([]); const sequenceWaaS = useSequenceWaaS(); const { data: googleClientId } = useStorageItem(LocalStorageKey.WaasGoogleClientID); const { data: appleClientId } = useStorageItem(LocalStorageKey.WaasAppleClientID); const { inProgress: emailAuthInProgress, loading: emailAuthLoading, initiateAuth: initiateEmailAuth, sendChallengeAnswer } = useEmailAuth({ sessionName: randomName(), onSuccess: async ({ wallet }) => { console.log(`Wallet address: ${wallet}`); }, linkAccount: true }); const removeAccount = async (id) => { setLoading(true); setAccounts(undefined); try { await sequenceWaaS.removeAccount(id); const response = await sequenceWaaS.listAccounts(); setAccounts(response.accounts); } catch (e) { setError(getMessageFromUnknownError(e)); const response = await sequenceWaaS.listAccounts(); setAccounts(response.accounts); } setLoading(false); }; const handleGoogleLogin = async (tokenResponse) => { const challenge = await sequenceWaaS.initAuth({ idToken: tokenResponse.credential }); try { const linkResponse = await sequenceWaaS.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; const handleAppleLogin = async (response) => { const challenge = await sequenceWaaS.initAuth({ idToken: response.authorization.id_token }); try { const linkResponse = await sequenceWaaS.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' }); } } }; useEffect(() => { sequenceWaaS .listAccounts() .then(response => { setAccounts(response.accounts); if (response.currentAccountId) { setCurrentAccount(response.accounts.find(account => account.id === response.currentAccountId)); } setLoading(false); }) .catch((e) => { setError(getMessageFromUnknownError(e)); setLoading(false); }); }, [emailAuthInProgress]); return (_jsxs("div", { className: "p-4", children: [_jsxs("div", { className: "flex flex-col gap-4 mb-5", children: [_jsx(Text, { variant: "normal", color: "text100", fontWeight: "bold", children: "Your connected (linked) accounts" }), accounts && (_jsx(_Fragment, { children: accounts.map(a => (_jsxs("div", { className: "flex flex-row items-center gap-2", children: [_jsx(Text, { variant: "normal", color: "text100", children: _jsx(AccountName, { acc: a }) }), a.id !== currentAccount?.id && _jsx(Button, { size: "xs", label: "Remove", onClick: () => removeAccount(a.id) }), a.id === currentAccount?.id && (_jsx("div", { children: _jsx(Text, { variant: "small", color: "text100", children: "(Account you logged in with)" }) }))] }, a.id))) })), loading && _jsx(Spinner, {})] }), _jsx(Divider, {}), _jsxs("div", { className: "flex flex-col gap-2 w-full", children: [_jsx(Text, { variant: "large", color: "text100", fontWeight: "bold", className: "mb-5", children: "Connect (link) another login method" }), _jsxs("div", { className: "flex flex-col w-fit gap-2", children: [googleClientId && _jsx(GoogleLogin, { onSuccess: handleGoogleLogin, shape: "circle", width: "100%" }), appleClientId && ( // @ts-ignore _jsx(AppleSignin, { authOptions: { clientId: appleClientId, scope: 'openid email', redirectURI: appleRedirectUri, usePopup: true }, onError: (error) => console.error(error), onSuccess: handleAppleLogin, uiType: "dark" }))] }), _jsx(Divider, {}), _jsx("div", { className: "mt-2", children: _jsx(Text, { variant: "normal", color: "text100", fontWeight: "bold", children: "Email" }) }), sendChallengeAnswer ? (_jsxs("div", { className: "flex flex-col", children: [_jsx("div", { className: "mt-3", children: _jsx(Text, { className: "mt-5", variant: "normal", color: "text80", children: "Enter code received in email." }) }), _jsx("div", { className: "mt-4", children: _jsx(PINCodeInput, { value: code, digits: 6, onChange: setCode }) }), _jsx("div", { className: "flex gap-2 my-4", children: emailAuthLoading ? (_jsx(Spinner, {})) : (_jsx(Button, { variant: "primary", disabled: code.includes(''), label: "Verify", onClick: () => sendChallengeAnswer(code.join('')), "data-id": "verifyButton" })) })] })) : (_jsxs("div", { className: "mb-4", children: [_jsxs(Text, { variant: "normal", color: "text80", children: ["Enter your email to recieve a code to login and create your wallet. ", _jsx("br", {}), "Please check your spam folder if you don't see it in your inbox."] }), _jsxs("div", { className: "mt-6", children: [_jsx(TextInput, { name: "email", type: "email", onChange: (ev) => { setEmail(ev.target.value); }, ref: inputRef, onKeyDown: (ev) => { if (email && ev.key === 'Enter') { initiateEmailAuth(email); } }, onBlur: () => setEmailWarning(!!email && !isEmailValid), value: email, placeholder: "hello@example.com", required: true, "data-id": "loginEmail" }), showEmailWarning && (_jsx(Text, { variant: "small", color: "negative", className: "my-2 text-red-500", children: "Invalid email address" }))] }), _jsx("div", { className: "flex gap-2 my-4 items-center justify-center", children: emailAuthLoading ? (_jsx(Spinner, {})) : (_jsx(Button, { variant: "primary", disabled: !isEmailValid, label: "Continue", onClick: () => initiateEmailAuth(email), "data-id": "continueButton" })) })] }))] }), error && (_jsxs(Text, { variant: "normal", color: "text100", fontWeight: "bold", children: ["Error loading accounts: ", error] }))] })); } const DEVICE_EMOJIS = [ // 256 emojis for unsigned byte range 0 - 255 ...'ðŸķðŸąðŸ­ðŸđ🐰ðŸĶŠðŸŧ🐞ðŸĻðŸŊðŸĶðŸŪðŸ·ðŸ―ðŸļðŸĩ🙈🙉🙊🐒🐔🐧ðŸĶðŸĪðŸĢðŸĨðŸĶ†ðŸĶ…ðŸĶ‰ðŸĶ‡ðŸšðŸ—ðŸīðŸĶ„🐝🐛ðŸĶ‹ðŸŒðŸžðŸœðŸĶŸðŸĶ—🕷ðŸ•ļðŸĶ‚ðŸĒ🐍ðŸĶŽðŸĶ–ðŸĶ•🐙ðŸĶ‘ðŸĶðŸĶžðŸĶ€ðŸĄðŸ ðŸŸðŸŽðŸģ🐋ðŸĶˆðŸŠðŸ…🐆ðŸĶ“ðŸĶðŸĶ§ðŸ˜ðŸĶ›ðŸĶðŸŠðŸŦðŸĶ’ðŸĶ˜ðŸƒðŸ‚🐄🐎🐖🐏🐑ðŸĶ™ðŸðŸĶŒðŸ•ðŸĐðŸĶŪ🐈🐓ðŸĶƒðŸĶšðŸĶœðŸĶĒðŸĶĐ🕊🐇ðŸĶðŸĶĻðŸĶĄðŸĶĶðŸĶĨ🐁🐀ðŸŋðŸĶ”ðŸū🐉ðŸēðŸŒĩ🎄ðŸŒēðŸŒģðŸŒīðŸŒąðŸŒŋ🍀🎍🎋🍃ðŸ‘Ģ🍂🍁🍄🐚ðŸŒū💐🌷ðŸŒđðŸĨ€ðŸŒšðŸŒļ🌞ðŸŒŧ🌞🌝🍏🍎🍐🍊🍋🍌🍉🍇🍓🍈ðŸĨ­ðŸðŸĨĨðŸĨðŸ…ðŸĨ‘ðŸĨĶðŸĨŽðŸĨ’ðŸŒķðŸŒ―ðŸĨ•🧄🧅ðŸĨ”🍠ðŸĨðŸĨŊ🍞ðŸĨ–ðŸĨĻ🧀ðŸĨšðŸģ🧈ðŸĨžðŸ§‡ðŸĨ“ðŸĨĐ🍗🍖ðŸĶī🌭🍔🍟🍕ðŸĨŠðŸĨ™ðŸ§†ðŸŒŪðŸŒŊðŸĨ—ðŸĨ˜ðŸĨŦ🍝🍜ðŸē🍛ðŸĢðŸąðŸĨŸðŸĶŠðŸĪ🍙🍚🍘ðŸĨðŸĨ ðŸĨŪðŸĒðŸĄðŸ§ðŸĻðŸĶðŸĨ§ðŸ§ðŸ°ðŸŽ‚ðŸŪ🍭🍎ðŸŦðŸŋðŸĐ🍊🌰ðŸĨœðŸ‘€ðŸ‘‚👃👄👅👆👇👈👉👊👋👌👍👎👏👐👑👒👓ðŸŽŊðŸŽ°ðŸŽąðŸŽēðŸŽģðŸ‘ūðŸ‘Ŋ👚ðŸ‘ŧðŸ‘―ðŸ‚ðŸƒðŸ„' ]; function randomName() { const wordlistSize = 2048; const words = ethers.wordlists.en; const randomEmoji = DEVICE_EMOJIS[Math.floor(Math.random() * DEVICE_EMOJIS.length)]; const randomWord1 = words.getWord(Math.floor(Math.random() * wordlistSize)); const randomWord2 = words.getWord(Math.floor(Math.random() * wordlistSize)); return `${randomEmoji} ${randomWord1} ${randomWord2}`; } function getMessageFromUnknownError(e) { if (e && typeof e === 'object' && 'message' in e && e.message && typeof e.message === 'string') { return e.message; } return 'unknown error'; } //# sourceMappingURL=SocialLink.js.map