@0xsequence/connect
Version:
Connect package for Sequence Web SDK
129 lines âĒ 9.85 kB
JavaScript
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