334 lines
12 KiB
JavaScript
334 lines
12 KiB
JavaScript
import { Avatar, Box, Link } from "@mui/material";
|
|
import { styled } from "@mui/material/styles";
|
|
|
|
import React, { useEffect, useState } from "react";
|
|
import { useSearchParams } from "react-router-dom";
|
|
|
|
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
|
import { useChainId } from "wagmi";
|
|
|
|
import TokenModal from "./TokenModal";
|
|
import StakeConfirmationModal from "./StakeConfirmationModal";
|
|
import StakeSettingsModal from "./StakeSettingsModal";
|
|
|
|
import SwapCard from "../../../components/Swap/SwapCard";
|
|
import SwapCollection from "../../../components/Swap/SwapCollection";
|
|
import { InfoNotification } from "../../../components/Notification";
|
|
import { PrimaryButton } from "../../../components/Button";
|
|
|
|
import {
|
|
GHST_ADDRESSES,
|
|
FTSO_ADDRESSES,
|
|
STNK_ADDRESSES,
|
|
STAKING_ADDRESSES,
|
|
} from "../../../constants/addresses";
|
|
import { useCurrentIndex } from "../../../hooks/staking";
|
|
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
|
import { formatNumber } from "../../../helpers";
|
|
|
|
const PREFIX = "StakeInputArea";
|
|
|
|
const classes = {
|
|
inputRow: `${PREFIX}-inputRow`,
|
|
gridItem: `${PREFIX}-gridItem`,
|
|
input: `${PREFIX}-input`,
|
|
button: `${PREFIX}-button`,
|
|
};
|
|
|
|
const StyledBox = styled(Box)(({ theme }) => ({
|
|
[`& .${classes.inputRow}`]: {
|
|
justifyContent: "space-around",
|
|
alignItems: "center",
|
|
height: "auto",
|
|
marginTop: "4px",
|
|
},
|
|
|
|
[`& .${classes.gridItem}`]: {
|
|
width: "100%",
|
|
paddingRight: "5px",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
},
|
|
|
|
[`& .${classes.input}`]: {
|
|
[theme.breakpoints.down("md")]: {
|
|
marginBottom: "10px",
|
|
},
|
|
[theme.breakpoints.up("sm")]: {
|
|
marginBottom: "0",
|
|
},
|
|
},
|
|
|
|
[`& .${classes.button}`]: {
|
|
width: "100%",
|
|
minWidth: "163px",
|
|
maxWidth: "542px",
|
|
},
|
|
}));
|
|
|
|
export const StakeInputArea = ({
|
|
upperToken,
|
|
setUpperToken,
|
|
bottomToken,
|
|
setBottomToken,
|
|
action,
|
|
chainId,
|
|
address,
|
|
connect,
|
|
settingsModalOpen,
|
|
closeSettingModal
|
|
}) => {
|
|
const [upperTokenModalOpen, setUpperTokenModalOpen] = useState(false);
|
|
const [bottomTokenModalOpen, setBottomTokenModalOpen] = useState(false);
|
|
const [confirmationModalOpen, setConfirmationModalOpen] = useState(false);
|
|
|
|
const [formatDecimals, setFormatDecimals] = useState(localStorage.getItem("stake-decimals")
|
|
? localStorage.getItem("stake-decimals")
|
|
: "5"
|
|
);
|
|
|
|
const [isClaim, setIsClaim] = useState(localStorage.getItem("stake-isClaim")
|
|
? localStorage.getItem("stake-isClaim") === 'true'
|
|
: true
|
|
);
|
|
|
|
const [isTrigger, setIsTrigger] = useState(localStorage.getItem("stake-isTrigger")
|
|
? localStorage.getItem("stake-isTrigger") === 'true'
|
|
: true
|
|
);
|
|
|
|
const [amount, setAmount] = useState("");
|
|
const [receiveAmount, setReceiveAmount] = useState("");
|
|
const [exceedsAmount, setExceedsAmount] = useState(false)
|
|
|
|
const { currentIndex, refetch: refetchCurrentIndex } = useCurrentIndex(chainId);
|
|
const { balance: ftsoBalance, refetch: ftsoRefetch } = useBalance(chainId, "FTSO", address);
|
|
const { balance: stnkBalance, refetch: stnkRefetch } = useBalance(chainId, "STNK", address);
|
|
const { balance: ghstBalance, refetch: ghstRefetch } = useBalance(chainId, "GHST", address);
|
|
|
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
|
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
|
|
|
const setIsClaimInner = (value) => {
|
|
setIsClaim(value);
|
|
localStorage.setItem("stake-isClaim", value);
|
|
|
|
}
|
|
|
|
const setIsTriggerInner = (value) => {
|
|
setIsTrigger(value);
|
|
localStorage.setItem("stake-isTrigger", value);
|
|
}
|
|
|
|
const setFormatDecimalsInner = (value) => {
|
|
if (Number(value) <= 17) {
|
|
setFormatDecimals(value);
|
|
localStorage.setItem("staking-decimals", value);
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
const innerBalance = upperToken === "GHST" ?
|
|
ghstBalance
|
|
:
|
|
upperToken === "STNK" ?
|
|
stnkBalance
|
|
:
|
|
ftsoBalance;
|
|
|
|
if (
|
|
(upperToken === "FTSO" && bottomToken === "STNK") ||
|
|
(upperToken === "STNK" && bottomToken === "FTSO")
|
|
) {
|
|
setReceiveAmount(amount);
|
|
setExceedsAmount(new DecimalBigNumber(amount, 9).gt(innerBalance))
|
|
} else {
|
|
const decimals = upperToken === "GHST" ? 18 : 9;
|
|
const raw = new DecimalBigNumber(amount, decimals);
|
|
const amountIn = new DecimalBigNumber(raw._value.toBigInt(), decimals);
|
|
const result = upperToken === "GHST" ?
|
|
currentIndex.mul(amountIn).toString()
|
|
:
|
|
currentIndex._value > 0n ? amountIn.div(currentIndex).toString() : "0";
|
|
|
|
const innerBalance = upperToken === "GHST" ?
|
|
ghstBalance
|
|
:
|
|
upperToken === "STNK" ?
|
|
stnkBalance
|
|
:
|
|
ftsoBalance;
|
|
|
|
setReceiveAmount(result);
|
|
setExceedsAmount(amountIn.gt(innerBalance));
|
|
}
|
|
}, [upperToken, bottomToken, amount, currentIndex]);
|
|
|
|
const handleTokenModalInput = (value, isUpper) => {
|
|
if (isUpper) {
|
|
if (value === bottomToken) {
|
|
const newValue = value === "GHST" ? "STNK" : "GHST";
|
|
setBottomToken(newValue)
|
|
}
|
|
setUpperToken(value);
|
|
} else {
|
|
setBottomToken(value);
|
|
}
|
|
}
|
|
|
|
const onSwapClick = () => {
|
|
const tmpUpper = upperToken;
|
|
const tmpBottom = bottomToken;
|
|
setUpperToken(tmpBottom);
|
|
setBottomToken(tmpUpper);
|
|
}
|
|
|
|
const SwapCardTemplate = (tokenName, tokenAmount, isUpper, handleModal) => {
|
|
const balance = tokenName === "STNK" || tokenName === "sCSPR" ?
|
|
stnkBalance : tokenName === "FTSO" || tokenName === "eCSPR" ?
|
|
ftsoBalance : ghstBalance;
|
|
|
|
let realTokenName = "";
|
|
switch (tokenName.toUpperCase()) {
|
|
case "FTSO":
|
|
realTokenName = ftsoSymbol;
|
|
break;
|
|
case "ECSPR":
|
|
realTokenName = ftsoSymbol;
|
|
break;
|
|
case "STNK":
|
|
realTokenName = stnkSymbol;
|
|
break;
|
|
case "SCSPR":
|
|
realTokenName = stnkSymbol;
|
|
break;
|
|
case "GHST":
|
|
realTokenName = ghstSymbol;
|
|
break;
|
|
case "CSPR":
|
|
realTokenName = ghstSymbol;
|
|
break;
|
|
}
|
|
|
|
return (
|
|
<SwapCard
|
|
id={`${tokenName.toLowerCase()}-input`}
|
|
token={tokenName}
|
|
tokenName={realTokenName}
|
|
tokenOnClick={() => handleModal(true)}
|
|
inputProps={{ "data-testid": `${tokenName.toLowerCase()}-input`, min: "0" }}
|
|
value={tokenAmount}
|
|
onChange={event => setAmount(event.target.value)}
|
|
info={`Balance: ${formatNumber(balance, formatDecimals)} ${tokenName}`}
|
|
endString={isUpper ? "Max" : ""}
|
|
endStringOnClick={() => isUpper && setAmount(balance.toString())}
|
|
disabled={!isUpper}
|
|
inputWidth={`${tokenAmount.length > 0 ? tokenAmount.length : 1}ch`}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const closeAndUpdate = () => {
|
|
setAmount("");
|
|
setConfirmationModalOpen(false);
|
|
refetchCurrentIndex();
|
|
ftsoRefetch();
|
|
stnkRefetch();
|
|
ghstRefetch();
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<StyledBox mb={3}>
|
|
<Box display="flex" flexDirection="row" width="100%" justifyContent="center" mt="24px">
|
|
<Box display="flex" flexDirection="column" width="100%" maxWidth="476px">
|
|
<Box mb="21px">
|
|
<SwapCollection
|
|
UpperSwapCard={SwapCardTemplate(upperToken, amount, true, setUpperTokenModalOpen)}
|
|
LowerSwapCard={SwapCardTemplate(bottomToken, receiveAmount, false, setBottomTokenModalOpen)}
|
|
arrowOnClick={onSwapClick}
|
|
/>
|
|
</Box>
|
|
|
|
{upperTokenModalOpen && (
|
|
<TokenModal
|
|
open={upperTokenModalOpen}
|
|
handleSelect={data => handleTokenModalInput(data.token, data.isUpper)}
|
|
handleClose={() => setUpperTokenModalOpen(false)}
|
|
ftsoBalance={formatNumber(ftsoBalance, formatDecimals)}
|
|
stnkBalance={formatNumber(stnkBalance, formatDecimals)}
|
|
ghstBalance={formatNumber(ghstBalance, formatDecimals)}
|
|
isUpper={true}
|
|
ftsoSymbol={ftsoSymbol}
|
|
stnkSymbol={stnkSymbol}
|
|
ghstSymbol={ghstSymbol}
|
|
/>
|
|
)}
|
|
{bottomTokenModalOpen && (
|
|
<TokenModal
|
|
open={bottomTokenModalOpen}
|
|
handleSelect={data => handleTokenModalInput(data.token, data.isUpper)}
|
|
handleClose={() => setBottomTokenModalOpen(false)}
|
|
ftsoBalance={formatNumber(ftsoBalance, formatDecimals)}
|
|
stnkBalance={formatNumber(stnkBalance, formatDecimals)}
|
|
ghstBalance={formatNumber(ghstBalance, formatDecimals)}
|
|
tokenToExclude={upperToken}
|
|
isUpper={false}
|
|
ftsoSymbol={ftsoSymbol}
|
|
stnkSymbol={stnkSymbol}
|
|
ghstSymbol={ghstSymbol}
|
|
/>
|
|
)}
|
|
|
|
<Box>
|
|
<PrimaryButton
|
|
fullWidth
|
|
onClick={() => setConfirmationModalOpen(true)}
|
|
loading={false}
|
|
disabled={exceedsAmount}
|
|
>
|
|
{exceedsAmount ?
|
|
"Exceeds amount"
|
|
:
|
|
action[0] + String(action.toLowerCase()).slice(1)
|
|
}
|
|
</PrimaryButton>
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
</StyledBox>
|
|
<StakeSettingsModal
|
|
open={settingsModalOpen}
|
|
onClose={closeSettingModal}
|
|
formatDecimals={formatDecimals}
|
|
onFormatDecimalsChange={event => setFormatDecimalsInner(event.currentTarget.value)}
|
|
isClaim={isClaim}
|
|
onIsClaimChanged={setIsClaimInner}
|
|
isTrigger={isTrigger}
|
|
onTriggerRebaseChange={setIsTriggerInner}
|
|
/>
|
|
<StakeConfirmationModal
|
|
open={confirmationModalOpen}
|
|
onClose={() => closeAndUpdate()}
|
|
chainId={chainId}
|
|
address={address}
|
|
action={action}
|
|
upperToken={upperToken}
|
|
bottomToken={bottomToken}
|
|
amount={amount}
|
|
receiveAmount={receiveAmount}
|
|
amountExceedsBalance={exceedsAmount}
|
|
connect={connect}
|
|
spendDecimals={upperToken === "GHST" ? 18 : 9}
|
|
receiveDecimals={bottomToken === "GHST" ? 18 : 9}
|
|
isClaim={isClaim}
|
|
isTrigger={isTrigger}
|
|
ftsoSymbol={ftsoSymbol}
|
|
stnkSymbol={stnkSymbol}
|
|
ghstSymbol={ghstSymbol}
|
|
/>
|
|
</>
|
|
);
|
|
};
|