UNPKG

@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
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