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