@0xsequence/connect
Version:
Connect package for Sequence Web SDK
322 lines • 22.3 kB
JavaScript
;
'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 = {}, isPreview = 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 [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 hasInjectedSequenceConnector = connectors.some(c => c.id === 'app.sequence');
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 sequence if wallet extension detected
.filter(c => {
if (c._wallet?.id === 'sequence' && hasInjectedSequenceConnector) {
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(c => c.type === 'injected')
// Remove the injected connectors when another connector is already in the base connectors
.filter(connector => {
if (connector.id === 'com.coinbase.wallet') {
return !connectors.find(connector => connector?._wallet?.id === 'coinbase-wallet');
}
if (connector.id === 'io.metamask') {
return !connectors.find(connector => connector?._wallet?.id === 'metamask-wallet');
}
return true;
})
.map(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 = [...baseWalletConnectors, ...injectedConnectors].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 }, {
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;
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: "p-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col justify-center text-primary items-center font-medium", style: {
marginTop: '2px'
}, children: [(0, jsx_runtime_1.jsx)(TitleWrapper, { isPreview: isPreview, 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: "p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col justify-center text-primary items-center font-medium", style: {
marginTop: '2px'
}, children: [(0, jsx_runtime_1.jsx)(TitleWrapper, { isPreview: isPreview, 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 }), (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 }), (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 }) }) }))] }) })] })), !hideExternalConnectOptions && walletConnectors.length > 0 && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (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') })] }) })), (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, isPreview }) => {
if (isPreview) {
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