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