@daimo/pay
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
336 lines (333 loc) • 12.9 kB
JavaScript
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { AnimatePresence } from 'framer-motion';
import { useState, useEffect } from 'react';
import { Container, ConnectingContainer, ConnectingAnimation, RetryButton, RetryIconContainer, Content } from './styles.js';
import Alert from '../../Common/Alert/index.js';
import Button from '../../Common/Button/index.js';
import { PageContent, ModalHeading, ModalContent, ModalContentContainer, ModalH1, ModalBody } from '../../Common/Modal/styles.js';
import Tooltip from '../../Common/Tooltip/index.js';
import SquircleSpinner from '../../Spinners/SquircleSpinner/index.js';
import { RetryIconCircle, AlertIcon, ExternalLinkIcon, TickIcon } from '../../../assets/icons.js';
import { useConnect } from '../../../hooks/useConnect.js';
import useLocales from '../../../hooks/useLocales.js';
import { usePayContext } from '../../../hooks/usePayContext.js';
import { detectBrowser } from '../../../utils/index.js';
import { useWallet } from '../../../wallets/useWallets.js';
import BrowserIcon from '../../Common/BrowserIcon/index.js';
import CircleSpinner from '../../Spinners/CircleSpinner/index.js';
const states = {
CONNECTED: "connected",
CONNECTING: "connecting",
EXPIRING: "expiring",
FAILED: "failed",
REJECTED: "rejected",
NOTCONNECTED: "notconnected",
UNAVAILABLE: "unavailable"
};
const contentVariants = {
initial: {
willChange: "transform,opacity",
position: "relative",
opacity: 0,
scale: 0.95
},
animate: {
position: "relative",
opacity: 1,
scale: 1,
transition: {
ease: [0.16, 1, 0.3, 1],
duration: 0.4,
delay: 0.05,
position: { delay: 0 }
}
},
exit: {
position: "absolute",
opacity: 0,
scale: 0.95,
transition: {
ease: [0.16, 1, 0.3, 1],
duration: 0.3
}
}
};
const ConnectWithInjector = ({ switchConnectMethod, forceState }) => {
const { connect } = useConnect({
mutation: {
onMutate: (connector) => {
if (connector.connector) {
setStatus(states.CONNECTING);
} else {
setStatus(states.UNAVAILABLE);
}
},
onError(err) {
console.error(err);
},
onSettled(data, error) {
if (error) {
setShowTryAgainTooltip(true);
setTimeout(() => setShowTryAgainTooltip(false), 3500);
if (error.code) {
switch (error.code) {
case -32002:
setStatus(states.NOTCONNECTED);
break;
case 4001:
setStatus(states.REJECTED);
break;
default:
setStatus(states.FAILED);
break;
}
} else {
if (error.message) {
switch (error.message) {
case "User rejected request":
setStatus(states.REJECTED);
break;
default:
setStatus(states.FAILED);
break;
}
}
}
}
setTimeout(triggerResize, 100);
}
}
});
const { triggerResize } = usePayContext();
const { pendingConnectorId } = usePayContext();
const wallet = useWallet(pendingConnectorId ?? "");
const walletInfo = {
name: wallet?.name,
shortName: wallet?.shortName ?? wallet?.name,
icon: wallet?.iconConnector ?? wallet?.icon,
iconShape: wallet?.iconShape ?? "circle",
iconShouldShrink: wallet?.iconShouldShrink
};
const [showTryAgainTooltip, setShowTryAgainTooltip] = useState(false);
const browser = detectBrowser();
const extensionUrl = wallet?.downloadUrls?.[browser];
const suggestedExtension = wallet?.downloadUrls ? {
name: Object.keys(wallet?.downloadUrls)[0],
label: Object.keys(wallet?.downloadUrls)[0]?.charAt(0).toUpperCase() + Object.keys(wallet?.downloadUrls)[0]?.slice(1),
// Capitalise first letter, but this might be better suited as a lookup table
url: wallet?.downloadUrls[Object.keys(wallet?.downloadUrls)[0]]
} : void 0;
const [status, setStatus] = useState(
forceState ? forceState : !wallet?.isInstalled ? states.UNAVAILABLE : states.CONNECTING
);
const locales = useLocales({
CONNECTORNAME: walletInfo.name,
CONNECTORSHORTNAME: walletInfo.shortName ?? walletInfo.name,
SUGGESTEDEXTENSIONBROWSER: suggestedExtension?.label ?? "your browser"
});
const runConnect = async () => {
if (wallet?.isInstalled && wallet?.connector) {
connect({ connector: wallet?.connector });
} else {
setStatus(states.UNAVAILABLE);
}
};
useEffect(() => {
if (status === states.UNAVAILABLE) return;
const connectTimeout = setTimeout(runConnect, 600);
return () => {
clearTimeout(connectTimeout);
};
}, []);
if (!wallet) {
return /* @__PURE__ */ jsx(PageContent, { children: /* @__PURE__ */ jsxs(Container, { children: [
/* @__PURE__ */ jsx(ModalHeading, { children: locales.invalidState_heading }),
/* @__PURE__ */ jsx(ModalContent, { children: /* @__PURE__ */ jsx(Alert, { children: locales.invalidState_description }) })
] }) });
}
return /* @__PURE__ */ jsx(PageContent, { children: /* @__PURE__ */ jsxs(Container, { children: [
/* @__PURE__ */ jsx(ConnectingContainer, { children: /* @__PURE__ */ jsxs(
ConnectingAnimation,
{
$shake: status === states.FAILED || status === states.REJECTED,
$circle: walletInfo.iconShape === "circle",
children: [
/* @__PURE__ */ jsx(AnimatePresence, { children: (status === states.FAILED || status === states.REJECTED) && /* @__PURE__ */ jsx(
RetryButton,
{
"aria-label": locales.retry,
initial: { opacity: 0, scale: 0.8 },
animate: { opacity: 1, scale: 1 },
exit: { opacity: 0, scale: 0.8 },
whileTap: { scale: 0.9 },
transition: { duration: 0.1 },
onClick: runConnect,
children: /* @__PURE__ */ jsx(RetryIconContainer, { children: /* @__PURE__ */ jsx(
Tooltip,
{
open: showTryAgainTooltip && (status === states.FAILED || status === states.REJECTED),
message: locales.tryAgainQuestion,
xOffset: -6,
children: /* @__PURE__ */ jsx(RetryIconCircle, {})
}
) })
}
) }),
walletInfo.iconShape === "circle" ? /* @__PURE__ */ jsx(
CircleSpinner,
{
logo: status === states.UNAVAILABLE ? /* @__PURE__ */ jsx(
"div",
{
style: {
transform: "scale(1.14)",
position: "relative",
width: "100%"
},
children: walletInfo.icon
}
) : /* @__PURE__ */ jsx(Fragment, { children: walletInfo.icon }),
smallLogo: walletInfo.iconShouldShrink,
loading: status === states.CONNECTING,
unavailable: status === states.UNAVAILABLE
}
) : /* @__PURE__ */ jsx(
SquircleSpinner,
{
logo: status === states.UNAVAILABLE ? /* @__PURE__ */ jsx(
"div",
{
style: {
transform: "scale(1.14)",
position: "relative",
width: "100%"
},
children: walletInfo.icon
}
) : /* @__PURE__ */ jsx(Fragment, { children: walletInfo.icon }),
loading: status === states.CONNECTING
}
)
]
}
) }),
/* @__PURE__ */ jsx(ModalContentContainer, { children: /* @__PURE__ */ jsxs(AnimatePresence, { initial: false, children: [
status === states.FAILED && /* @__PURE__ */ jsx(
Content,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
children: /* @__PURE__ */ jsxs(ModalContent, { children: [
/* @__PURE__ */ jsxs(ModalH1, { $error: true, children: [
/* @__PURE__ */ jsx(AlertIcon, {}),
locales.injectionScreen_failed_h1
] }),
/* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_failed_p })
] })
},
states.FAILED
),
status === states.REJECTED && /* @__PURE__ */ jsx(
Content,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
children: /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [
/* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_rejected_h1 }),
/* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_rejected_p })
] })
},
states.REJECTED
),
(status === states.CONNECTING || status === states.EXPIRING) && /* @__PURE__ */ jsx(
Content,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
children: /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [
/* @__PURE__ */ jsx(ModalH1, { children: wallet.connector?.id === "injected" ? locales.injectionScreen_connecting_injected_h1 : locales.injectionScreen_connecting_h1 }),
/* @__PURE__ */ jsx(ModalBody, { children: wallet.connector?.id === "injected" ? locales.injectionScreen_connecting_injected_p : locales.injectionScreen_connecting_p }),
/* @__PURE__ */ jsxs(Button, { icon: /* @__PURE__ */ jsx(ExternalLinkIcon, {}), onClick: runConnect, children: [
"Connect ",
walletInfo.name
] })
] })
},
states.CONNECTING
),
status === states.CONNECTED && /* @__PURE__ */ jsx(
Content,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
children: /* @__PURE__ */ jsxs(ModalContent, { children: [
/* @__PURE__ */ jsxs(ModalH1, { $valid: true, children: [
/* @__PURE__ */ jsx(TickIcon, {}),
" ",
locales.injectionScreen_connected_h1
] }),
/* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_connected_p })
] })
},
states.CONNECTED
),
status === states.NOTCONNECTED && /* @__PURE__ */ jsx(
Content,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
children: /* @__PURE__ */ jsxs(ModalContent, { children: [
/* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_notconnected_h1 }),
/* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_notconnected_p })
] })
},
states.NOTCONNECTED
),
status === states.UNAVAILABLE && /* @__PURE__ */ jsx(
Content,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
children: !extensionUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 12 }, children: [
/* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_unavailable_h1 }),
/* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_unavailable_p })
] }),
!wallet.isInstalled && suggestedExtension && /* @__PURE__ */ jsxs(
Button,
{
href: suggestedExtension?.url,
icon: /* @__PURE__ */ jsx(BrowserIcon, { browser: suggestedExtension?.name }),
children: [
"Install on ",
suggestedExtension?.label
]
}
)
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 18 }, children: [
/* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_install_h1 }),
/* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_install_p })
] }),
!wallet.isInstalled && extensionUrl && /* @__PURE__ */ jsx(Button, { href: extensionUrl, icon: /* @__PURE__ */ jsx(BrowserIcon, {}), children: locales.installTheExtension })
] })
},
states.UNAVAILABLE
)
] }) })
] }) });
};
export { ConnectWithInjector as default, states };
//# sourceMappingURL=index.js.map