UNPKG

@daimo/pay

Version:

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

158 lines (155 loc) 5.91 kB
import { jsx, jsxs } from 'react/jsx-runtime'; import { getChainExplorerTxUrl } from '@daimo/pay-common'; import { useState, useEffect } from 'react'; import { useChainId, useSwitchChain } from 'wagmi'; import { ROUTES } from '../../../constants/routes.js'; import { useDaimoPay } from '../../../hooks/useDaimoPay.js'; import useLocales from '../../../hooks/useLocales.js'; import { usePayContext } from '../../../hooks/usePayContext.js'; import { getSupportUrl } from '../../../utils/supportUrl.js'; import Button from '../../Common/Button/index.js'; import { PageContent, ModalContent, ModalH1, Link } from '../../Common/Modal/styles.js'; import PaymentBreakdown from '../../Common/PaymentBreakdown/index.js'; import TokenLogoSpinner from '../../Spinners/TokenLogoSpinner/index.js'; const PayWithToken = () => { const { triggerResize, paymentState, setRoute, log, trpc } = usePayContext(); const { payWithToken, selectedTokenOption } = paymentState; const { order } = useDaimoPay(); const [payState, setPayStateInner] = useState( "Waiting For Payment" /* RequestingPayment */ ); const setPayState = (state) => { setPayStateInner(state); log(`[PAY TOKEN] payState: ${state}`); trpc.nav.mutate({ action: "pay-with-token-state", data: { state } }); }; const [txURL, setTxURL] = useState(); const locales = useLocales(); const walletChainId = useChainId(); const { switchChainAsync } = useSwitchChain(); const trySwitchingChain = async (option, forceSwitch = false) => { if (walletChainId !== option.required.token.chainId || forceSwitch) { const resultChain = await (async () => { try { return await switchChainAsync({ chainId: option.required.token.chainId }); } catch (e) { console.error("Failed to switch chain", e); return null; } })(); if (resultChain?.id !== option.required.token.chainId) { return false; } } return true; }; const handleTransfer = async (option) => { setPayState("Switching Chain" /* SwitchingChain */); const switchChain = await trySwitchingChain(option); if (!switchChain) { console.error("Switching chain failed"); setPayState("Payment Cancelled" /* RequestCancelled */); return; } setPayState("Waiting For Payment" /* RequestingPayment */); try { const result = await payWithToken(option); if (!result.txHash) { return; } setTxURL( getChainExplorerTxUrl(option.required.token.chainId, result.txHash) ); if (result.success) { setPayState("Payment Successful" /* RequestSuccessful */); setTimeout(() => { setRoute(ROUTES.CONFIRMATION, { event: "wait-pay-with-token" }); }, 200); } else { setPayState("Payment Failed" /* RequestFailed */); } } catch (e) { if (e?.name === "ConnectorChainMismatchError") { log("Chain mismatch detected, attempting to switch and retry"); const switchSuccessful = await trySwitchingChain(option, true); if (switchSuccessful) { setPayState("Waiting For Payment" /* RequestingPayment */); try { const retryResult = await payWithToken(option); if (!retryResult.txHash) { return; } setTxURL( getChainExplorerTxUrl( option.required.token.chainId, retryResult.txHash ) ); if (retryResult.success) { setPayState("Payment Successful" /* RequestSuccessful */); setTimeout(() => { setRoute(ROUTES.CONFIRMATION, { event: "wait-pay-with-token" }); }, 200); } else { setPayState("Payment Failed" /* RequestFailed */); } return; } catch (retryError) { console.error( "Failed to pay with token after switching chain", retryError ); throw retryError; } } } setPayState("Payment Cancelled" /* RequestCancelled */); console.error("Failed to pay with token", e); } }; useEffect(() => { if (!selectedTokenOption) return; const transferTimeout = setTimeout(() => { handleTransfer(selectedTokenOption); }, 100); return () => { clearTimeout(transferTimeout); }; }, [selectedTokenOption]); useEffect(() => { triggerResize(); }, [payState]); if (selectedTokenOption == null) { return /* @__PURE__ */ jsx(PageContent, {}); } return /* @__PURE__ */ jsxs(PageContent, { children: [ /* @__PURE__ */ jsx(TokenLogoSpinner, { token: selectedTokenOption.required.token }), /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 0 }, $preserveDisplay: true, children: [ txURL ? /* @__PURE__ */ jsx(ModalH1, { children: /* @__PURE__ */ jsx(Link, { href: txURL, target: "_blank", rel: "noopener noreferrer", children: payState }) }) : /* @__PURE__ */ jsx(ModalH1, { children: payState }), /* @__PURE__ */ jsx(PaymentBreakdown, { paymentOption: selectedTokenOption }), payState === "Payment Cancelled" /* RequestCancelled */ && /* @__PURE__ */ jsx(Button, { onClick: () => handleTransfer(selectedTokenOption), children: locales.retryPayment }), payState === "Payment Failed" /* RequestFailed */ && /* @__PURE__ */ jsx( Button, { onClick: () => { window.open( getSupportUrl( order?.id?.toString() ?? "", `Pay with token${txURL ? ` ${txURL}` : ""}` ), "_blank" ); }, children: locales.contactSupport } ) ] }) ] }); }; export { PayWithToken as default }; //# sourceMappingURL=index.js.map