@coin-voyage/paykit
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
73 lines (72 loc) • 2.91 kB
JavaScript
import { PayOrderMode, PayOrderStatus, } from "@coin-voyage/shared/types";
import { useEffect, useMemo, useRef } from "react";
/**
* Handles payment lifecycle events of an order, such as started, completed, and bounced.
* @param {PayOrder | undefined} order The pay order to monitor.
* @param {PaymentLifecycleHandlers} handlers Handlers for payment lifecycle events.
* @returns
*/
export function usePaymentLifecycle(order, handlers) {
const sentStart = useRef(false);
const sentComplete = useRef(false);
const { onPaymentStarted, onPaymentCompleted, onPaymentBounced } = handlers;
const orderStatus = order?.status;
const isSale = order?.mode === PayOrderMode.SALE;
const completedStates = useMemo(() => [PayOrderStatus.COMPLETED, PayOrderStatus.REFUNDED], []);
const isStarted = useMemo(() => {
if (!orderStatus)
return false;
const startedStatus = [
...completedStates,
PayOrderStatus.AWAITING_CONFIRMATION,
PayOrderStatus.OPTIMISTIC_CONFIRMED,
PayOrderStatus.EXECUTING_ORDER,
];
return startedStatus.includes(orderStatus);
}, [orderStatus, completedStates]);
const isFinalized = useMemo(() => {
if (!orderStatus)
return false;
const finalizedStatus = [...completedStates];
if (isSale) {
finalizedStatus.push(PayOrderStatus.OPTIMISTIC_CONFIRMED, PayOrderStatus.EXECUTING_ORDER);
}
return finalizedStatus.includes(orderStatus);
}, [orderStatus, isSale, completedStates]);
useEffect(() => {
if (sentStart.current || !order?.payment || !isStarted)
return;
sentStart.current = true;
onPaymentStarted?.({
type: "payorder_confirming",
payorder_id: order.id,
status: order.status,
metadata: order.metadata,
payment_data: order.payment,
});
}, [order, isStarted, onPaymentStarted]);
useEffect(() => {
if (sentComplete.current || !order?.payment || !isFinalized)
return;
sentComplete.current = true;
if (order.status === PayOrderStatus.REFUNDED) {
onPaymentBounced?.({
type: "payorder_refunded",
payorder_id: order.id,
status: order.status,
metadata: order.metadata,
refund_address: order.payment.refund_address,
refund_tx_hash: order.refund_tx_hash ?? "",
});
return;
}
onPaymentCompleted?.({
type: "payorder_completed",
payorder_id: order.id,
status: order.status,
metadata: order.metadata,
payment_data: order.payment,
});
}, [order, isFinalized, onPaymentCompleted, onPaymentBounced]);
return { isStarted, isFinalized, order };
}