UNPKG

@0xsequence/connect

Version:
347 lines 23.4 kB
"use strict"; 'use client'; Object.defineProperty(exports, "__esModule", { value: true }); exports.Connect = exports.SEQUENCE_UNIVERSAL_CONNECTOR_NAME = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const design_system_1 = require("@0xsequence/design-system"); const hooks_1 = require("@0xsequence/hooks"); const waas_1 = require("@0xsequence/waas"); const tracker_1 = require("@databeat/tracker"); const clsx_1 = require("clsx"); const react_1 = require("react"); const react_apple_signin_auth_1 = require("react-apple-signin-auth"); const wagmi_1 = require("wagmi"); const analytics_js_1 = require("../../constants/analytics.js"); const localStorage_js_1 = require("../../constants/localStorage.js"); const walletLinking_js_1 = require("../../constants/walletLinking.js"); const Analytics_js_1 = require("../../contexts/Analytics.js"); const useStorage_js_1 = require("../../hooks/useStorage.js"); const useWaasEmailAuth_js_1 = require("../../hooks/useWaasEmailAuth.js"); const useWaasLinkWallet_js_1 = require("../../hooks/useWaasLinkWallet.js"); const useWallets_js_1 = require("../../hooks/useWallets.js"); const useWalletSettings_js_1 = require("../../hooks/useWalletSettings.js"); const helpers_js_1 = require("../../utils/helpers.js"); const ConnectButton_js_1 = require("../ConnectButton/ConnectButton.js"); const index_js_1 = require("../ConnectButton/index.js"); const index_js_2 = require("../SequenceLogo/index.js"); const Banner_js_1 = require("./Banner.js"); const ConnectedWallets_js_1 = require("./ConnectedWallets.js"); const EmailWaasVerify_js_1 = require("./EmailWaasVerify.js"); const ExtendedWalletList_js_1 = require("./ExtendedWalletList.js"); const MAX_ITEM_PER_ROW = 4; exports.SEQUENCE_UNIVERSAL_CONNECTOR_NAME = 'Sequence'; const Connect = (props) => { (0, react_apple_signin_auth_1.useScript)(react_apple_signin_auth_1.appleAuthHelpers.APPLE_SCRIPT_SRC); const { analytics } = (0, Analytics_js_1.useAnalyticsContext)(); const { hideExternalConnectOptions, hideConnectedWallets, hideSocialConnectOptions } = (0, useWalletSettings_js_1.useWalletSettings)(); const { onClose, emailConflictInfo, config = {}, isInline = false } = props; const { signIn = {} } = config; const storage = (0, useStorage_js_1.useStorage)(); const descriptiveSocials = !!config?.signIn?.descriptiveSocials; const [isLoading, setIsLoading] = (0, react_1.useState)(false); const projectName = config?.signIn?.projectName; const showWalletAuthOptionsFirst = config?.signIn?.showWalletAuthOptionsFirst ?? false; const [email, setEmail] = (0, react_1.useState)(''); const [showEmailWaasPinInput, setShowEmailWaasPinInput] = (0, react_1.useState)(false); const [showExtendedList, setShowExtendedList] = (0, react_1.useState)(null); const { status, connectors, connect } = (0, wagmi_1.useConnect)(); const connections = (0, wagmi_1.useConnections)(); const { signMessageAsync } = (0, wagmi_1.useSignMessage)(); const { wallets, linkedWallets, disconnectWallet, refetchLinkedWallets } = (0, useWallets_js_1.useWallets)(); const { data: waasStatusData } = (0, hooks_1.useGetWaasStatus)(); const hasConnectedSequenceUniversal = connections.some(c => c.connector.name === exports.SEQUENCE_UNIVERSAL_CONNECTOR_NAME); const hasConnectedSocialOrSequenceUniversal = connections.some(c => c.connector?._wallet?.type === 'social') || hasConnectedSequenceUniversal; const waasConnection = connections.find(c => c.connector?.type === 'sequence-waas'); // Setup wallet linking const { linkWallet, removeLinkedWallet } = (0, useWaasLinkWallet_js_1.useWaasLinkWallet)(waasConnection?.connector); const [lastConnectedWallet, setLastConnectedWallet] = (0, react_1.useState)(undefined); const [isSigningLinkMessage, setIsSigningLinkMessage] = (0, react_1.useState)(false); const handleUnlinkWallet = async (address) => { try { await removeLinkedWallet(address); const parentWallet = wallets.find(w => w.isEmbedded)?.address; try { analytics?.track({ event: 'UNLINK_WALLET', props: { parentWalletAddress: parentWallet ? getUserIdForEvent(parentWallet) : '', linkedWalletAddress: getUserIdForEvent(address), linkedWalletType: linkedWallets?.find(lw => lw.linkedWalletAddress === address)?.walletType || '', source: analytics_js_1.EVENT_SOURCE } }); } catch (e) { console.warn('unlink analytics error:', e); } refetchLinkedWallets(); } catch (e) { console.warn('unlink error:', e); } }; (0, react_1.useEffect)(() => { if (!lastConnectedWallet) { return; } const tryLinkWallet = async () => { const nonWaasWallets = connections.filter(c => c.connector?.type !== 'sequence-waas'); const nonLinkedWallets = nonWaasWallets.filter(c => !linkedWallets?.find(lw => lw.linkedWalletAddress === c.accounts[0].toLowerCase())); if (nonLinkedWallets.map(w => w.accounts[0]).includes(lastConnectedWallet)) { const waasWalletAddress = waasConnection?.accounts[0]; if (!waasWalletAddress) { return; } const childWalletAddress = lastConnectedWallet; const childMessage = `Link to parent wallet with address ${waasWalletAddress}`; setIsSigningLinkMessage(true); let childSignature; try { childSignature = await signMessageAsync({ account: lastConnectedWallet, message: childMessage }); if (!childSignature) { return; } await linkWallet({ signatureChainId: walletLinking_js_1.CHAIN_ID_FOR_SIGNATURE, connectorName: connections.find(c => c.accounts[0] === lastConnectedWallet)?.connector?.name || '', childWalletAddress, childMessage, childSignature }); try { analytics?.track({ event: 'LINK_WALLET', props: { parentWalletAddress: getUserIdForEvent(waasWalletAddress), linkedWalletAddress: getUserIdForEvent(childWalletAddress), linkedWalletType: connections.find(c => c.accounts[0] === lastConnectedWallet)?.connector?.name || '', source: analytics_js_1.EVENT_SOURCE } }); } catch (e) { console.warn('link analytics error:', e); } refetchLinkedWallets(); } catch (e) { console.log(e); } } setIsSigningLinkMessage(false); setLastConnectedWallet(undefined); onClose(); }; if (connections && connections.length > 1 && waasConnection !== undefined) { tryLinkWallet(); } else { setLastConnectedWallet(undefined); onClose(); } }, [connections, lastConnectedWallet]); const baseWalletConnectors = connectors .filter(c => { return c._wallet && (c._wallet.type === 'wallet' || c._wallet.type === undefined); }) // Remove metamask if metamask is detected .filter(c => { const isMetamaskInjected = window.ethereum?.isMetaMask; if (c._wallet?.id === 'metamask-wallet' && isMetamaskInjected) { return false; } return true; }) // Remove coinbase if coinbase is detected .filter(c => { const isCoinbaseInjected = window.ethereum?.isCoinbaseWallet; if (c._wallet?.id === 'coinbase-wallet' && isCoinbaseInjected) { return false; } return true; }); const mockConnector = baseWalletConnectors.find(connector => { return connector._wallet.id === 'mock'; }); // EIP-6963 connectors will not have the _wallet property const injectedConnectors = connectors .filter(connector => { // Keep the connector when it is an EIP-6963 connector if (connector.type === 'injected') { return true; } // We check if SDK-generated connectors is actually an injected connector const isMetamaskInjected = window.ethereum?.isMetaMask; if (connector._wallet?.id === 'metamask-wallet' && isMetamaskInjected) { return true; } const isCoinbaseInjected = window.ethereum?.isCoinbaseWallet; if (connector._wallet?.id === 'coinbase-wallet' && isCoinbaseInjected) { return true; } return false; }) .map(connector => { if (connector?._wallet) { return connector; } const Logo = (props) => { return (0, jsx_runtime_1.jsx)(design_system_1.Image, { src: connector.icon, alt: connector.name, disableAnimation: true, ...props }); }; return { ...connector, _wallet: { id: connector.id, name: connector.name, logoLight: Logo, logoDark: Logo, type: 'wallet' } }; }); const socialAuthConnectors = connectors .filter(c => c._wallet?.type === 'social') .filter(c => !c._wallet.id.includes('email')); const walletConnectors = [...injectedConnectors, ...baseWalletConnectors].filter(c => hasConnectedSequenceUniversal ? c.name !== exports.SEQUENCE_UNIVERSAL_CONNECTOR_NAME : true); const emailConnector = connectors.find(c => c._wallet?.id.includes('email')); const onChangeEmail = ev => { setEmail(ev.target.value); }; (0, react_1.useEffect)(() => { setIsLoading(status === 'pending' || status === 'success'); }, [status]); const handleConnect = async (connector) => { if (connector._wallet.id === 'guest-waas') { const sequenceWaaS = new waas_1.SequenceWaaS({ projectAccessKey: config.projectAccessKey, waasConfigKey: config.waasConfigKey ?? '' }); await sequenceWaaS.signIn({ guest: true }, 'Guest'); } connect({ connector }, { onSuccess: result => { if (result?.accounts[0]) { config.onConnectSuccess?.(result.accounts[0]); } }, onSettled: result => { setLastConnectedWallet(result?.accounts[0]); } }); }; const onConnect = (connector) => { if (signIn.useMock && mockConnector) { handleConnect(mockConnector); return; } if (connector._wallet.id === 'email') { const email = prompt('Auto-email login, please specify the email address:'); if ('setEmail' in connector) { ; connector.setEmail(email); } } handleConnect(connector); }; const onConnectInlineEmail = async (e) => { e.preventDefault(); if (!(0, helpers_js_1.isEmailValid)(email)) { return; } if (signIn.useMock && mockConnector) { handleConnect(mockConnector); return; } if (emailConnector) { if ('setEmail' in emailConnector) { ; emailConnector.setEmail(email); } if (emailConnector._wallet.id === 'email-waas') { try { await sendEmailCode(); setShowEmailWaasPinInput(true); } catch (e) { console.log(e); } } else { handleConnect(emailConnector); } } }; const { inProgress: emailAuthInProgress, loading: emailAuthLoading, error: emailAuthError, initiateAuth: initiateEmailAuth, sendChallengeAnswer, resetError } = (0, useWaasEmailAuth_js_1.useEmailAuth)({ connector: emailConnector, onSuccess: async (result) => { if ('signInResponse' in result && result.signInResponse?.email) { storage?.setItem(localStorage_js_1.LocalStorageKey.WaasSignInEmail, result.signInResponse.email); } if (emailConnector) { if (result.version === 1) { // Store the version 1 idToken so that it can be used to authenticate during a refresh storage?.setItem(localStorage_js_1.LocalStorageKey.WaasEmailIdToken, result.idToken); } handleConnect(emailConnector); } } }); const sendEmailCode = async () => { await initiateEmailAuth(email); }; // Hide the email input if there is an email conflict (0, react_1.useEffect)(() => { if (emailConflictInfo) { setShowEmailWaasPinInput(false); } }, [emailConflictInfo]); const showSocialConnectorSection = socialAuthConnectors.length > 0; const showEmailInputSection = !!emailConnector; const showMoreSocialOptions = socialAuthConnectors.length > MAX_ITEM_PER_ROW; const showMoreWalletOptions = walletConnectors.length > MAX_ITEM_PER_ROW; const socialConnectorsPerRow = showMoreSocialOptions && !descriptiveSocials ? MAX_ITEM_PER_ROW - 1 : socialAuthConnectors.length; const walletConnectorsPerRow = showMoreWalletOptions ? MAX_ITEM_PER_ROW - 1 : walletConnectors.length; const WalletConnectorsSection = () => { return ((0, jsx_runtime_1.jsxs)("div", { className: (0, clsx_1.clsx)('flex gap-2 flex-row justify-center items-center', hasConnectedSequenceUniversal ? 'mt-4' : 'mt-6'), children: [walletConnectors.slice(0, walletConnectorsPerRow).map(connector => { return (0, jsx_runtime_1.jsx)(index_js_1.ConnectButton, { connector: connector, onConnect: onConnect }, connector.uid); }), showMoreWalletOptions && (0, jsx_runtime_1.jsx)(index_js_1.ShowAllWalletsButton, { onClick: () => setShowExtendedList('wallet') })] })); }; if (showExtendedList) { const SEARCHABLE_TRESHOLD = 8; const connectors = showExtendedList === 'social' ? socialAuthConnectors : walletConnectors; const searchable = connectors.length > SEARCHABLE_TRESHOLD; return ((0, jsx_runtime_1.jsx)(ExtendedWalletList_js_1.ExtendedWalletList, { searchable: searchable, onGoBack: () => setShowExtendedList(null), onConnect: onConnect, connectors: connectors, title: showExtendedList === 'social' ? 'Continue with a social account' : 'Choose a wallet' })); } if (waasStatusData?.errorResponse) { const errorMessage = waasStatusData.errorResponse.status === 451 ? 'Service unavailable due to legal and geographic restrictions' : `Something went wrong. (${waasStatusData.errorResponse.msg})`; return ((0, jsx_runtime_1.jsx)("div", { className: isInline ? 'p-0' : 'p-4', children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col justify-center text-primary items-center font-medium", style: { marginTop: isInline ? '0' : '2px' }, children: [(0, jsx_runtime_1.jsx)(TitleWrapper, { isInline: isInline, children: (0, jsx_runtime_1.jsx)(design_system_1.Text, { color: "secondary", children: isLoading ? `Connecting...` : hasConnectedSocialOrSequenceUniversal ? 'Wallets' : `Connect ${projectName ? `to ${projectName}` : ''}` }) }), (0, jsx_runtime_1.jsx)("div", { className: "relative flex flex-col items-center justify-center p-8", children: (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col items-center gap-4 mt-2 mb-2", children: (0, jsx_runtime_1.jsx)(design_system_1.Text, { color: "secondary", className: "text-center text-lg font-medium text-negative", children: errorMessage }) }) })] }) })); } return ((0, jsx_runtime_1.jsxs)("div", { className: isInline ? 'p-0' : 'p-4', children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col justify-center text-primary items-center font-medium", style: { marginTop: isInline ? '0' : '2px' }, children: [(0, jsx_runtime_1.jsx)(TitleWrapper, { isInline: isInline, children: (0, jsx_runtime_1.jsx)(design_system_1.Text, { color: "secondary", children: isLoading ? `Connecting...` : hasConnectedSocialOrSequenceUniversal ? 'Wallets' : `Connect ${projectName ? `to ${projectName}` : ''}` }) }), isSigningLinkMessage && ((0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (0, jsx_runtime_1.jsx)(design_system_1.Text, { variant: "small", color: "muted", children: "Confirm the signature request to link your account" }) }))] }), isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center items-center pt-4", children: (0, jsx_runtime_1.jsx)(design_system_1.Spinner, {}) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!hideConnectedWallets && wallets.length > 0 && !showEmailWaasPinInput && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ConnectedWallets_js_1.ConnectedWallets, { wallets: wallets, linkedWallets: linkedWallets, disconnectWallet: disconnectWallet, unlinkWallet: handleUnlinkWallet, connectWallet: handleConnect, connectors: walletConnectors, embeddedWalletTitle: config.embeddedWalletTitle }), (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: !hideExternalConnectOptions && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(design_system_1.Divider, { className: "text-background-raised w-full" }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: (0, jsx_runtime_1.jsx)(design_system_1.Text, { variant: "small", color: "muted", children: !hasConnectedSocialOrSequenceUniversal ? 'Connect with a social account' : 'Connect another wallet' }) })] })) })] })), showEmailWaasPinInput ? ((0, jsx_runtime_1.jsx)(EmailWaasVerify_js_1.EmailWaasVerify, { sendEmailCode: sendEmailCode, error: emailAuthError, isLoading: emailAuthLoading, onConfirm: sendChallengeAnswer, resetError: resetError })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!hasConnectedSocialOrSequenceUniversal && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Banner_js_1.Banner, { config: config }), showWalletAuthOptionsFirst && !hideExternalConnectOptions && walletConnectors.length > 0 && ((0, jsx_runtime_1.jsx)(WalletConnectorsSection, {})), (0, jsx_runtime_1.jsx)("div", { className: "flex mt-6 gap-6 flex-col", children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!hideSocialConnectOptions && showSocialConnectorSection && ((0, jsx_runtime_1.jsxs)("div", { className: `flex gap-2 justify-center items-center ${descriptiveSocials ? 'flex-col' : 'flex-row'}`, children: [socialAuthConnectors.slice(0, socialConnectorsPerRow).map(connector => { return ((0, jsx_runtime_1.jsx)("div", { className: "w-full", children: connector._wallet.id === 'guest-waas' ? ((0, jsx_runtime_1.jsx)(ConnectButton_js_1.GuestWaasConnectButton, { isDescriptive: descriptiveSocials, connector: connector, onConnect: onConnect, setIsLoading: setIsLoading })) : connector._wallet.id === 'google-waas' ? ((0, jsx_runtime_1.jsx)(index_js_1.GoogleWaasConnectButton, { isDescriptive: descriptiveSocials, connector: connector, onConnect: onConnect })) : connector._wallet.id === 'apple-waas' ? ((0, jsx_runtime_1.jsx)(index_js_1.AppleWaasConnectButton, { isDescriptive: descriptiveSocials, connector: connector, onConnect: onConnect })) : connector._wallet.id === 'epic-waas' ? ((0, jsx_runtime_1.jsx)(index_js_1.EpicWaasConnectButton, { isDescriptive: descriptiveSocials, connector: connector, onConnect: onConnect })) : connector._wallet.id === 'X-waas' ? ((0, jsx_runtime_1.jsx)(ConnectButton_js_1.XWaasConnectButton, { isDescriptive: descriptiveSocials, connector: connector, onConnect: onConnect })) : ((0, jsx_runtime_1.jsx)(index_js_1.ConnectButton, { disableTooltip: config?.signIn?.disableTooltipForDescriptiveSocials, isDescriptive: descriptiveSocials, connector: connector, onConnect: onConnect })) }, connector.uid)); }), showMoreSocialOptions && ((0, jsx_runtime_1.jsx)("div", { className: "w-full", children: (0, jsx_runtime_1.jsx)(index_js_1.ShowAllWalletsButton, { onClick: () => setShowExtendedList('social') }) }))] })), !hideSocialConnectOptions && showSocialConnectorSection && showEmailInputSection && ((0, jsx_runtime_1.jsxs)("div", { className: "flex gap-4 flex-row justify-center items-center", children: [(0, jsx_runtime_1.jsx)(design_system_1.Divider, { className: "mx-0 my-0 text-background-secondary grow" }), (0, jsx_runtime_1.jsx)(design_system_1.Text, { className: "leading-4 h-4 text-sm", variant: "normal", fontWeight: "medium", color: "muted", children: "or" }), (0, jsx_runtime_1.jsx)(design_system_1.Divider, { className: "mx-0 my-0 text-background-secondary grow" })] })), showEmailInputSection && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("form", { onSubmit: onConnectInlineEmail, children: (0, jsx_runtime_1.jsx)(design_system_1.TextInput, { autoFocus: true, onChange: onChangeEmail, value: email, name: "email", placeholder: "Email address", controls: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: emailAuthInProgress ? ((0, jsx_runtime_1.jsx)(design_system_1.Spinner, {})) : ((0, jsx_runtime_1.jsx)(design_system_1.IconButton, { type: "submit", size: "xs", icon: design_system_1.ArrowRightIcon, disabled: !(0, helpers_js_1.isEmailValid)(email) })) }), "data-1p-ignore": true }) }) }))] }) })] })), !showWalletAuthOptionsFirst && !hideExternalConnectOptions && walletConnectors.length > 0 && ((0, jsx_runtime_1.jsx)(WalletConnectorsSection, {})), (0, jsx_runtime_1.jsx)("div", { className: "mt-6", children: (0, jsx_runtime_1.jsx)(index_js_2.PoweredBySequence, {}) })] }))] }))] })); }; exports.Connect = Connect; const TitleWrapper = ({ children, isInline }) => { if (isInline) { return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children }); } return (0, jsx_runtime_1.jsx)(design_system_1.ModalPrimitive.Title, { asChild: true, children: children }); }; const getUserIdForEvent = (address) => { return (0, tracker_1.genUserId)(address.toLowerCase(), false, { privacy: { userIdHash: true } }).userId; }; //# sourceMappingURL=Connect.js.map