@coin-voyage/paykit
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
138 lines (135 loc) • 5.41 kB
JavaScript
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
import { getChainExplorerTxUrl, PayOrderMode, PayOrderStatus } from "@coin-voyage/shared/common";
import { motion } from "framer-motion";
import { useEffect, useMemo } from "react";
import { ExternalLinkIcon, LoadingCircleIcon, TickIcon } from "../../../assets/icons";
import useLocales from "../../../hooks/useLocales";
import styled from "../../../styles/styled/index";
import usePayContext from "../../contexts/pay/index";
import { ModalContent, ModalH1, PageContent } from "../../ui/Modal/styles";
import PoweredByFooter from "../../ui/PoweredByFooter/index";
const confirmingState = [PayOrderStatus.AWAITING_CONFIRMATION, PayOrderStatus.OPTIMISTIC_CONFIRMED, PayOrderStatus.EXECUTING_ORDER, PayOrderStatus.COMPLETED];
export default function Confirmation() {
const locales = useLocales();
const { paymentState, onSuccess } = usePayContext();
const { payOrder } = paymentState;
const isDeposit = payOrder?.mode === PayOrderMode.DEPOSIT;
const { status, done, txURL } = useMemo(() => {
if (!payOrder || !confirmingState.includes(payOrder.status)) {
return {
status: _jsxs(_Fragment, { children: [locales.confirmationScreen_awaiting, "..."] }),
done: false,
txURL: undefined,
};
}
const payment = payOrder.payment;
let sourceTxUrl = undefined;
if (payment?.src.chain_id) {
const sourceTxHash = payOrder.deposit_tx_hash;
const chainId = payment?.src.chain_id;
sourceTxUrl = sourceTxHash && getChainExplorerTxUrl(chainId, sourceTxHash);
}
if (payOrder.status === PayOrderStatus.AWAITING_CONFIRMATION
|| payOrder.status === PayOrderStatus.OPTIMISTIC_CONFIRMED) {
return {
status: isDeposit ? _jsxs(_Fragment, { children: [locales.awaitingConfirmation, "..."] }) : locales.confirmationScreen_completed,
done: !isDeposit,
txURL: sourceTxUrl,
};
}
if (payOrder.status === PayOrderStatus.EXECUTING_ORDER) {
return {
status: isDeposit ? _jsxs(_Fragment, { children: [locales.confirmationScreen_executing, "..."] }) : locales.confirmationScreen_completed,
done: !isDeposit,
txURL: sourceTxUrl,
};
}
if (payOrder.status === PayOrderStatus.COMPLETED) {
const receivingTxHash = payOrder.receiving_tx_hash;
const destChainId = payment?.dst.chain_id;
const exposedTxURL = isDeposit && destChainId && receivingTxHash ? getChainExplorerTxUrl(destChainId, receivingTxHash) : sourceTxUrl;
return {
status: locales.confirmationScreen_completed,
done: true,
txURL: exposedTxURL
};
}
return {
status: locales.awaitingConfirmation,
done: false,
txURL: sourceTxUrl,
};
}, [payOrder, isDeposit]);
useEffect(() => {
if (done) {
onSuccess();
}
}, [done, onSuccess]);
return (_jsx(PageContent, { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
}, children: _jsxs(ModalContent, { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
paddingBottom: 0,
}, children: [_jsx(AnimationContainer, { children: _jsxs(InsetContainer, { children: [_jsx(Spinner, { "$status": done }), _jsx(SuccessIcon, { "$status": done })] }) }), _jsx(ModalH1, { children: status }), txURL &&
_jsxs(Link, { href: txURL, target: "_blank", rel: "noopener noreferrer", children: [_jsx(ExternalLinkIcon, { width: 14, height: 14, fillOpacity: 0.9 }), " view transaction"] }), _jsx(PoweredByFooter, {})] }) }));
}
const AnimationContainer = styled(motion.div) `
position: relative;
width: 100px;
height: 100px;
transition: transform 0.5s ease-in-out;
margin-bottom: 16px;
`;
const InsetContainer = styled(motion.div) `
position: absolute;
overflow: hidden;
inset: 6px;
border-radius: 50px;
background: var(--ck-body-background);
display: flex;
align-items: center;
justify-content: center;
svg {
position: absolute;
width: 100%;
height: 100%;
}
`;
const Link = styled.a `
display: flex;
gap: 0.5rem;
align-items: center;
color: var(--ck-body-color);
text-decoration: none;
&:hover {
color: var(--ck-body-color-muted);
}
`;
const SuccessIcon = styled(TickIcon) `
color: var(--ck-body-color-valid);
transform: scale(0.5);
transition: all 0.2s ease-in-out;
position: absolute;
opacity: ${(props) => (props.$status ? 1 : 0)};
transform: ${(props) => (props.$status ? "scale(1)" : "scale(0.5)")};
`;
const Spinner = styled(LoadingCircleIcon) `
position: absolute;
transition: all 0.2s ease-in-out;
animation: rotateSpinner 400ms linear infinite;
opacity: ${(props) => (props.$status ? 0 : 1)};
transform: ${(props) => (props.$status ? "scale(0.5)" : "scale(1)")};
@keyframes rotateSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`;
//# sourceMappingURL=index.js.map