ghost-dao-interface/src/containers/WethWrapper/WethWrapper.jsx
Uncle Fatso e153760532
change dai naming to reserve; flexible network representation
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2025-11-04 14:40:21 +03:00

261 lines
13 KiB
JavaScript

import { useState, useEffect, useMemo } from "react";
import { Box, Container, Typography, useMediaQuery } from "@mui/material";
import { useConfig, useBalance } from "wagmi";
import { Helmet } from "react-helmet";
import ReactGA from "react-ga4";
import PageTitle from "../../components/PageTitle/PageTitle";
import Paper from "../../components/Paper/Paper";
import SwapCard from "../../components/Swap/SwapCard";
import TokenStack from "../../components/TokenStack/TokenStack";
import { PrimaryButton } from "../../components/Button";
import { Tab, Tabs } from "../../components/Tabs/Tabs";
import { RESERVE_ADDRESSES } from "../../constants/addresses";
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { formatCurrency, formatNumber } from "../../helpers";
import {
useBalance as useTokenBalance,
useTokenSymbol,
useTotalSupply,
useConversionRate,
useAccumulatedDonation,
depositNative,
withdrawWeth
} from "../../hooks/tokens";
const WethWrapper = ({ chainId, address, config, connect }) => {
const isSmallScreen = useMediaQuery("(max-width: 650px)");
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
const [chainName, setChainName] = useState("");
const [isMint, setIsMint] = useState(true);
const [isPending, setIsPending] = useState(false);
const [balance, setBalance] = useState(new DecimalBigNumber(0, 0));
const [amount, setAmount] = useState("");
const [scanInfo, setScanInfo] = useState({
name: "",
url: "",
});
const [nativeInfo, setNativeInfo] = useState({
decimals: 18,
name: "",
symbol: "",
})
const { balance: reserveBalance, refetch: reserveBalanceRefetch } = useTokenBalance(chainId, "RESERVE", address);
const { data: nativeBalance, refetch: balanceRefetch } = useBalance({ address });
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
useEffect(() => {
ReactGA.send({ hitType: "pageview", page: "/wrapper" });
}, [])
useEffect(() => {
const value = nativeBalance ? nativeBalance.value : 0n;
const decimals = nativeBalance ? nativeBalance.decimals : 18;
setBalance(new DecimalBigNumber(value, decimals));
}, [nativeBalance]);
useEffect(() => {
let scanName = "";
let scanUrl = "";
const client = config?.getClient();
scanName = client?.chain?.blockExplorers?.default?.name;
scanUrl = client?.chain?.blockExplorers?.default?.url;
setScanInfo({
name: scanName,
url: scanUrl,
})
setChainName(client?.chain?.name);
setNativeInfo(client?.chain?.nativeCurrency)
}, [chainId]);
const changeIsMinted = (value) => {
setAmount("");
setIsMint(value);
}
const preparedAmount = useMemo(() => {
if (address === "") new DecimalBigNumber("0", 0);
const decimals = isMint ? nativeInfo.decimals : 18;
return new DecimalBigNumber(amount, decimals);
}, [amount, balance, nativeInfo])
const estimatedAmountIn = useMemo(() => {
return new DecimalBigNumber(amount, nativeInfo.decimals);
}, [amount, nativeInfo]);
const estimatedAmountOut = useMemo(() => {
return new DecimalBigNumber(amount, nativeInfo.decimals);
}, [amount, nativeInfo]);
const actionOrConnect = async () => {
if (address === "") {
connect();
} else {
setIsPending(true);
if (isMint) {
await depositNative(chainId, address, preparedAmount._value.toString());
} else {
await withdrawWeth(chainId, address, preparedAmount._value.toString());
}
await balanceRefetch();
await reserveBalanceRefetch();
setAmount("");
setIsPending(false);
}
}
return (
<Box height="calc(100vh - 43px)">
<Helmet>
<title>ghostWrapper | WETH9</title>
<meta name="description" content="Standard WETH9 wrapper. Convert native coin to WETH9 representation directly to your wallet." />
<meta name="keywords" content="weth, weth9, ghostFaucet, web3 faucet, ethereum, sepolia, polygon, bnb, bsc, AVAX" />
<meta property="og:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
<meta property="og:title" content="ghostDAO | The DeFi 2.0 cross-chain reserve currency" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:type" content="website" />
<meta property="og:description" content="Standard WETH9 wrapper. Convert native coin to WETH9 representation directly to your wallet." />
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@realGhostChain" />
<meta name="twitter:title" content="ghostDAO | The DeFi 2.0 cross-chain reserve currency" />
<meta name="twitter:description" content="Standard WETH9 wrapper. Convert native coin to WETH9 representation directly to your wallet." />
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
</Helmet>
<PageTitle name={`${reserveSymbol} Faucet`} subtitle={`Swap ${chainName} ${nativeInfo.symbol} for ${reserveSymbol}.`} />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "calc(100vh - 153px)"
}}
>
<Box width="100%" maxWidth="476px" display="flex" alignItems="center" justifyContent="center" flexDirection="column">
<Paper
headerContent={
<Box alignItems="center" justifyContent="space-between" display="flex" width="100%">
<Tabs
centered
textColor="primary"
indicatorColor="primary"
value={isMint ? 0 : 1}
aria-label="Faucet menu"
onChange={(_, view) => changeIsMinted(view === 0)}
TabIndicatorProps={{ style: { display: "none" } }}
>
<Tab aria-label="faucet-mint-button" label="Mint" style={{ fontSize: "1.5rem" }} />
<Tab aria-label="faucet-burn-button" label="Burn" style={{ fontSize: "1.5rem" }} />
</Tabs>
{!isSemiSmallScreen && <PrimaryButton
variant="text"
href={`${scanInfo.url}/token/${RESERVE_ADDRESSES[chainId]}`}
>
Check on {scanInfo.name}
</PrimaryButton>}
</Box>
}
enableBackground
fullWidth
>
<Box>
{isMint && <SwapCard
id={`faucet-sepolia-eth`}
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
tokenName={nativeInfo.symbol}
token={<TokenStack tokens={[nativeInfo.symbol]} sx={{ fontSize: "21px" }} />}
info={`${isSemiSmallScreen ? "" : "Balance: "}${formatCurrency(balance.toString(), 4, nativeInfo.symbol)}`}
value={amount}
onChange={event => setAmount(event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
/>}
{!isMint && <SwapCard
id={`faucet-sepolia-eth`}
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
tokenName={reserveSymbol}
token={<TokenStack tokens={[reserveSymbol]} sx={{ fontSize: "21px" }} />}
info={`${formatCurrency(reserveBalance.toString(), 4, reserveSymbol)}`}
value={amount}
onChange={event => setAmount(event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
endString={"Max"}
endStringOnClick={() => setAmount(reserveBalance.toString())}
/>}
<Box
mb="20px"
mt="20px"
flexDirection="column"
display="flex"
justifyContent="space-between"
>
{isMint && (
<>
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">You will get:</Typography>}
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(estimatedAmountIn, 5, reserveSymbol)}</Typography>
</Box>
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Your {reserveSymbol} balance:</Typography>}
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(reserveBalance, 5, reserveSymbol)}</Typography>
</Box>
</>
)}
{!isMint && (
<>
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">You will get:</Typography>}
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(estimatedAmountOut, 5, nativeInfo.symbol)}</Typography>
</Box>
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Your {nativeInfo.symbol} balance:</Typography>}
<Typography fontSize="12px" lineHeight="15px">{formatCurrency(balance, 5, nativeInfo.symbol)}</Typography>
</Box>
</>
)}
</Box>
<PrimaryButton
fullWidth
disabled={
address !== "" && (
preparedAmount?._value === 0n ||
isPending ||
(isMint && balance?.lt(preparedAmount)) ||
(!isMint && reserveBalance?.lt(preparedAmount))
)
}
loading={isPending}
onClick={() => actionOrConnect()}
>
{address === "" ?
"Connect"
:
isMint ? "Mint" : "Burn"
}
</PrimaryButton>
</Box>
</Paper>
</Box>
</Container>
</Box>
)
}
export default WethWrapper;