@daimo/pay
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
198 lines (195 loc) • 6.88 kB
JavaScript
import { jsx } from 'react/jsx-runtime';
import { useEffect, useCallback, useRef } from 'react';
import { usePayContext } from '../../hooks/usePayContext.js';
import { TextContainer } from './styles.js';
import { getOrderSourceChainId, DaimoPayEventType, writeDaimoPayOrderID, getDaimoPayOrderView, getOrderDestChainId, assertNotNull } from '@daimo/pay-common';
import { AnimatePresence } from 'framer-motion';
import { useDaimoPay } from '../../hooks/useDaimoPay.js';
import useLocales from '../../hooks/useLocales.js';
import { ResetContainer } from '../../styles/index.js';
import ThemedButton from '../Common/ThemedButton/index.js';
import { ThemeContainer } from '../Common/ThemedButton/styles.js';
function DaimoPayButton(props) {
const { theme, mode, customTheme } = props;
const context = usePayContext();
return /* @__PURE__ */ jsx(DaimoPayButtonCustom, { ...props, children: ({ show }) => /* @__PURE__ */ jsx(
ResetContainer,
{
$useTheme: theme ?? context.theme,
$useMode: mode ?? context.mode,
$customTheme: customTheme ?? context.customTheme,
children: /* @__PURE__ */ jsx(ThemeContainer, { onClick: props.disabled ? void 0 : show, children: /* @__PURE__ */ jsx(
ThemedButton,
{
theme: theme ?? context.theme,
mode: mode ?? context.mode,
customTheme: customTheme ?? context.customTheme,
children: /* @__PURE__ */ jsx(DaimoPayButtonInner, {})
}
) })
}
) });
}
function DaimoPayButtonCustom(props) {
const context = usePayContext();
let payParams = "appId" in props ? {
appId: props.appId,
toChain: props.toChain,
toAddress: props.toAddress,
toToken: props.toToken,
toUnits: props.toUnits,
toCallData: props.toCallData,
intent: props.intent,
paymentOptions: props.paymentOptions,
preferredChains: props.preferredChains,
preferredTokens: props.preferredTokens,
evmChains: props.evmChains,
externalId: props.externalId,
metadata: props.metadata,
refundAddress: props.refundAddress,
passthroughTokens: props.passthroughTokens,
uniquePaymentOption: props.uniquePaymentOption
} : null;
let payId = "payId" in props ? props.payId : null;
const { paymentState } = context;
const { order, paymentState: payState } = useDaimoPay();
useEffect(() => {
if (payId != null) {
paymentState.setPayId(payId);
} else if (payParams != null) {
paymentState.setPayParams(payParams);
}
paymentState.setButtonProps(props);
}, [payId, JSON.stringify(payParams || {})]);
const { setConfirmationMessage } = context;
useEffect(() => {
if (props.confirmationMessage) {
setConfirmationMessage(props.confirmationMessage);
}
}, [props.confirmationMessage, setConfirmationMessage]);
const { setRedirectReturnUrl } = context;
useEffect(() => {
if (props.redirectReturnUrl) {
setRedirectReturnUrl(props.redirectReturnUrl);
}
}, [props.redirectReturnUrl, setRedirectReturnUrl]);
const { setOnOpen, setOnClose } = context;
useEffect(() => {
setOnOpen(props.onOpen);
return () => setOnOpen(void 0);
}, [props.onOpen, setOnOpen]);
useEffect(() => {
setOnClose(props.onClose);
return () => setOnClose(void 0);
}, [props.onClose, setOnClose]);
const { onPaymentStarted, onPaymentCompleted, onPaymentBounced } = props;
const { children, closeOnSuccess, resetOnSuccess, connectedWalletOnly } = props;
const show = useCallback(() => {
const modalOptions = {
closeOnSuccess,
resetOnSuccess,
connectedWalletOnly
};
context.showPayment(modalOptions);
}, [connectedWalletOnly, closeOnSuccess, resetOnSuccess, context]);
const hide = useCallback(() => context.setOpen(false), [context]);
const sentStart = useRef(false);
useEffect(() => {
if (sentStart.current) return;
if (payState !== "payment_started") return;
const sourceChainId = getOrderSourceChainId(order);
if (sourceChainId == null) return;
sentStart.current = true;
onPaymentStarted?.({
type: DaimoPayEventType.PaymentStarted,
paymentId: writeDaimoPayOrderID(order.id),
chainId: sourceChainId,
txHash: order.sourceInitiateTxHash,
payment: getDaimoPayOrderView(order)
});
}, [order, payState]);
const sentComplete = useRef(false);
useEffect(() => {
if (sentComplete.current) return;
if (payState !== "payment_completed" && payState !== "payment_bounced")
return;
sentComplete.current = true;
const eventType = payState === "payment_completed" ? DaimoPayEventType.PaymentCompleted : DaimoPayEventType.PaymentBounced;
const passthroughTxHash = order.passedToAddress == null ? void 0 : order.sourceInitiateTxHash;
const event = {
type: eventType,
paymentId: writeDaimoPayOrderID(order.id),
chainId: getOrderDestChainId(order),
txHash: assertNotNull(
order.destFastFinishTxHash ?? order.destClaimTxHash ?? passthroughTxHash,
`[PAY BUTTON] dest tx hash null on order ${order.id} when intent status is ${order.intentStatus}`
),
payment: getDaimoPayOrderView(order)
};
if (payState === "payment_completed") {
onPaymentCompleted?.(event);
} else if (payState === "payment_bounced") {
onPaymentBounced?.(event);
}
}, [order, payState]);
const hasAutoOpened = useRef(false);
useEffect(() => {
if (!props.defaultOpen || hasAutoOpened.current) return;
if (order == null) return;
show();
hasAutoOpened.current = true;
}, [order, props.defaultOpen, hasAutoOpened.current]);
if (payId == null == (payParams == null)) {
throw new Error("Must specify either payId or appId, not both");
}
return children({ show, hide });
}
DaimoPayButtonCustom.displayName = "DaimoPayButton.Custom";
DaimoPayButton.Custom = DaimoPayButtonCustom;
const contentVariants = {
initial: {
zIndex: 2,
opacity: 0,
x: "-100%"
},
animate: {
opacity: 1,
x: 0.1,
transition: {
duration: 0.4,
ease: [0.25, 1, 0.5, 1]
}
},
exit: {
zIndex: 1,
opacity: 0,
x: "-100%",
pointerEvents: "none",
position: "absolute",
transition: {
duration: 0.4,
ease: [0.25, 1, 0.5, 1]
}
}
};
function DaimoPayButtonInner() {
const { order } = useDaimoPay();
const locales = useLocales();
const defaultLabel = locales.payButton_defaultLabel;
const label = order?.metadata?.intent ?? defaultLabel;
return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
TextContainer,
{
initial: "initial",
animate: "animate",
exit: "exit",
variants: contentVariants,
style: {
height: 40
},
children: label
}
) });
}
export { DaimoPayButton, DaimoPayButtonInner };
//# sourceMappingURL=index.js.map