@coin-voyage/paykit
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
160 lines (159 loc) • 6.09 kB
JavaScript
import { useAccount } from "@coin-voyage/crypto/hooks";
import { zPayOrder } from "@coin-voyage/shared/common";
import { ChainType, PayOrderMode } from "@coin-voyage/shared/types";
import { useResolveSuiNSName } from "@mysten/dapp-kit";
import { useCallback, useState } from "react";
import { mainnet } from "viem/chains";
import { useEnsName } from "wagmi";
import { useBackendApi } from "../components/contexts/api";
import { ROUTES } from "../types/routes";
import { usePayOrderQuotes } from "./usePayOrderQuotes";
import { usePayToAddress } from "./usePayToAddress";
import { usePayFromWallet } from "./usePayWithToken";
export function usePaymentState({ payOrder, setPayOrder, setRoute, log, }) {
const api = useBackendApi();
const [connectorChainType, setConnectorChainType] = useState();
const [selectedWallet, setSelectedWallet] = useState();
const { account: senderAccount } = useAccount({
selectedWallet,
chainType: connectorChainType,
});
const { data: suiEnsName } = useResolveSuiNSName(senderAccount.address, {
enabled: !!senderAccount.address && senderAccount.chainType === ChainType.SUI && senderAccount.isConnected,
});
const { data: evmEnsName } = useEnsName({
chainId: mainnet.id,
address: senderAccount.address,
query: {
enabled: !!senderAccount.address && senderAccount.chainType === ChainType.EVM && senderAccount.isConnected,
},
});
const payOrderQuotes = usePayOrderQuotes({
payOrder,
address: senderAccount.address,
chainType: connectorChainType,
});
const [selectedCurrencyOption, setSelectedCurrencyOption] = useState();
const [paymentMethod, setPaymentMethod] = useState();
const [payToAddressChainId, setPayToAddressChainId] = useState();
const [payToAddressCurrency, setPayToAddressCurrency] = useState();
const { payFromWallet } = usePayFromWallet({
senderAddr: senderAccount.address,
payOrder,
setPayOrder,
chainType: connectorChainType,
log,
});
const { payToAddress } = usePayToAddress({
payOrder,
setPayOrder,
log,
});
const fetchPayOrder = useCallback(async (id) => {
const { data: order, error } = await api.getPayOrder(id);
if (!order || error) {
log(`[CHECKOUT] No order found for ${id}: ${JSON.stringify(error)}`);
return undefined;
}
return order;
}, [api, log]);
const refreshOrder = useCallback(async () => {
if (!payOrder?.id)
return;
const order = await fetchPayOrder(payOrder.id);
if (order)
setPayOrder(order);
}, [payOrder, fetchPayOrder, setPayOrder]);
const setPayOrderId = useCallback(async (payOrderId) => {
if (!payOrderId || payOrder?.id === payOrderId)
return;
const order = await fetchPayOrder(payOrderId);
if (order)
setPayOrder(order);
}, [payOrder, fetchPayOrder, setPayOrder]);
const copyDepositPayOrder = useCallback(async () => {
if (!payOrder?.id) {
log(`No payOrder to copy`);
return;
}
if (payOrder.mode !== PayOrderMode.DEPOSIT) {
log(`Cannot recreate SALE order`);
return;
}
const asset = payOrder.fulfillment.asset;
const { data, error } = await api.createDepositPayOrder({
intent: {
asset,
amount: {
...(asset ? { token_amount: payOrder.fulfillment.amount.ui_amount } : {}),
...(payOrder.fulfillment.fiat
? {
fiat: {
amount: payOrder.fulfillment.amount.value_usd,
unit: payOrder.fulfillment.fiat,
},
}
: {}),
},
receiving_address: payOrder.fulfillment.receiving_address,
},
metadata: payOrder.metadata,
});
if (!data || error) {
log(`[CHECKOUT] Error creating payOrder: ${JSON.stringify(error)}`);
return;
}
await setPayOrderId(data.id);
}, [api, payOrder, log, setPayOrderId]);
const createDepositPayOrder = useCallback(async (params, onError) => {
try {
const result = zPayOrder.safeParse(params);
if (result.error) {
onError?.(`[CREATE DEPOSIT]: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ")}`);
return;
}
const { data: payOrder, error } = await api.createDepositPayOrder(params);
if (!payOrder || error) {
log(`[CREATE DEPOSIT] Error creating payOrder: ${JSON.stringify(error)}`);
return;
}
setPayOrder(payOrder);
}
catch (e) {
if (e instanceof Error)
onError?.(e.message);
else
onError?.("Unknown error");
}
}, [api, setPayOrder, log]);
const clearUserSelection = useCallback(() => {
setSelectedCurrencyOption(undefined);
setConnectorChainType(undefined);
setSelectedWallet(undefined);
setRoute(ROUTES.SELECT_METHOD);
}, [setRoute]);
return {
setPayId: setPayOrderId,
createDepositPayOrder,
copyDepositPayOrder,
clearUserSelection,
payOrder,
paymentMethod,
setPaymentMethod,
connectorChainType,
setConnectorChainType,
selectedWallet,
setSelectedWallet,
selectedCurrencyOption,
setSelectedCurrencyOption,
payOrderQuotes,
payFromWallet,
payToAddress,
refreshOrder,
senderEnsName: evmEnsName ?? suiEnsName ?? undefined,
payToAddressChainId,
setPayToAddressChainId,
payToAddressCurrency,
setPayToAddressCurrency,
};
}