UNPKG

@daimo/pay

Version:

Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.

149 lines (146 loc) 5.98 kB
import { jsx } from 'react/jsx-runtime'; import { getOrderSourceChainId, DaimoPayEventType, writeDaimoPayOrderID, getDaimoPayOrderView, getOrderDestChainId, assertNotNull } from '@daimo/pay-common'; import { useState, useEffect, useRef, useCallback } from 'react'; import ThemedButton from '../components/Common/ThemedButton/index.js'; import { DaimoPayButtonInner } from '../components/DaimoPayButton/index.js'; import { ROUTES } from '../constants/routes.js'; import { useDaimoPay } from '../hooks/useDaimoPay.js'; import { usePayContext } from '../hooks/usePayContext.js'; import { ResetContainer } from '../styles/index.js'; import { promptWorldcoinPayment } from './promptWorldPayment.js'; import { MiniKit } from '@worldcoin/minikit-js'; import useIsMobile from '../hooks/useIsMobile.js'; import { ThemeContainer } from '../components/Common/ThemedButton/styles.js'; function WorldPayButton(props) { const { theme, mode, customTheme } = props; const context = usePayContext(); return /* @__PURE__ */ jsx(WorldPayButtonCustom, { ...props, children: ({ show, isMiniKitReady }) => /* @__PURE__ */ jsx( ResetContainer, { $useTheme: theme ?? context.theme, $useMode: mode ?? context.mode, $customTheme: customTheme ?? context.customTheme, children: /* @__PURE__ */ jsx( ThemeContainer, { onClick: props.disabled || !isMiniKitReady ? void 0 : show, children: /* @__PURE__ */ jsx(ThemedButton, { children: /* @__PURE__ */ jsx(DaimoPayButtonInner, {}) }) } ) } ) }); } function WorldPayButtonCustom(props) { const pay = useDaimoPay(); const context = usePayContext(); const { paymentState, log } = context; const [isMiniKitReady, setIsMiniKitReady] = useState(false); const { isIOS } = useIsMobile(); const { onPaymentStarted, onPaymentCompleted, onPaymentBounced } = props; useEffect(() => { log("[WORLD] Installing MiniKit"); const result = MiniKit.install(); log("[WORLD] MiniKit install result", result); log("[WORLD] MiniKit is installed", MiniKit.isInstalled()); setIsMiniKitReady(MiniKit.isInstalled()); }, []); useEffect(() => { if ("payId" in props) { log("[WORLD] Using payId from props: ", props.payId); paymentState.setPayId(props.payId); } else { log("[WORLD] Creating preview order"); paymentState.setPayParams(props); } }, [JSON.stringify(props || {})]); useEffect(() => { context.setShowContactSupport(!isIOS); }, [isIOS]); const hasAutoOpened = useRef(false); useEffect(() => { if (!props.defaultOpen || hasAutoOpened.current) return; if (pay.order == null) return; show(); hasAutoOpened.current = true; }, [pay.order, props.defaultOpen, hasAutoOpened.current]); const sentStart = useRef(false); useEffect(() => { if (sentStart.current) return; if (pay.paymentState !== "payment_started") return; const sourceChainId = getOrderSourceChainId(pay.order); if (sourceChainId == null) return; sentStart.current = true; onPaymentStarted?.({ type: DaimoPayEventType.PaymentStarted, paymentId: writeDaimoPayOrderID(pay.order.id), chainId: sourceChainId, txHash: pay.order.sourceInitiateTxHash, payment: getDaimoPayOrderView(pay.order) }); }, [pay.order, pay.paymentState]); const sentComplete = useRef(false); useEffect(() => { if (sentComplete.current) return; if (pay.paymentState !== "payment_completed" && pay.paymentState !== "payment_bounced") return; sentComplete.current = true; const eventType = pay.paymentState === "payment_completed" ? DaimoPayEventType.PaymentCompleted : DaimoPayEventType.PaymentBounced; const event = { type: eventType, paymentId: writeDaimoPayOrderID(pay.order.id), chainId: getOrderDestChainId(pay.order), txHash: assertNotNull( pay.order.destFastFinishTxHash ?? pay.order.destClaimTxHash, `[WORLD PAY BUTTON] dest tx hash null on order ${pay.order.id} when intent status is ${pay.order.intentStatus}` ), payment: getDaimoPayOrderView(pay.order) }; if (pay.paymentState === "payment_completed") { onPaymentCompleted?.(event); } else if (pay.paymentState === "payment_bounced") { onPaymentBounced?.(event); } }, [pay.order, pay.paymentState]); const showSpinner = useCallback(() => { log(`[WORLD] showing spinner ${pay.order?.id}`); const modalOptions = { closeOnSuccess: props.closeOnSuccess, resetOnSuccess: props.resetOnSuccess }; context.showPayment(modalOptions); context.setRoute(ROUTES.CONFIRMATION); }, [context, pay.order?.id, log, props.closeOnSuccess, props.resetOnSuccess]); const show = useCallback(async () => { log(`[WORLD] showing payment ${pay.order?.id}`); if (!isMiniKitReady) { console.error( "[WORLD] MiniKit is not installed. Please install @worldcoin/minikit-js to use this feature." ); return; } if (["payment_started", "payment_completed", "payment_bounced"].includes( pay.paymentState )) { showSpinner(); return; } log(`[WORLD] hydrating order ${pay.order?.id}`); const { order } = await pay.hydrateOrder(); log( `[WORLD] hydrated order ${pay.order?.id}. Prompting payment with MiniKit` ); const payRes = await promptWorldcoinPayment(order, context.trpc); if (payRes == null || payRes.finalPayload.status == "error") { log("[WORLD] Failed to prompt Worldcoin payment: ", payRes); return; } log(`[WORLD] triggering payment search on ${pay.order?.id}`); pay.paySource(); showSpinner(); }, [pay, showSpinner, context.trpc, isMiniKitReady, log]); return props.children({ show, isMiniKitReady }); } WorldPayButtonCustom.displayName = "WorldPayButton.Custom"; WorldPayButton.Custom = WorldPayButtonCustom; export { WorldPayButton }; //# sourceMappingURL=WorldPayButton.js.map