UNPKG

@daimo/pay

Version:

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

92 lines (89 loc) 4.37 kB
import { useContext, useSyncExternalStore, useMemo, useCallback } from 'react'; import { waitForPaymentState } from '../payment/paymentStore.js'; import { PaymentContext } from '../provider/PaymentProvider.js'; /** * React hook for interacting with Daimo Pay orders and payments. Use this hook * to manage the lifecycle of a Daimo Pay payment in your application. * * This hook provides a simple interface to create, hydrate, pay, and reset * Daimo Pay orders. * * @returns {UseDaimoPay} An object with current payment state and methods to * manage Daimo Pay orders and payments. */ function useDaimoPay() { const store = useContext(PaymentContext); if (!store) { throw new Error("useDaimoPay must be used within <PaymentProvider>"); } /* -------------------------------------------------- Order state ---------------------------------------------------*/ // Subscribe to the store and keep an up-to-date copy of the payment. const paymentFsmState = useSyncExternalStore(store.subscribe, store.getState, store.getState); // Wrap `order` in `useMemo` for reference stability. This allows downstream // components to use `order` as a dependency to avoid unnecessary re-renders. const order = useMemo(() => { if (paymentFsmState.type === "idle") return null; return paymentFsmState.order ?? null; }, [paymentFsmState]); const paymentState = paymentFsmState.type; const paymentErrorMessage = paymentFsmState.type === "error" ? paymentFsmState.message : null; /* -------------------------------------------------- Order event dispatch helpers ---------------------------------------------------*/ // Internal helper to dispatch events to the store. const dispatch = useCallback((e) => store.dispatch(e), [store]); const createPreviewOrder = useCallback(async (payParams) => { dispatch({ type: "set_pay_params", payParams }); // Wait for the order to enter the "preview" state, which means it // has been successfully created. const previewOrderState = await waitForPaymentState(store, "preview"); return previewOrderState; }, [dispatch, store]); const setPayId = useCallback(async (payId) => { dispatch({ type: "set_pay_id", payId }); // Wait for the order to be queried from the API. Using payId could // result in the order being in any state. const previewOrderState = await waitForPaymentState(store, "unhydrated", "payment_unpaid", "payment_started", "payment_completed", "payment_bounced"); return previewOrderState; }, [dispatch, store]); const hydrateOrder = useCallback(async (refundAddress) => { dispatch({ type: "hydrate_order", refundAddress }); // Wait for the order to enter the "payment_unpaid" state, which means it // has been successfully hydrated. const hydratedOrderState = await waitForPaymentState(store, "payment_unpaid"); return hydratedOrderState; }, [dispatch, store]); const paySource = useCallback(() => dispatch({ type: "pay_source" }), [dispatch]); const payEthSource = useCallback(async (args) => { dispatch({ type: "pay_ethereum_source", ...args }); // Will throw if the payment is not verified by the server. const paidState = await waitForPaymentState(store, "payment_started", "payment_completed", "payment_bounced"); return paidState; }, [dispatch, store]); const paySolanaSource = useCallback(async (args) => { dispatch({ type: "pay_solana_source", ...args }); // Will throw if the payment is not verified by the server. const paidState = await waitForPaymentState(store, "payment_started", "payment_completed", "payment_bounced"); return paidState; }, [dispatch, store]); const reset = useCallback(() => dispatch({ type: "reset" }), [dispatch]); const setChosenUsd = useCallback((usd) => dispatch({ type: "set_chosen_usd", usd }), [dispatch]); return { order, paymentState, paymentErrorMessage, createPreviewOrder, hydrateOrder, setPayId, paySource, payEthSource, paySolanaSource, reset, setChosenUsd, }; } export { useDaimoPay }; //# sourceMappingURL=useDaimoPay.js.map