UNPKG

@coin-voyage/paykit

Version:

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

102 lines (101 loc) 4.29 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { PaymentMethod, PayOrderMode } from "@coin-voyage/shared/types"; import { useQuery } from "@tanstack/react-query"; import { useMemo } from "react"; import { CreditCardIcon } from "../assets/icons"; import Logos from "../assets/logos"; import { useBackendApi } from "../components/contexts/api"; import usePayContext from "../components/contexts/pay"; import { ROUTE } from "../types/routes"; import { Ethereum, Solana, Sui } from "@coin-voyage/shared/chain"; function getTitle(subject, isDeposit) { return `${isDeposit ? "Deposit" : "Pay"} ${subject}`; } export function useMethodOptions({ mode, onClick }) { const api = useBackendApi(); const { setRoute, paymentState, options: contextOptions } = usePayContext(); const { payOrder, setPaymentMethod } = paymentState; const isDeposit = mode === PayOrderMode.DEPOSIT; const mayUseCardPayments = payOrder?.settings?.card_payments === true; const wantsToUseCardPayments = contextOptions?.experimentalFeatures?.cardPayments === true; const shouldCheckCardAvailability = wantsToUseCardPayments && mayUseCardPayments; const { data: paymentMethods, isLoading } = useQuery({ queryKey: ["payment-methods", payOrder?.id], enabled: shouldCheckCardAvailability && Boolean(payOrder?.id), retry: false, refetchOnWindowFocus: false, queryFn: async () => { if (!payOrder?.id) { throw new Error("Missing pay order"); } const response = await api.getPayOrderPaymentMethods(payOrder.id); if (response.error || !response.data) { throw new Error(response.error?.message ?? "Unable to load payment methods"); } return response.data; }, }); const options = useMemo(() => { const nextOptions = [ { id: PaymentMethod.WALLET, title: getTitle("with Wallet", isDeposit), iconShape: "squircle", icons: [ _jsx(Logos.MetaMask, {}, "metamask"), _jsx(Logos.Phantom, {}, "phantom"), _jsx(Logos.Slush, { style: { backgroundColor: "#000" } }, "slush"), ], onClick: () => { setPaymentMethod(PaymentMethod.WALLET); setRoute(ROUTE.WALLET_CHAIN_SELECT); onClick(); }, }, { id: PaymentMethod.DEPOSIT_ADDRESS, title: getTitle("to Address", isDeposit), iconShape: "circle", icons: [_jsx(Ethereum, {}, "ethereum"), _jsx(Solana, {}, "solana"), _jsx(Sui, {}, "sui")], onClick: () => { setPaymentMethod(PaymentMethod.DEPOSIT_ADDRESS); setRoute(ROUTE.ADDRESS_CHAIN_SELECT); onClick(); }, }, ]; if (!shouldCheckCardAvailability) { return nextOptions; } const cardMethod = paymentMethods?.methods.find((m) => m.method === PaymentMethod.CARD); if (!cardMethod) { return nextOptions; } nextOptions.push({ id: PaymentMethod.CARD, title: getTitle("with Card", isDeposit), subtitle: !cardMethod.available ? (cardMethod.reason ?? formatMinimumAmount(cardMethod.minimum_amount)) : undefined, disabled: !cardMethod.available, iconShape: "squircle", icons: [_jsx(CreditCardIcon, {}, "stripe")], onClick: () => { if (!cardMethod.available) { return; } setPaymentMethod(PaymentMethod.CARD); setRoute(ROUTE.CARD_PAYMENT); onClick(); }, }); return nextOptions; }, [isDeposit, onClick, paymentMethods?.methods, setPaymentMethod, setRoute, shouldCheckCardAvailability]); return { options, isLoading }; } function formatMinimumAmount(minimumAmount) { if (!minimumAmount) { return undefined; } return `Minimum ${minimumAmount.amount} ${minimumAmount.unit}`; }