253 lines
13 KiB
JavaScript
253 lines
13 KiB
JavaScript
import { Box, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material";
|
|
import { useState, useEffect } from "react";
|
|
import toast from "react-hot-toast";
|
|
|
|
import BondVesting from "./BondVesting";
|
|
import BondDuration from "./BondDuration";
|
|
import WarmupConfirmModal from "./WarmupConfirmModal";
|
|
|
|
import Paper from "../../../components/Paper/Paper";
|
|
import TokenStack from "../../../components/TokenStack/TokenStack";
|
|
import { Tab, Tabs } from "../../../components/Tabs/Tabs";
|
|
import { PrimaryButton, TertiaryButton } from "../../../components/Button";
|
|
import { useScreenSize } from "../../../hooks/useScreenSize";
|
|
|
|
import { BOND_DEPOSITORY_ADDRESSES } from "../../../constants/addresses";
|
|
|
|
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
|
import { formatCurrency } from "../../../helpers";
|
|
|
|
import { useCurrentIndex, useEpoch, useWarmupLength, useWarmupInfo } from "../../../hooks/staking";
|
|
import { useNotes, redeem } from "../../../hooks/bonds";
|
|
import { useTokenSymbol } from "../../../hooks/tokens";
|
|
|
|
export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|
const isSmallScreen = useScreenSize("md");
|
|
const [isPending, setIsPending] = useState(false);
|
|
const [isWarmup, setIsWapmup] = useState(false);
|
|
const [isPreClaimConfirmed, setPreClaimConfirmed] = useState(false);
|
|
const [isPayoutGhst, setIsPayoutGhst] = useState(localStorage.getItem("bond-isGhstPayout")
|
|
? localStorage.getItem("bond-isGhstPayout") === "true"
|
|
: true
|
|
);
|
|
|
|
const { epoch } = useEpoch(chainId);
|
|
const { warmupExists } = useWarmupLength(chainId);
|
|
const { warmupInfo } = useWarmupInfo(chainId, BOND_DEPOSITORY_ADDRESSES[chainId]);
|
|
|
|
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
|
|
const { notes, refetch: notesRefetch } = useNotes(chainId, address);
|
|
|
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
|
|
|
if (!notes || notes.length === 0) return null;
|
|
|
|
const totalClaimableBalance = new DecimalBigNumber(
|
|
notes.reduce((res, note) => {
|
|
if (secondsTo < note.matured) return res + 0n;
|
|
return res + note.payout._value
|
|
}, 0n),
|
|
18
|
|
);
|
|
|
|
const setIsPayoutGhstInner = (value) => {
|
|
setIsPayoutGhst(value);
|
|
localStorage.setItem("bond-isGhstPayout", value);
|
|
}
|
|
|
|
const onSubmit = async (indexes) => {
|
|
const isFundsInWarmup = warmupInfo.deposit._value > 0n;
|
|
if (warmupExists && isFundsInWarmup && !isPreClaimConfirmed) {
|
|
setIsWapmup(true);
|
|
} else {
|
|
setIsPending(true);
|
|
await redeem(
|
|
chainId,
|
|
address,
|
|
isPayoutGhst,
|
|
indexes
|
|
);
|
|
await notesRefetch();
|
|
setIsPending(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<WarmupConfirmModal
|
|
isOpen={isWarmup}
|
|
handleConfirmClose={() => setIsWapmup(false)}
|
|
address={address}
|
|
warmupLength={warmupInfo.expiry - epoch.number}
|
|
setPreClaimConfirmed={() => setPreClaimConfirmed(true)}
|
|
/>
|
|
<Paper
|
|
fullWidth
|
|
enableBackground
|
|
headerContent={
|
|
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
<Typography variant="h6">
|
|
Your Bonds
|
|
</Typography>
|
|
</Box>
|
|
}
|
|
>
|
|
<Box display="flex" flexDirection="column" alignItems="center">
|
|
<Typography variant="h4" align="center" color="textSecondary">
|
|
Payout Options
|
|
</Typography>
|
|
<Tabs
|
|
centered
|
|
textColor="primary"
|
|
indicatorColor="primary"
|
|
value={isPayoutGhst ? 1 : 0}
|
|
aria-label="Payout token tabs"
|
|
onChange={(_, view) => setIsPayoutGhstInner(view === 1)}
|
|
TabIndicatorProps={{ style: { display: "none" } }}
|
|
>
|
|
<Tab aria-label="payout-stnk-button" label={stnkSymbol} style={{ fontSize: "1rem" }} />
|
|
<Tab aria-label="payout-ghst-button" label={ghstSymbol} style={{ fontSize: "1rem" }} />
|
|
</Tabs>
|
|
</Box>
|
|
|
|
<Box display="flex" justifyContent="center">
|
|
<Box display="flex" flexDirection="column" alignItems="center" mt="24px" width={isSmallScreen ? "100%" : "50%"}>
|
|
<Typography variant="h5" align="center" color="textSecondary" style={{ fontSize: "1.2rem" }}>
|
|
Claimable Balance
|
|
</Typography>
|
|
|
|
<Box mt="4px" mb="8px">
|
|
<Typography variant="h4" align="center">
|
|
{isPayoutGhst
|
|
? formatCurrency(totalClaimableBalance, 5, ghstSymbol)
|
|
: formatCurrency(currentIndex.mul(totalClaimableBalance), 5, stnkSymbol)
|
|
}
|
|
</Typography>
|
|
</Box>
|
|
|
|
<PrimaryButton
|
|
disabled={isPending || totalClaimableBalance._value === 0n}
|
|
fullWidth
|
|
className=""
|
|
onClick={() => onSubmit(notes.filter((note) => secondsTo > note.matured).map(note => note.id))}
|
|
>
|
|
Claim All
|
|
</PrimaryButton>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box mt="48px">
|
|
{isSmallScreen ? (
|
|
<>
|
|
{notes.map((note, index) => (
|
|
<Box key={index} mt="32px">
|
|
<Box display="flex" alignItems="center">
|
|
<TokenStack tokens={note.quoteToken.icons} />
|
|
<Box ml="8px">
|
|
<Typography>{note.quoteToken.name}</Typography>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box display="flex" justifyContent="space-between" mt="16px">
|
|
<Typography>Duration</Typography>
|
|
<Typography>
|
|
<BondVesting vesting={note.vesting} />
|
|
</Typography>
|
|
</Box>
|
|
|
|
<Box display="flex" justifyContent="space-between" mt="8px">
|
|
<Typography>Remaining</Typography>
|
|
<Typography>
|
|
<BondDuration msg="Matured" secondsTo={secondsTo} duration={note.matured} />
|
|
</Typography>
|
|
</Box>
|
|
|
|
<Box display="flex" justifyContent="space-between" mt="8px">
|
|
<Typography>Payout</Typography>
|
|
<Typography>
|
|
{isPayoutGhst
|
|
? formatCurrency(note.payout, 5, ghstSymbol)
|
|
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
|
}
|
|
</Typography>
|
|
</Box>
|
|
|
|
<Box mt="16px">
|
|
<TertiaryButton
|
|
fullWidth
|
|
disabled={isPending || secondsTo < note.matured}
|
|
onClick={() => onSubmit([note.id])}
|
|
>
|
|
Claim
|
|
</TertiaryButton>
|
|
</Box>
|
|
</Box>
|
|
))}
|
|
</>
|
|
) : (
|
|
<TableContainer>
|
|
<Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell style={{ width: "180px", padding: "8px 0" }}>Bond</TableCell>
|
|
<TableCell style={{ padding: "8px 0" }}>Duration</TableCell>
|
|
<TableCell style={{ padding: "8px 0" }}>Remaining</TableCell>
|
|
<TableCell style={{ padding: "8px 0" }}>Payout</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{notes.map((note, index) => (
|
|
<TableRow key={index}>
|
|
<TableCell style={{ padding: "8px 0" }}>
|
|
<Box display="flex" alignItems="center">
|
|
<TokenStack tokens={note.quoteToken.icons} />
|
|
<Box display="flex" flexDirection="column" ml="16px">
|
|
<Typography>{note.quoteToken.name}</Typography>
|
|
</Box>
|
|
</Box>
|
|
</TableCell>
|
|
|
|
<TableCell style={{ padding: "8px 0" }}>
|
|
<Typography>
|
|
<BondVesting vesting={note.vesting} />
|
|
</Typography>
|
|
</TableCell>
|
|
|
|
<TableCell style={{ padding: "8px 0" }}>
|
|
<Typography>
|
|
<BondDuration msg="Matured" secondsTo={secondsTo} duration={note.matured} />
|
|
</Typography>
|
|
</TableCell>
|
|
|
|
<TableCell style={{ padding: "8px 0" }}>
|
|
<Typography>
|
|
{isPayoutGhst
|
|
? formatCurrency(note.payout, 5, ghstSymbol)
|
|
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
|
}
|
|
</Typography>
|
|
</TableCell>
|
|
|
|
<TableCell style={{ padding: "8px 0" }}>
|
|
<TertiaryButton
|
|
fullWidth
|
|
disabled={isPending || secondsTo < note.matured}
|
|
onClick={() => onSubmit([note.id])}
|
|
>
|
|
Claim
|
|
</TertiaryButton>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
)}
|
|
</Box>
|
|
</Paper>
|
|
</>
|
|
);
|
|
};
|