ghost-dao-interface/src/containers/Bond/components/BondConfirmModal.jsx
Uncle Fatso c38628c107
fix text typos
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2026-05-03 17:48:01 +03:00

177 lines
6.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState, useEffect } from "react";
import { Box, Typography, Checkbox, FormControlLabel } from "@mui/material";
import { CheckBoxOutlineBlank, CheckBoxOutlined } from "@mui/icons-material";
import { styled, useTheme } from "@mui/material/styles";
import SettingsIcon from '@mui/icons-material/Settings';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import toast from "react-hot-toast";
import GhostStyledIcon from "../../../components/Icon/GhostIcon";
import Metric from "../../../components/Metric/Metric";
import Modal from "../../../components/Modal/Modal";
import TokenStack from "../../../components/TokenStack/TokenStack";
import DataRow from "../../../components/DataRow/DataRow";
import { PrimaryButton, SecondaryButton } from "../../../components/Button";
import BondDiscount from "./BondDiscount";
import BondVesting from "./BondVesting";
import BondSlippage from "./BondSlippage";
import { purchaseBond } from "../../../hooks/bonds";
import { useWarmupLength } from "../../../hooks/staking";
const StyledBox = styled(Box, {
shouldForwardProp: prop => prop !== "template",
})(({ theme }) => {
return {
root: {},
};
});
const BondConfirmModal = ({
chainId,
bond,
slippage,
recipientAddress,
spendAmountValue,
spendAmount,
receiveAmount,
sender,
handleSettingsOpen,
isOpen,
isNative,
bondQuoteTokenName,
bondQuoteTokenIcons,
handleConfirmClose
}) => {
const theme = useTheme();
const { warmupLength, warmupExists: needsWarmup } = useWarmupLength(chainId);
const [acknowledgedWarmup, setAcknowledgedWarmup] = useState(false);
const [isPending, setIsPending] = useState(false);
useEffect(() => setAcknowledgedWarmup(acknowledgedWarmup || !needsWarmup), [acknowledgedWarmup, needsWarmup]);
const AcknowledgeWarmupCheckbox = () => {
if (!needsWarmup) return <></>;
return (
<Box sx={{ marginBottom: "1rem" }}>
<FormControlLabel
control={
<Checkbox
data-testid="acknowledge-bond-warm-up"
checked={acknowledgedWarmup}
onChange={event => setAcknowledgedWarmup(event.target.checked)}
icon={<CheckBoxOutlineBlank viewBox="0 0 24 24" />}
checkedIcon={<CheckBoxOutlined viewBox="0 0 24 24" />}
/>
}
label={
<Typography variant="body2">
{`I understand the ${bondQuoteTokenName} Im bonding will only be available to claim ${warmupLength.toString()} epochs after my transaction is confirmed, and the warm-up extends with each bond purchase`}
</Typography>
}
/>
</Box>
);
};
const NeedsWarmupDetails = () => {
if (!needsWarmup) return <></>;
return (
<>
<AcknowledgeWarmupCheckbox />
<SecondaryButton
fullWidth
href="https://ghostchain.io/ghostdao_litepaper"
>
Why is there a warm-up?
</SecondaryButton>
</>
);
};
const handleConfirmCloseMaster = () => {
setAcknowledgedWarmup(false);
handleConfirmClose()
}
const onSubmit = async () => {
setIsPending(true);
const shares = 100000;
const one = BigInt(shares * 100);
const floatSlippage = slippage === "" ? 0 : parseFloat(slippage);
const bigIntSlippage = one + BigInt(Math.round(floatSlippage * shares));
const maxPrice = bond.price.inBaseToken._value * bigIntSlippage / one;
const referral = import.meta.env.VITE_APP_REFERRAL_ADDRESS;
await purchaseBond({
chainId,
bondId: bond.id,
amount: spendAmountValue._value.toBigInt(),
maxPrice,
user: recipientAddress,
sender,
referral,
isNative
});
setIsPending(false);
handleConfirmCloseMaster();
}
return (
<Modal
maxWidth="476px"
minHeight="200px"
open={isOpen}
headerContent={
<Box display="flex" flexDirection="row">
<TokenStack tokens={bondQuoteTokenIcons} sx={{ fontSize: "27px" }} />
<Typography variant="h4" sx={{ marginLeft: "6px" }}>
{bondQuoteTokenName}
</Typography>
</Box>
}
onClose={!isPending && handleConfirmCloseMaster}
topLeft={<GhostStyledIcon viewBox="0 0 23 23" component={SettingsIcon} style={{ cursor: "pointer" }} onClick={handleSettingsOpen} />}
>
<>
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
<Box display="flex" flexDirection="column">
<Metric
label="Assets to Bond"
metric={spendAmount}
/>
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>{bondQuoteTokenName}</Typography>
</Box>
</Box>
<GhostStyledIcon sx={{ transform: "rotate(-90deg)" }} component={ArrowDropDownIcon} />
<Box display="flex" flexDirection="column">
<Metric label="Assets to Receive" metric={receiveAmount} />
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>{bond.baseToken.name}</Typography>
</Box>
</Box>
</Box>
<Box mt="21px" mb="21px" borderTop={`1px solid ${theme.colors.gray[500]}`}></Box>
<DataRow title="ROI" balance={<BondDiscount discount={bond.discount} textOnly />} />
<DataRow title="Bond Slippage" balance={<BondSlippage slippage={slippage} textOnly />} />
<DataRow title="Vesting Term" balance={<BondVesting vesting={bond.vesting} />} />
{!acknowledgedWarmup && <Box>
<Box mt="21px" mb="21px" borderTop={`1px solid ${theme.colors.gray[500]}`}></Box>
<NeedsWarmupDetails />
</Box>}
{acknowledgedWarmup && <PrimaryButton fullWidth onClick={onSubmit} disabled={isPending} loading={isPending}>
{isPending ? "Bonding..." : "Confirm Bond Purchase"}
</PrimaryButton>}
</>
</Modal>
);
};
export default BondConfirmModal;