Compare commits
No commits in common. "3f9003883d50a316b69ecda150f1c57aba48e83b" and "e9eff0b651a35c3c2ad40c6bdc7b4ffa88ad5af9" have entirely different histories.
3f9003883d
...
e9eff0b651
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ghost-dao-interface",
|
||||
"private": true,
|
||||
"version": "0.7.0",
|
||||
"version": "0.6.14",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@ -22,7 +22,7 @@ import Sidebar from "./components/Sidebar/Sidebar";
|
||||
import TopBar from "./components/TopBar/TopBar";
|
||||
|
||||
import { shouldTriggerSafetyCheck } from "./helpers";
|
||||
import { isNetworkAvailable, isGovernanceAvailable } from "./constants";
|
||||
import { isNetworkAvailable, isNetworkLegacy, isGovernanceAvailable } from "./constants";
|
||||
import useTheme from "./hooks/useTheme";
|
||||
import { useUnstableProvider } from "./hooks/ghost";
|
||||
import { dark as darkTheme } from "./themes/dark.js";
|
||||
@ -34,6 +34,8 @@ const Bonds = lazy(() => import("./containers/Bond/Bonds"));
|
||||
const BondModalContainer = lazy(() => import("./containers/Bond/BondModal"));
|
||||
const StakeContainer = lazy(() => import("./containers/Stake/StakeContainer"));
|
||||
const TreasuryDashboard = lazy(() => import("./containers/TreasuryDashboard/TreasuryDashboard"));
|
||||
const Faucet = lazy(() => import("./containers/Faucet/Faucet"));
|
||||
const Wrapper = lazy(() => import("./containers/WethWrapper/WethWrapper"));
|
||||
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
||||
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
||||
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
||||
@ -217,6 +219,10 @@ function App() {
|
||||
<Route path="bonds" element={<Bonds connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="bonds/:id" element={<BondModalContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="stake" element={<StakeContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
{isNetworkLegacy(chainId)
|
||||
? <Route path="faucet" element={<Faucet config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
: <Route path="wrapper" element={<Wrapper config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
}
|
||||
<Route path="bridge" element={<Bridge config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
<Route path="dex/:name" element={<Dex config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||
{isGovernanceAvailable(chainId, addressChainId) && <Route path="governance" element={<Governance config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
|
||||
|
||||
@ -40,14 +40,13 @@ import BondIcon from "../Icon/BondIcon";
|
||||
import StakeIcon from "../Icon/StakeIcon";
|
||||
import WrapIcon from "../Icon/WrapIcon";
|
||||
|
||||
import { isNetworkAvailable, isGovernanceAvailable } from "../../constants";
|
||||
import { isNetworkAvailable, isNetworkLegacy, isGovernanceAvailable } from "../../constants";
|
||||
import { AVAILABLE_DEXES } from "../../constants/dexes";
|
||||
import { GATEKEEPER_ADDRESSES } from "../../constants/addresses";
|
||||
import { ECOSYSTEM } from "../../constants/ecosystem";
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { sortBondsByDiscount, formatCurrency } from "../../helpers";
|
||||
import BondDiscount from "../../containers/Bond/components/BondDiscount";
|
||||
import Chip from "../Chip/Chip";
|
||||
|
||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import ShowerIcon from '@mui/icons-material/Shower';
|
||||
@ -144,9 +143,6 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
to={`/${chainName}/bonds`}
|
||||
children={
|
||||
<AccordionDetails style={{ margin: "0 0 -20px", display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||
<Box width="180px" mb="10px" ml="auto">
|
||||
<Typography component="span" variant="body2">Bond Discounts</Typography>
|
||||
</Box>
|
||||
{sortBondsByDiscount(ghostBonds).map((bond, index) => {
|
||||
return (
|
||||
<Link
|
||||
@ -160,7 +156,6 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
style={{
|
||||
width: "180px",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
gap: "10px"
|
||||
}}
|
||||
@ -168,10 +163,7 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
variant="body2"
|
||||
>
|
||||
{bond.displayName}
|
||||
{bond.soldOut
|
||||
? <Chip label="Sold Out" template="darkGray" />
|
||||
: <BondDiscount discount={bond.discount} />
|
||||
}
|
||||
<BondDiscount textOnly discount={bond.discount} />
|
||||
</Typography>
|
||||
</Box>
|
||||
</Link>
|
||||
@ -180,7 +172,7 @@ const NavContent = ({ chainId, addressChainId }) => {
|
||||
</AccordionDetails>
|
||||
}
|
||||
/>
|
||||
<NavItem icon={ForkRightIcon} label={`${bridgeNumbers} Stake\u00B2`} to={`/${chainName}/bridge`} />
|
||||
<NavItem icon={ForkRightIcon} label={`${bridgeNumbers} GHOST Staking`} to={`/${chainName}/bridge`} />
|
||||
{isGovernanceAvailable(chainId, addressChainId) && <NavItem icon={GavelIcon} label={`Governance`} to={`/${chainName}/governance`} />}
|
||||
<Box className="menu-divider">
|
||||
<Divider />
|
||||
|
||||
@ -151,6 +151,18 @@ function InitialWalletView({ isWalletOpen, address, chainId, onClose }) {
|
||||
<Divider />
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{ display: "flex", flexDirection: "column" }}
|
||||
style={{ gap: theme.spacing(1.5) }}
|
||||
>
|
||||
<SecondaryButton
|
||||
fullWidth
|
||||
onClick={() => onBtnClick("uniswap", RESERVE_ADDRESSES[chainId], FTSO_ADDRESSES[chainId])}
|
||||
>
|
||||
<Typography>{`${tokens?.ftso?.symbol}-${tokens?.reserve?.symbol} on Uniswap`}</Typography>
|
||||
</SecondaryButton>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ width: "100%", marginTop: "auto", marginX: "auto", padding: theme.spacing(2, 0) }}>
|
||||
<DisconnectButton onClose={onClose} />
|
||||
</Box>
|
||||
|
||||
@ -15,6 +15,7 @@ import { useQuery } from "react-query";
|
||||
import { formatCurrency, formatNumber } from "../../../helpers";
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber"
|
||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||
import { isNetworkLegacy } from "../../../constants";
|
||||
import { EMPTY_ADDRESS } from "../../../constants/addresses";
|
||||
|
||||
import GhostStyledIcon from "../../Icon/GhostIcon";
|
||||
@ -239,8 +240,10 @@ export const useWallet = (chainId, userAddress) => {
|
||||
address: reserveAddress,
|
||||
balance: reserveBalance,
|
||||
price: reservePrice,
|
||||
icons: [tokenNameConverter(chainId, reserveSymbol)],
|
||||
externalUrl: "https://ghostchain.io/wp-content/uploads/2025/11/6A-Classic-ETC-Token.svg",
|
||||
icons: isNetworkLegacy(chainId) ? ["GDAI"] : [tokenNameConverter(chainId, reserveSymbol)],
|
||||
externalUrl: isNetworkLegacy(chainId)
|
||||
? "https://ghostchain.io/wp-content/uploads/2025/03/gDAI.svg"
|
||||
: "https://ghostchain.io/wp-content/uploads/2025/11/6A-Classic-ETC-Token.svg",
|
||||
refetch: reserveRefetch,
|
||||
},
|
||||
ftso: {
|
||||
|
||||
@ -42,10 +42,7 @@ export const isNetworkAvailable = (chainId, addressChainId) => {
|
||||
export const isNetworkLegacy = (chainId) => {
|
||||
let isLegacy = false;
|
||||
switch (chainId) {
|
||||
case 11155111:
|
||||
isLegacy = true
|
||||
break;
|
||||
case 63:
|
||||
case 560048:
|
||||
isLegacy = true
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -4,25 +4,25 @@ export const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||
|
||||
export const STAKING_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506",
|
||||
[NetworkId.TESTNET_HOODI]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506",
|
||||
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
||||
[NetworkId.TESTNET_MORDOR]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506",
|
||||
};
|
||||
|
||||
export const BOND_DEPOSITORY_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x46BF6F7c3e96351eab7542f2B14c9f2ac6d08dF0",
|
||||
[NetworkId.TESTNET_HOODI]: "0x46BF6F7c3e96351eab7542f2B14c9f2ac6d08dF0",
|
||||
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x46BF6F7c3e96351eab7542f2B14c9f2ac6d08dF0",
|
||||
};
|
||||
|
||||
export const DAO_TREASURY_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x05D797f9F34844594C956da58f1785997397f02E",
|
||||
[NetworkId.TESTNET_HOODI]: "0x05D797f9F34844594C956da58f1785997397f02E",
|
||||
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x05D797f9F34844594C956da58f1785997397f02E",
|
||||
};
|
||||
|
||||
export const FTSO_DAI_LP_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xCd1505E5d169525e0241c177aF5929A92E02276D",
|
||||
[NetworkId.TESTNET_HOODI]: "0x32388605b5E83Ea79CDdC479AA9939DBCF98f59D",
|
||||
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x53B13C4722081c405ce25c7A7629fC326A49a469",
|
||||
};
|
||||
|
||||
@ -34,7 +34,7 @@ export const FTSO_STNK_LP_ADDRESSES = {
|
||||
|
||||
export const RESERVE_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
|
||||
[NetworkId.TESTNET_HOODI]: "0xE69a5c6dd88cA798b93c3C92fc50c51Fd5305eB4",
|
||||
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
||||
};
|
||||
|
||||
@ -46,43 +46,41 @@ export const WETH_ADDRESSES = {
|
||||
|
||||
export const GHST_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x1eCee8BfceC44e535B3Ee92Aca70507668781392",
|
||||
[NetworkId.TESTNET_HOODI]: "0x1eCee8BfceC44e535B3Ee92Aca70507668781392",
|
||||
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x1eCee8BfceC44e535B3Ee92Aca70507668781392",
|
||||
};
|
||||
|
||||
export const STNK_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xa31cf59baC26Dd8A8b422b999eB1Ba541C941EA7",
|
||||
[NetworkId.TESTNET_HOODI]: "0xa31cf59baC26Dd8A8b422b999eB1Ba541C941EA7",
|
||||
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
||||
[NetworkId.TESTNET_MORDOR]: "0xa31cf59baC26Dd8A8b422b999eB1Ba541C941EA7",
|
||||
};
|
||||
|
||||
export const FTSO_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0x7ebd1224D36d64eA09312073e60f352d1383801A",
|
||||
[NetworkId.TESTNET_HOODI]: "0x7ebd1224D36d64eA09312073e60f352d1383801A",
|
||||
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x7ebd1224D36d64eA09312073e60f352d1383801A",
|
||||
};
|
||||
|
||||
export const DISTRIBUTOR_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xfa524772eec78FAeD0db2cF8A831FDDa9F5B0544",
|
||||
[NetworkId.TESTNET_HOODI]: "0xfa524772eec78FAeD0db2cF8A831FDDa9F5B0544",
|
||||
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
||||
[NetworkId.TESTNET_MORDOR]: "0xfa524772eec78FAeD0db2cF8A831FDDa9F5B0544",
|
||||
};
|
||||
|
||||
export const GHOST_GOVERNANCE_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xaf7Ad1b83C47405BB9aa96868bCFbb6D65e4C2a1",
|
||||
[NetworkId.TESTNET_HOODI]: "0xF950101af53733Ccf9309Ef4CC374B300dd43010",
|
||||
[NetworkId.TESTNET_MORDOR]: "0xF950101af53733Ccf9309Ef4CC374B300dd43010",
|
||||
};
|
||||
|
||||
export const BONDING_CALCULATOR_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xfA821181de76D3EAdb404dDe971A6d28289F22b3",
|
||||
[NetworkId.TESTNET_HOODI]: "0xfA821181de76D3EAdb404dDe971A6d28289F22b3",
|
||||
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
||||
[NetworkId.TESTNET_MORDOR]: "0xfA821181de76D3EAdb404dDe971A6d28289F22b3",
|
||||
}
|
||||
|
||||
export const GATEKEEPER_ADDRESSES = {
|
||||
[NetworkId.TESTNET_SEPOLIA]: "0xd735cA07984a16911222c08411A80e24EB38869B",
|
||||
[NetworkId.TESTNET_HOODI]: "0x4823F1DC785D721eAdD2bD218E1eeD63aF67fBF4",
|
||||
[NetworkId.TESTNET_MORDOR]: "0x4823F1DC785D721eAdD2bD218E1eeD63aF67fBF4",
|
||||
}
|
||||
|
||||
@ -118,10 +116,6 @@ export const CEX_TICKERS = {
|
||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT",
|
||||
"https://api.coinbase.com/v2/prices/ETH-USDT/spot",
|
||||
],
|
||||
[NetworkId.TESTNET_HOODI]: [
|
||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT",
|
||||
"https://api.coinbase.com/v2/prices/ETH-USDT/spot",
|
||||
],
|
||||
[NetworkId.TESTNET_MORDOR]: [
|
||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
||||
"https://api.coinbase.com/v2/prices/ETC-USDT/spot",
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { ArrowBack } from "@mui/icons-material";
|
||||
import { Box, Link, Skeleton, Typography } from "@mui/material";
|
||||
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
import { Link as RouterLink, useLocation, useParams, useNavigate } from "react-router-dom";
|
||||
import { useAccount, useSwitchChain } from "wagmi";
|
||||
import { isAddress } from "viem";
|
||||
import ReactGA from "react-ga4";
|
||||
|
||||
import PageTitle from "../../components/PageTitle/PageTitle";
|
||||
@ -21,7 +20,6 @@ import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { NetworkId } from "../../constants";
|
||||
import { formatCurrency } from "../../helpers";
|
||||
|
||||
import { useLocalStorage } from "../../hooks/localstorage";
|
||||
import { useLiveBonds } from "../../hooks/bonds";
|
||||
import { useFtsoPrice } from "../../hooks/prices";
|
||||
|
||||
@ -40,38 +38,29 @@ export const BondModal = ({ bond, chainId, address, connect }) => {
|
||||
const { network } = useParams();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const [slippage, setSlippage] = useState(localStorage.getItem("bond-slippage") || "10");
|
||||
const [formatDecimals, setFormatDecimals] = useState(localStorage.getItem("bond-decimals") || "5");
|
||||
const [isSettingsOpen, setSettingsOpen] = useState(false);
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
|
||||
const [slippage, setSlippage] = useState(() => getStorageValue(chainId, address, "bond-slippage", "10"));
|
||||
const [formatDecimals, setFormatDecimals] = useState(() => getStorageValue(chainId, address, "bond-decimals", "5"));
|
||||
const [recipientAddress, setRecipientAddressInner] = useState(() => getStorageValue(chainId, address, "bond-recipient", address));
|
||||
const [recipientAddress, setRecipientAddress] = useState(address);
|
||||
|
||||
useEffect(() => {
|
||||
ReactGA.send({ hitType: "pageview", page: pathname });
|
||||
}, [])
|
||||
|
||||
const setRecipientAddress = useCallback((value) => {
|
||||
setRecipientAddressInner(value);
|
||||
if (isAddress(value)) {
|
||||
setStorageValue(chainId, address, "bond-recipient", value);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
|
||||
const setSlippageInner = useCallback((value) => {
|
||||
const setSlippageInner = (value) => {
|
||||
const maybeValue = parseFloat(value);
|
||||
if (!maybeValue || parseFloat(value) <= 100) {
|
||||
setSlippage(value);
|
||||
setStorageValue(chainId, address, "bond-slippage", value);
|
||||
localStorage.setItem("bond-slippage", value);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
}
|
||||
|
||||
const setFormatDecimalsInner = useCallback((value) => {
|
||||
const setFormatDecimalsInner = (value) => {
|
||||
if (Number(value) <= 17) {
|
||||
setFormatDecimals(value);
|
||||
setStorageValue(chainId, address, "bond-decimals", value);
|
||||
localStorage.setItem("bond-decimals", value);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event) => {
|
||||
|
||||
@ -20,7 +20,6 @@ import { formatCurrency } from "../../../helpers";
|
||||
import { useCurrentIndex, useEpoch, useWarmupLength, useWarmupInfo } from "../../../hooks/staking";
|
||||
import { useNotes, redeem } from "../../../hooks/bonds";
|
||||
import { useTokenSymbol } from "../../../hooks/tokens";
|
||||
import { useGhstPrice } from "../../../hooks/prices";
|
||||
|
||||
export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
||||
const isSmallScreen = useScreenSize("md");
|
||||
@ -29,7 +28,6 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
||||
const [isPreClaimConfirmed, setPreClaimConfirmed] = useState(false);
|
||||
const [isPayoutGhst, _] = useState(true);
|
||||
|
||||
const ghstPrice = useGhstPrice(chainId);
|
||||
const { epoch } = useEpoch(chainId);
|
||||
const { warmupExists } = useWarmupLength(chainId);
|
||||
const { warmupInfo } = useWarmupInfo(chainId, BOND_DEPOSITORY_ADDRESSES[chainId]);
|
||||
@ -99,8 +97,6 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
||||
? formatCurrency(totalClaimableBalance, 5, ghstSymbol)
|
||||
: formatCurrency(currentIndex.mul(totalClaimableBalance), 5, stnkSymbol)
|
||||
}
|
||||
|
||||
({formatCurrency(totalClaimableBalance * ghstPrice, 2)})
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
@ -143,15 +139,12 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
||||
|
||||
<Box display="flex" justifyContent="space-between" mt="8px">
|
||||
<Typography>Payout</Typography>
|
||||
<Box display="flex" flexDirection="column" alignItems="flex-end">
|
||||
<Typography>
|
||||
{isPayoutGhst
|
||||
? formatCurrency(note.payout, 5, ghstSymbol)
|
||||
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
||||
}
|
||||
</Typography>
|
||||
<Typography>{formatCurrency(note.payout * ghstPrice, 2)}</Typography>
|
||||
</Box>
|
||||
<Typography>
|
||||
{isPayoutGhst
|
||||
? formatCurrency(note.payout, 5, ghstSymbol)
|
||||
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
||||
}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box mt="16px">
|
||||
@ -202,15 +195,12 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
||||
</TableCell>
|
||||
|
||||
<TableCell style={{ padding: "8px 0" }}>
|
||||
<Box display="flex" flexDirection="column" alignItems="flex-start">
|
||||
<Typography>
|
||||
{isPayoutGhst
|
||||
? formatCurrency(note.payout, 5, ghstSymbol)
|
||||
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
||||
}
|
||||
</Typography>
|
||||
<Typography variant="body2">{formatCurrency(note.payout * ghstPrice, 2)}</Typography>
|
||||
</Box>
|
||||
<Typography>
|
||||
{isPayoutGhst
|
||||
? formatCurrency(note.payout, 5, ghstSymbol)
|
||||
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
|
||||
}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
|
||||
<TableCell style={{ padding: "8px 0" }}>
|
||||
|
||||
@ -46,13 +46,14 @@ import {
|
||||
useLatestBlockNumber,
|
||||
useEraIndex,
|
||||
} from "../../hooks/ghost";
|
||||
import { useLocalStorage } from "../../hooks/localstorage";
|
||||
|
||||
import { ValidatorTable } from "./ValidatorTable";
|
||||
import { BridgeModal, BridgeConfirmModal } from "./BridgeModal";
|
||||
import { BridgeHeader } from "./BridgeHeader";
|
||||
import { BridgeCardAction, BridgeCardHistory } from "./BridgeCard";
|
||||
|
||||
const STORAGE_PREFIX = "storedTransactions"
|
||||
|
||||
const Bridge = ({ chainId, address, config, connect }) => {
|
||||
const isBigScreen = useMediaQuery("(max-width: 980px)")
|
||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||
@ -66,15 +67,14 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
||||
const [bridgeAction, setBridgeAction] = useState(true);
|
||||
const [currentTime, setCurrentTime] = useState(Date.now());
|
||||
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => setCurrentTime(Date.now()), 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const [storedTransactions, setStoredTransactions] = useState(() =>
|
||||
getStorageValue(chainId, address, "bridge-txs", [])
|
||||
const initialStoredTransactions = localStorage.getItem(STORAGE_PREFIX);
|
||||
const [storedTransactions, setStoredTransactions] = useState(
|
||||
initialStoredTransactions ? JSON.parse(initialStoredTransactions) : []
|
||||
);
|
||||
|
||||
const { gatekeeperAddress } = useGatekeeperAddress(chainId);
|
||||
@ -281,7 +281,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
||||
const removeStoredRecord = useCallback(() => {
|
||||
const newStoredTransactions = storedTransactions.filter((_, index) => index !== activeTxIndex)
|
||||
setStoredTransactions(newStoredTransactions);
|
||||
setStorageValue(chainId, address, "bridge-txs", newStoredTransactions);
|
||||
localStorage.setItem(storagePrefix, JSON.stringify(newStoredTransactions));
|
||||
setActiveTxIndex(-1);
|
||||
}, [storedTransactions, activeTxIndex, setStoredTransactions, setActiveTxIndex]);
|
||||
|
||||
@ -307,8 +307,8 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
||||
|
||||
const newStoredTransactions = [transaction, ...storedTransactions];
|
||||
setStoredTransactions(newStoredTransactions);
|
||||
setStorageValue(chainId, address, "bridge-txs", newStoredTransactions);
|
||||
setActiveTxIndex(0);
|
||||
localStorage.setItem(STORAGE_PREFIX, JSON.stringify(newStoredTransactions));
|
||||
setActiveTxIndex(0)
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
import { Box, Typography, Link, FormControlLabel, Checkbox, useTheme } from "@mui/material";
|
||||
import { CheckBoxOutlineBlank, CheckBoxOutlined } from "@mui/icons-material";
|
||||
@ -19,11 +19,10 @@ import ContentPasteIcon from '@mui/icons-material/ContentPaste';
|
||||
import InfoTooltip from "../../components/Tooltip/InfoTooltip";
|
||||
import Modal from "../../components/Modal/Modal";
|
||||
import GhostStyledIcon from "../../components/Icon/GhostIcon";
|
||||
import { PrimaryButton, TertiaryButton, SecondaryButton } from "../../components/Button";
|
||||
import { PrimaryButton, TertiaryButton } from "../../components/Button";
|
||||
|
||||
import { formatCurrency } from "../../helpers";
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { GATEKEEPER_ADDRESSES } from "../../constants/addresses";
|
||||
|
||||
export const BridgeModal = ({
|
||||
providerDetail,
|
||||
@ -51,12 +50,6 @@ export const BridgeModal = ({
|
||||
});
|
||||
};
|
||||
|
||||
const bridgeNumbers = () => {
|
||||
const connectedNetworks = Object.keys(GATEKEEPER_ADDRESSES).length;
|
||||
const number = 1 + connectedNetworks * 3;
|
||||
return `(${number}, ${number})`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
data-testid="transaction-details-modal"
|
||||
@ -96,43 +89,15 @@ export const BridgeModal = ({
|
||||
minHeight={"100px"}
|
||||
>
|
||||
<Box display="flex" gap="1.5rem" flexDirection="column" marginTop=".8rem">
|
||||
{!providerDetail && <Box
|
||||
width="90%"
|
||||
display="flex"
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
backgroundColor="#1f4771"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '130px',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
<SecondaryButton
|
||||
{!providerDetail && <Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
|
||||
<TertiaryButton
|
||||
fullWidth
|
||||
sx={{
|
||||
marginTop: "0 !important",
|
||||
marginBottom: "0 !important"
|
||||
}}
|
||||
onClick={() => window.open(
|
||||
'https://git.ghostchain.io/ghostchain/ghost-extension-wallet/releases',
|
||||
'_blank',
|
||||
'noopener,noreferrer'
|
||||
)}
|
||||
onClick={() => window.open('https://git.ghostchain.io/ghostchain/ghost-extension-wallet/releases', '_blank', 'noopener,noreferrer')}
|
||||
>
|
||||
Get GHOST Connect
|
||||
</SecondaryButton>
|
||||
</TertiaryButton>
|
||||
</Box>}
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
sx={{ filter: providerDetail ? '' : 'blur(5px)' }}
|
||||
>
|
||||
{providerDetail && <Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
|
||||
{currentRecord?.finalization > 0 && (
|
||||
<>
|
||||
<Box
|
||||
@ -320,7 +285,7 @@ export const BridgeModal = ({
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Box>}
|
||||
|
||||
<Box display="flex" flexDirection="column" gap="5px" padding="0.6rem 0">
|
||||
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
||||
@ -392,21 +357,13 @@ export const BridgeModal = ({
|
||||
</Box>
|
||||
|
||||
<Box display="flex" flexDirection="column" gap="5px">
|
||||
{currentRecord && currentRecord.finalization < 1 && currentRecord.applaused && <PrimaryButton
|
||||
fullWidth
|
||||
loading={false}
|
||||
onClick={() => removeStoredRecord()}
|
||||
>
|
||||
{`Get ${bridgeNumbers()} Stake\u00B2`}
|
||||
</PrimaryButton>}
|
||||
|
||||
<TertiaryButton
|
||||
<PrimaryButton
|
||||
fullWidth
|
||||
loading={false}
|
||||
onClick={() => removeStoredRecord()}
|
||||
>
|
||||
Erase Record
|
||||
</TertiaryButton>
|
||||
</PrimaryButton>
|
||||
|
||||
<Typography variant="body2" sx={{ fontStyle: "italic" }}>
|
||||
This will permanently remove the bridge transaction record from the session storage, but it will not cancel the bridge transaction.
|
||||
@ -442,12 +399,6 @@ export const BridgeConfirmModal = ({
|
||||
>
|
||||
<Box gap="20px" display="flex" flexDirection="column" justifyContent="space-between" alignItems="center">
|
||||
<Box width="100%" display="flex" flexDirection="column" alignItems="start">
|
||||
<Box>
|
||||
<Typography variant="subtitle1">
|
||||
You are bridging to GHOST Chain. We will guide you towards (10, 10) Stake<sup>2</sup> rewards right after that.
|
||||
</Typography>
|
||||
</Box>
|
||||
<hr style={{ margin: "10px 0", width: "100%" }} />
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@ -483,7 +434,7 @@ export const BridgeConfirmModal = ({
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<hr style={{ margin: "10px 0", width: "100%" }} />
|
||||
<hr style={{ margin: "10px 0", width: "100%" }} />
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
|
||||
@ -10,10 +10,9 @@ import {
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import { useEffect, useMemo, useState, useCallback } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useParams, useLocation, useSearchParams } from "react-router-dom";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { isAddress } from "viem";
|
||||
import ReactGA from "react-ga4";
|
||||
|
||||
import InfoTooltip from "../../components/Tooltip/InfoTooltip";
|
||||
@ -32,7 +31,6 @@ import {
|
||||
EMPTY_ADDRESS,
|
||||
WETH_ADDRESSES,
|
||||
} from "../../constants/addresses";
|
||||
import { useLocalStorage } from "../../hooks/localstorage";
|
||||
import { useTokenSymbol } from "../../hooks/tokens";
|
||||
import { getTokenAddress } from "../../hooks/helpers";
|
||||
|
||||
@ -45,7 +43,6 @@ const Dex = ({ chainId, address, connect, config }) => {
|
||||
const pathname = useParams();
|
||||
|
||||
const theme = useTheme();
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
|
||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||
@ -58,10 +55,10 @@ const Dex = ({ chainId, address, connect, config }) => {
|
||||
const [topTokenListOpen, setTopTokenListOpen] = useState(false);
|
||||
const [bottomTokenListOpen, setBottomTokenListOpen] = useState(false);
|
||||
|
||||
const [secondsToWait, setSecondsToWait] = useState(() => getStorageValue(chainId, address, "dex-deadline", "60"));
|
||||
const [slippage, setSlippage] = useState(() => getStorageValue(chainId, address, "dex-slippage", "5"));
|
||||
const [formatDecimals, setFormatDecimals] = useState(() => getStorageValue(chainId, address, "dex-decimals", "5"));
|
||||
const [actualDestinationAddress, setActualDestinationAddress] = useState(() => getStorageValue(chainId, address, "dex-destination", address));
|
||||
const [secondsToWait, setSecondsToWait] = useState(localStorage.getItem("dex-deadline") || "60");
|
||||
const [slippage, setSlippage] = useState(localStorage.getItem("dex-slippage") || "5");
|
||||
const [formatDecimals, setFormatDecimals] = useState(localStorage.getItem("dex-decimals") || "5");
|
||||
const [actualDestinationAddress, setActualDestinationAddress] = useState(localStorage.getItem("dex-destination"));
|
||||
const [destinationAddress, setDestinationAddress] = useState(actualDestinationAddress);
|
||||
|
||||
const [tokenAddressTop, setTokenAddressTop] = useState(EMPTY_ADDRESS);
|
||||
@ -183,34 +180,38 @@ const Dex = ({ chainId, address, connect, config }) => {
|
||||
setSearchParams(newQueryParameters);
|
||||
}
|
||||
|
||||
const setSlippageInner = useCallback((value) => {
|
||||
const setSlippageInner = (value) => {
|
||||
const maybeValue = parseFloat(value);
|
||||
if (!maybeValue || parseFloat(value) <= 100) {
|
||||
setSlippage(value);
|
||||
setStorageValue(chainId, address, "dex-slippage", value);
|
||||
localStorage.setItem("dex-slippage", value);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
}
|
||||
|
||||
const setSecondsToWaitInner = useCallback((value) => {
|
||||
const setSecondsToWaitInner = (value) => {
|
||||
localStorage.setItem("dex-deadline", value);
|
||||
setSecondsToWait(value);
|
||||
setStorageValue(chainId, address, "dex-deadline", value);
|
||||
}, [chainId, address]);
|
||||
}
|
||||
|
||||
const setFormatDecimalsInner = useCallback((value) => {
|
||||
const setFormatDecimalsInner = (value) => {
|
||||
if (Number(value) <= 17) {
|
||||
localStorage.setItem("dex-decimals", value);
|
||||
setFormatDecimals(value);
|
||||
setStorageValue(chainId, address, "dex-decimals", value);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
}
|
||||
|
||||
const setDestinationAddressInner = useCallback((value) => {
|
||||
const setDestinationAddressInner = (value) => {
|
||||
const cleanedValue = value.trim();
|
||||
setDestinationAddress(value);
|
||||
if (isAddress(cleanedValue)) {
|
||||
const isEvmAddress = /^0x[a-fA-F0-9]{40}$/.test(cleanedValue);
|
||||
if (isEvmAddress) {
|
||||
localStorage.setItem("dex-destination", value);
|
||||
setActualDestinationAddress(value);
|
||||
setStorageValue(chainId, address, "dex-destination", value);
|
||||
} else if (!isEvmAddress && actualDestinationAddress) {
|
||||
localStorage.removeItem("dex-destination");
|
||||
setActualDestinationAddress(undefined);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
setDestinationAddress(value);
|
||||
}
|
||||
|
||||
const handleCloseSetting = () => {
|
||||
setDestinationAddress(undefined);
|
||||
@ -254,7 +255,7 @@ const Dex = ({ chainId, address, connect, config }) => {
|
||||
}}
|
||||
>
|
||||
<Modal
|
||||
maxWidth="450px"
|
||||
maxWidth="376px"
|
||||
minHeight="200px"
|
||||
open={settingsOpen}
|
||||
headerText={"Settings"}
|
||||
|
||||
@ -20,6 +20,7 @@ import TokenStack from "../../components/TokenStack/TokenStack";
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { formatNumber } from "../../helpers/";
|
||||
import { useBalance, useTokenSymbol } from "../../hooks/tokens";
|
||||
import { isNetworkLegacy } from "../../constants";
|
||||
import {
|
||||
RESERVE_ADDRESSES,
|
||||
FTSO_ADDRESSES,
|
||||
@ -71,7 +72,7 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT
|
||||
},
|
||||
{
|
||||
name: reserveSymbol,
|
||||
icons: [chainSymbol],
|
||||
icons: isNetworkLegacy(chainId) ? ["GDAI"] : [chainSymbol],
|
||||
balance: reserveBalance,
|
||||
address: RESERVE_ADDRESSES[chainId]
|
||||
},
|
||||
|
||||
@ -28,7 +28,6 @@ import PageTitle from "../../components/PageTitle/PageTitle";
|
||||
import { PrimaryButton, TertiaryButton } from "../../components/Button";
|
||||
import { TokenAllowanceGuard } from "../../components/TokenAllowanceGuard/TokenAllowanceGuard";
|
||||
|
||||
import { useLocalStorage } from "../../hooks/localstorage";
|
||||
import { useTokenSymbol, useBalance } from "../../hooks/tokens";
|
||||
import { useProposalThreshold, useProposalHash, propose } from "../../hooks/governance";
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
@ -43,10 +42,11 @@ const NewProposal = ({ config, address, connect, chainId }) => {
|
||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
||||
|
||||
const theme = useTheme();
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
|
||||
const myStoredProposals = getStorageValue(chainId, address, MY_PROPOSALS_PREFIX, []);
|
||||
const [myProposals, setMyProposalsInner] = useState(() => myStoredProposals.map(id => BigInt(id)));
|
||||
const myStoredProposals = localStorage.getItem(`${MY_PROPOSALS_PREFIX}-${chainId}-${address}`);
|
||||
const [myProposals, setMyProposals] = useState(
|
||||
myStoredProposals ? JSON.parse(myStoredProposals).map(id => BigInt(id)) : []
|
||||
);
|
||||
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
const [isModalOpened, setIsModalOpened] = useState(false);
|
||||
@ -61,10 +61,10 @@ const NewProposal = ({ config, address, connect, chainId }) => {
|
||||
proposalDescription
|
||||
} = useProposalHash(chainId, proposalFunctions);
|
||||
|
||||
const setMyProposals = useCallback((proposals) => {
|
||||
setMyProposalsInner(proposals);
|
||||
setStorageValue(chainId, address, MY_PROPOSALS_PREFIX, proposals.map(id => id.toString()))
|
||||
}, [chainId, address]);
|
||||
useEffect(() => {
|
||||
const toStore = JSON.stringify(myProposals.map(id => id.toString()));
|
||||
localStorage.setItem(`${MY_PROPOSALS_PREFIX}-${chainId}-${address}`, toStore);
|
||||
}, [myProposals]);
|
||||
|
||||
useEffect(() => {
|
||||
ReactGA.send({ hitType: "pageview", page: "/governance/create" });
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
import ReactGA from "react-ga4";
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
@ -38,7 +38,6 @@ import { parseFunctionCalldata } from "./components/functions";
|
||||
|
||||
import { networkAvgBlockSpeed } from "../../constants";
|
||||
|
||||
import { useLocalStorage } from "../../hooks/localstorage";
|
||||
import { useTokenSymbol, usePastTotalSupply, usePastVotes, useBalance } from "../../hooks/tokens";
|
||||
import {
|
||||
getVoteValue,
|
||||
@ -76,6 +75,7 @@ import RepeatIcon from '@mui/icons-material/Repeat';
|
||||
|
||||
const HUNDRED = new DecimalBigNumber(100n, 0);
|
||||
|
||||
|
||||
const ProposalDetails = ({ chainId, address, connect, config }) => {
|
||||
const { id } = useParams();
|
||||
const proposalId = BigInt(id);
|
||||
@ -89,7 +89,6 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
|
||||
|
||||
const theme = useTheme();
|
||||
const queryClient = useQueryClient();
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
|
||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||
const { balance } = useBalance(chainId, "GHST", address);
|
||||
@ -150,19 +149,20 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
|
||||
return url;
|
||||
}, [proposalProposer, config]);
|
||||
|
||||
const handleVote = useCallback(async (support) => {
|
||||
const handleVote = async (support) => {
|
||||
setIsPending(true);
|
||||
const result = await castVote(chainId, address, proposalId, support);
|
||||
|
||||
if (result) {
|
||||
const storedVotedProposals = getStorageValue(chainId, address, VOTED_PROPOSALS_PREFIX, []);
|
||||
const storedVotedProposals = localStorage.getItem(`${VOTED_PROPOSALS_PREFIX}-${chainId}-${address}`);
|
||||
const proposals = JSON.parse(storedVotedProposals || "[]").map(id => BigInt(id));
|
||||
proposals.push(proposalId);
|
||||
setStorageValue(chainId, address, VOTED_PROPOSALS_PREFIX, proposals.map(id => id.toString()));
|
||||
const toStore = JSON.stringify(proposals.map(id => id.toString()));
|
||||
localStorage.setItem(`${VOTED_PROPOSALS_PREFIX}-${chainId}-${address}`, toStore);
|
||||
await queryClient.invalidateQueries();
|
||||
}
|
||||
setIsPending(false);
|
||||
}, [chainId, address, proposalId]);
|
||||
}
|
||||
|
||||
const handleExecute = async () => {
|
||||
setIsPending(true);
|
||||
|
||||
@ -42,7 +42,6 @@ import {
|
||||
import { useScreenSize } from "../../../hooks/useScreenSize";
|
||||
|
||||
import { useProposals } from "../../../hooks/governance";
|
||||
import { useLocalStorage } from "../../../hooks/localstorage";
|
||||
|
||||
const MAX_PROPOSALS_TO_SHOW = 10;
|
||||
|
||||
@ -52,15 +51,18 @@ const ProposalsList = ({ chainId, address, config }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const { network } = useParams();
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
|
||||
const [proposalsFilter, setProposalFilter] = useState("active");
|
||||
|
||||
const myStoredProposals = getStorageValue(chainId, address, MY_PROPOSALS_PREFIX, []);
|
||||
const [myProposals, setMyProposals] = useState(() => myStoredProposals.map(id => BigInt(id)));
|
||||
const myStoredProposals = localStorage.getItem(`${MY_PROPOSALS_PREFIX}-${chainId}-${address}`);
|
||||
const [myProposals, setMyProposals] = useState(
|
||||
myStoredProposals ? JSON.parse(myStoredProposals).map(id => BigInt(id)) : []
|
||||
);
|
||||
|
||||
const storedVotedProposals = getStorageValue(chainId, address, VOTED_PROPOSALS_PREFIX, []);
|
||||
const [votedProposals, setVotedProposals] = useState(() => storedVotedProposals.map(id => BigInt(id)));
|
||||
const storedVotedProposals = localStorage.getItem(`${VOTED_PROPOSALS_PREFIX}-${chainId}-${address}`);
|
||||
const [votedProposals, setVotedProposals] = useState(
|
||||
storedVotedProposals ? JSON.parse(storedVotedProposals).map(id => BigInt(id)) : []
|
||||
);
|
||||
|
||||
const searchedIndexes = useMemo(() => {
|
||||
switch (proposalsFilter) {
|
||||
|
||||
@ -24,11 +24,10 @@ import { PrimaryButton, SecondaryButton } from "../../../components/Button";
|
||||
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
||||
import { prettifySecondsInDays } from "../../../helpers/timeUtil";
|
||||
import { formatNumber, formatCurrency } from "../../../helpers";
|
||||
import { formatNumber } from "../../../helpers";
|
||||
import { STAKING_ADDRESSES } from "../../../constants/addresses";
|
||||
import { useCurrentIndex, useWarmupInfo } from "../../../hooks/staking";
|
||||
import { useBalanceForShares, useTokenSymbol } from "../../../hooks/tokens";
|
||||
import { useGhstPrice } from "../../../hooks/prices";
|
||||
|
||||
import ClaimConfirmationModal from "./ClaimConfirmationModal";
|
||||
|
||||
@ -54,7 +53,6 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
||||
const [confirmationModalOpen, setConfirmationModalOpen] = useState(false);
|
||||
const [isPayoutGhst, _] = useState(true);
|
||||
|
||||
const ghstPrice = useGhstPrice(chainId);
|
||||
const { warmupInfo: claim, refetch: claimRefetch } = useWarmupInfo(chainId, address);
|
||||
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
|
||||
const { balanceForShares } = useBalanceForShares(chainId, "STNK", claim.shares);
|
||||
@ -134,7 +132,6 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
||||
isClaimable={claim.expiry > epoch.number}
|
||||
stnkSymbol={stnkSymbol}
|
||||
ghstSymbol={ghstSymbol}
|
||||
ghstPrice={ghstPrice}
|
||||
/>
|
||||
</Table>
|
||||
|
||||
@ -144,17 +141,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const ClaimInfo = ({
|
||||
setConfirmationModalOpen,
|
||||
prepareBalance,
|
||||
claim,
|
||||
epoch,
|
||||
isClaimable,
|
||||
isPayoutGhst,
|
||||
stnkSymbol,
|
||||
ghstSymbol,
|
||||
ghstPrice
|
||||
}) => {
|
||||
const ClaimInfo = ({ setConfirmationModalOpen, prepareBalance, claim, epoch, isClaimable, isPayoutGhst, stnkSymbol, ghstSymbol }) => {
|
||||
return (
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
@ -168,10 +155,7 @@ const ClaimInfo = ({
|
||||
</TableCell>
|
||||
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
||||
<Typography gutterBottom={false} style={{ lineHeight: 1.4 }}>
|
||||
{formatCurrency(prepareBalance, 5, isPayoutGhst ? ghstSymbol : stnkSymbol)}
|
||||
</Typography>
|
||||
<Typography variant="body2" gutterBottom={false} style={{ lineHeight: 1.4 }}>
|
||||
{formatCurrency(prepareBalance * ghstPrice, 2)}
|
||||
{`${formatNumber(prepareBalance, 5)} ${isPayoutGhst ? ghstSymbol : stnkSymbol}`}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell style={{ padding: "8px 8px 8px 0" }}>
|
||||
|
||||
@ -17,6 +17,7 @@ import TokenStack from "../../../components/TokenStack/TokenStack";
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
||||
import { formatCurrency } from "../../../helpers";
|
||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||
import { isNetworkLegacy } from "../../../constants";
|
||||
|
||||
import { useLpValuation } from "../../../hooks/treasury";
|
||||
import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens";
|
||||
@ -35,7 +36,7 @@ const FarmPools = ({ chainId }) => {
|
||||
|
||||
const pools = [
|
||||
{
|
||||
icons: ["FTSO", tokenNameConverter(chainId, reserveSymbol)],
|
||||
icons: ["FTSO", isNetworkLegacy(chainId) ? "GDAI" : tokenNameConverter(chainId, reserveSymbol)],
|
||||
name: `${ftsoSymbol}-${reserveSymbol}`,
|
||||
dex: "Uniswap V2",
|
||||
url: `/${network}/dex/uniswap`,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Avatar, Box, Link } from "@mui/material";
|
||||
import { styled } from "@mui/material/styles";
|
||||
|
||||
import React, { useEffect, useState, useCallback } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
||||
@ -23,7 +23,6 @@ import {
|
||||
STAKING_ADDRESSES,
|
||||
} from "../../../constants/addresses";
|
||||
import { useCurrentIndex } from "../../../hooks/staking";
|
||||
import { useLocalStorage } from "../../../hooks/localstorage";
|
||||
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||
import { formatNumber } from "../../../helpers";
|
||||
|
||||
@ -83,11 +82,20 @@ export const StakeInputArea = ({
|
||||
const [bottomTokenModalOpen, setBottomTokenModalOpen] = useState(false);
|
||||
const [confirmationModalOpen, setConfirmationModalOpen] = useState(false);
|
||||
|
||||
const { getStorageValue, setStorageValue } = useLocalStorage();
|
||||
const [formatDecimals, setFormatDecimals] = useState(localStorage.getItem("stake-decimals")
|
||||
? localStorage.getItem("stake-decimals")
|
||||
: "5"
|
||||
);
|
||||
|
||||
const [formatDecimals, setFormatDecimals] = useState(() => getStorageValue(chainId, address, "stake-decimals", "5"));
|
||||
const [isClaim, setIsClaim] = useState(() => getStorageValue(chainId, address, "stake-isClaim", true));
|
||||
const [isTrigger, setIsTrigger] = useState(() => getStorageValue(chainId, address, "stake-isTrigger", true));
|
||||
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("");
|
||||
@ -102,22 +110,23 @@ export const StakeInputArea = ({
|
||||
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
||||
|
||||
const setIsClaimInner = useCallback((value) => {
|
||||
const setIsClaimInner = (value) => {
|
||||
setIsClaim(value);
|
||||
setStorageValue(chainId, address, "stake-isClaim", value);
|
||||
}, [chainId, address]);
|
||||
localStorage.setItem("stake-isClaim", value);
|
||||
|
||||
const setIsTriggerInner = useCallback((value) => {
|
||||
}
|
||||
|
||||
const setIsTriggerInner = (value) => {
|
||||
setIsTrigger(value);
|
||||
setStorageValue(chainId, address, "stake-isTrigger", value);
|
||||
}, [chainId, address]);
|
||||
localStorage.setItem("stake-isTrigger", value);
|
||||
}
|
||||
|
||||
const setFormatDecimalsInner = useCallback((value) => {
|
||||
const setFormatDecimalsInner = (value) => {
|
||||
if (Number(value) <= 17) {
|
||||
setFormatDecimals(value);
|
||||
setStorageValue(chainId, address, "stake-decimals", value);
|
||||
localStorage.setItem("staking-decimals", value);
|
||||
}
|
||||
}, [chainId, address]);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const innerBalance = upperToken === ghstSymbol ?
|
||||
@ -233,6 +242,36 @@ export const StakeInputArea = ({
|
||||
/>
|
||||
</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
|
||||
|
||||
@ -6,6 +6,7 @@ import Token from "../../../components/Token/Token";
|
||||
import { SecondaryButton } from "../../../components/Button";
|
||||
import { formatNumber, formatCurrency } from "../../../helpers";
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
||||
import { isNetworkLegacy } from "../../../constants"
|
||||
|
||||
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||
import {
|
||||
@ -128,15 +129,17 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
||||
price={ghstPrice}
|
||||
description={`${ghstSymbol} is the governance token enabling pure Web3 cross-chain magic. 1 ${ghstSymbol} = 1 ${ftsoSymbol} x Current Index.`}
|
||||
/>
|
||||
<TokenTab
|
||||
isMobileScreen={isMobileScreen}
|
||||
tokenUrl={"https://ghostchain.io/faucet/"}
|
||||
theme={theme}
|
||||
tokenName={nativeSymbol}
|
||||
balance={new DecimalBigNumber(nativeBalance?.value ?? 0n, 18)}
|
||||
price={reservePrice}
|
||||
description={`${nativeSymbol} is the native currency of the ${networkName} Network, functioning as the backing asset for the ghostDAO.`}
|
||||
/>
|
||||
{!isNetworkLegacy(chainId) && (
|
||||
<TokenTab
|
||||
isMobileScreen={isMobileScreen}
|
||||
tokenUrl={"https://ghostchain.io/faucet/"}
|
||||
theme={theme}
|
||||
tokenName={nativeSymbol}
|
||||
balance={new DecimalBigNumber(nativeBalance?.value ?? 0n, 18)}
|
||||
price={reservePrice}
|
||||
description={`${nativeSymbol} is the native currency of the ${networkName} Network, functioning as the backing asset for the ghostDAO.`}
|
||||
/>
|
||||
)}
|
||||
<TokenTab
|
||||
isMobileScreen={isMobileScreen}
|
||||
tokenUrl={`/${network}/dex/uniswap`}
|
||||
@ -148,7 +151,10 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
||||
tokenName={reserveSymbol}
|
||||
balance={reserveBalance}
|
||||
price={reservePrice}
|
||||
description={`${ftsoSymbol} is backed by a treasury reserve of crypto assets, with ${reserveSymbol} being the primary and most liquid asset.`}
|
||||
description={isNetworkLegacy(chainId)
|
||||
? `${ftsoSymbol} is backed by a treasury reserve of crypto assets, with ${reserveSymbol} being the primary and most liquid asset.`
|
||||
: `${reserveSymbol} (Wrapped ${nativeSymbol}) is an ERC-20 token that represents ${nativeSymbol} and is pegged 1:1 to the value of ${nativeSymbol}.`
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
import { createContext, useContext, useState, useEffect } from "react";
|
||||
|
||||
const LocalStorageContext = createContext();
|
||||
export const useLocalStorage = () => useContext(LocalStorageContext);
|
||||
|
||||
export const LocalStorageProvider = ({ children }) => {
|
||||
const getStorageKey = (chainId, address, target) => {
|
||||
return `${chainId}:${address}:${target}`;
|
||||
}
|
||||
|
||||
const getStorageValue = (chainId, address, target, defaultValue) => {
|
||||
const key = getStorageKey(chainId, address, target);
|
||||
const stored = localStorage.getItem(key);
|
||||
return stored ? JSON.parse(stored) : defaultValue;
|
||||
}
|
||||
|
||||
const setStorageValue = (chainId, address, target, value) => {
|
||||
const key = getStorageKey(prefix, chainId, address, target);
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
|
||||
return (
|
||||
<LocalStorageContext.Provider value={{ getStorageValue, setStorageValue }}>
|
||||
{children}
|
||||
</LocalStorageContext.Provider>
|
||||
)
|
||||
}
|
||||
@ -9,7 +9,6 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { WagmiProvider } from "wagmi";
|
||||
import { config } from "./config";
|
||||
import { UnstableProviderProvider, MetadataProviderProvider } from "./hooks/ghost"
|
||||
import { LocalStorageProvider } from "./hooks/localstorage";
|
||||
import ReactGA from "react-ga4";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
@ -25,9 +24,7 @@ ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<StyledEngineProvider injectFirst>
|
||||
<UnstableProviderProvider>
|
||||
<MetadataProviderProvider>
|
||||
<LocalStorageProvider>
|
||||
<App />
|
||||
</LocalStorageProvider>
|
||||
<App />
|
||||
</MetadataProviderProvider>
|
||||
</UnstableProviderProvider>
|
||||
</StyledEngineProvider>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user