150 lines
6.8 KiB
JavaScript
150 lines
6.8 KiB
JavaScript
import { useMemo } from "react";
|
|
import { Grid, Box, Typography } from "@mui/material";
|
|
import { useConfig } from "wagmi";
|
|
import { useNavigate, createSearchParams } from "react-router-dom";
|
|
|
|
import { formatNumber } from "../../../helpers";
|
|
import { useLiveBonds } from "../../../hooks/bonds/index";
|
|
import { useEpoch, useGatekeeperApy } from "../../../hooks/staking";
|
|
import { useTokenSymbol, useBalance, useCirculatingSupply } from "../../../hooks/tokens";
|
|
import { SecondaryButton } from "../../../components/Button";
|
|
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
|
|
|
import { GATEKEEPER_ADDRESSES, EMPTY_ADDRESS } from "../../../constants/addresses";
|
|
|
|
const ProtocolDetail = ({ isMobileScreen, theme, name, sideName, url, urlParams, description }) => {
|
|
const navigate = useNavigate();
|
|
return (
|
|
<Box position="relative" width={`${isMobileScreen ? "100%" : "48%"}`}>
|
|
<Box
|
|
borderRadius="9px"
|
|
padding="12px"
|
|
sx={{ backgroundColor: theme.colors.paper.card }}
|
|
display="flex"
|
|
flexDirection="column"
|
|
justifyContent="space-between"
|
|
>
|
|
<Box display="flex" gap={"3px"} alignItems="center" justifyContent="space-between">
|
|
<Typography fontSize="20px" fontWeight="bold" lineHeight="33px">
|
|
{name}
|
|
</Typography>
|
|
<Typography color={theme.colors.primary[300]} fontSize="20px" fontWeight="bold" lineHeight="33px">
|
|
{sideName}
|
|
</Typography>
|
|
</Box>
|
|
<>
|
|
<Box my="18px">
|
|
<Typography color={theme.colors.gray[40]} mt="9px">
|
|
{description}
|
|
</Typography>
|
|
</Box>
|
|
|
|
<Box display="flex" justifyContent="center" width="100%">
|
|
<SecondaryButton
|
|
onClick={() => urlParams
|
|
? navigate({
|
|
pathname: url,
|
|
search: urlParams.toString()
|
|
})
|
|
: navigate(url, { replace: true })
|
|
}
|
|
fullWidth
|
|
>
|
|
{name}
|
|
</SecondaryButton>
|
|
</Box>
|
|
</>
|
|
</Box>
|
|
</Box>
|
|
)
|
|
}
|
|
|
|
const ProtocolDetails = ({ chainId, isMobileScreen, theme, }) => {
|
|
const config = useConfig();
|
|
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
|
|
const networkName = config?.getClient()?.chain?.name;
|
|
|
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
|
const { symbol: csprSymbol } = useTokenSymbol(chainId, "CSPR");
|
|
const { contractAddress: ftsoAddress } = useBalance(chainId, "FTSO", EMPTY_ADDRESS);
|
|
const { liveBonds } = useLiveBonds(chainId);
|
|
|
|
const circulatingSupply = useCirculatingSupply(chainId, "STNK");
|
|
const gatekeepedApy = useGatekeeperApy(chainId);
|
|
const { epoch } = useEpoch(chainId);
|
|
|
|
const maxBondDiscountTest = useMemo(() => {
|
|
const sortedGhostBonds = liveBonds.filter((bond) => !bond.isSoldOut)
|
|
if (sortedGhostBonds?.length === 0) return "Coming Up";
|
|
const maxDiscountBond = sortedGhostBonds.reduce((prev, current) =>
|
|
(prev.discount > current.discount) ? prev : current
|
|
);
|
|
const maxDiscount = maxDiscountBond.discount.mul(new DecimalBigNumber(100, 0));
|
|
return `Up to ${formatNumber(maxDiscount, 0)}% Discount`;
|
|
}, [liveBonds]);
|
|
|
|
const apyInner = useMemo(() => {
|
|
let apy = Infinity;
|
|
if (circulatingSupply._value > 0n) {
|
|
const value = epoch.distribute.div(circulatingSupply);
|
|
apy = 100 * (Math.pow(1 + parseFloat(value.toString()), 1095) - 1);
|
|
if (apy === 0) apy = Infinity;
|
|
}
|
|
return apy;
|
|
}, [circulatingSupply, epoch]);
|
|
|
|
const bridgeNumbers = useMemo(() => {
|
|
const connectedNetworks = Object.keys(GATEKEEPER_ADDRESSES).length;
|
|
const number = 1 + connectedNetworks * 3;
|
|
return `(${number}, ${number})`;
|
|
}, [chainId]);
|
|
|
|
return (
|
|
<Grid container spacing={0} justifyContent={"center"}>
|
|
<Box display="flex" flexWrap="wrap" justifyContent="space-between" mt="10px" gap="25px">
|
|
<ProtocolDetail
|
|
isMobileScreen={isMobileScreen}
|
|
theme={theme}
|
|
url={`/${networkName.toLowerCase()}/dex/uniswap`}
|
|
urlParams={createSearchParams({
|
|
from: EMPTY_ADDRESS,
|
|
to: `${ftsoAddress}`,
|
|
})}
|
|
name="(3, 3) Swap"
|
|
sideName="Unlock Magic"
|
|
description={`Buying strategy expands bond capacity triggering a positive loop to strengthen the Treasury and attract more stakers. Swap ${nativeSymbol} for ${ftsoSymbol} to unlock (3, 3) Stake.`}
|
|
/>
|
|
|
|
<ProtocolDetail
|
|
isMobileScreen={isMobileScreen}
|
|
theme={theme}
|
|
url={`/${networkName.toLowerCase()}/bonds`}
|
|
name="(1, 1) Bond"
|
|
sideName={maxBondDiscountTest}
|
|
description={`Bonding strategy grows Treasury and builds Protocol Owned Liquidity (POL) by allowing users to acquire ${csprSymbol} at a discount. Take advantage of the next available bond.`}
|
|
/>
|
|
|
|
<ProtocolDetail
|
|
isMobileScreen={isMobileScreen}
|
|
theme={theme}
|
|
url={`/${networkName.toLowerCase()}/stake`}
|
|
name="(3, 3) Stake"
|
|
sideName={`${formatNumber(apyInner, 0)}% APY`}
|
|
description={`Staking enables (3, 3) coordination by aligning long-term incentives, sustainably backed by (1, 1) Bonds, LP fees, and Farming. Stake ${ftsoSymbol} to earn rewards and unlock ${bridgeNumbers} Stake\u00B2.`}
|
|
/>
|
|
|
|
<ProtocolDetail
|
|
isMobileScreen={isMobileScreen}
|
|
theme={theme}
|
|
url={`/${networkName.toLowerCase()}/bridge`}
|
|
name={`${bridgeNumbers} Stake\u00B2`}
|
|
sideName={`${formatNumber(apyInner * gatekeepedApy, 0)}% APY`}
|
|
description={`Staking\u00B2 strategy further deepens long-term incentives powered by sustainable crosschain bridging revenue. ${bridgeNumbers} Stake\u00B2 your ${csprSymbol} to receive organic APY with no warmup and no dilution.`}
|
|
/>
|
|
</Box>
|
|
</Grid>
|
|
)
|
|
}
|
|
|
|
export default ProtocolDetails;
|