From e244299465bdf91bb3e6c17d993f92d5a63a5e89 Mon Sep 17 00:00:00 2001 From: Uncle Fatso Date: Sun, 12 Jul 2026 13:57:02 +0300 Subject: [PATCH] apply small changes for the app Signed-off-by: Uncle Fatso --- package.json | 2 +- src/App.jsx | 2 +- src/components/Modal/Modal.jsx | 14 ++-- src/components/Paper/Paper.jsx | 4 +- src/components/Swap/SwapCard.jsx | 21 +++++- src/components/Token/Token.jsx | 17 ++--- src/components/TokenStack/TokenStack.jsx | 16 +++-- .../TopBar/Wallet/InitialWalletView.tsx | 2 - src/components/TopBar/Wallet/Token.tsx | 13 +++- src/constants/dexes.js | 3 + src/containers/Bond/BondModal.jsx | 7 +- .../Bond/components/BondConfirmModal.jsx | 64 +++++++++++++++---- .../Bond/components/BondInputArea.jsx | 18 +++++- src/containers/Bond/components/BondList.jsx | 4 +- src/containers/Bond/components/ClaimBonds.jsx | 6 +- src/containers/Breakout/BreakoutModal.jsx | 24 ++++--- src/containers/Bridge/BridgeCard.jsx | 16 +++-- src/containers/Bridge/BridgeRoute.jsx | 18 +++++- src/containers/Dex/Dex.jsx | 12 +++- src/containers/Dex/PoolContainer.jsx | 7 +- src/containers/Dex/SwapContainer.jsx | 8 ++- src/containers/Dex/TokenModal.jsx | 22 ++++--- src/containers/Governance/ProposalDetails.jsx | 14 ++-- .../Governance/components/functions/index.jsx | 6 +- src/containers/Stake/Stake.jsx | 13 ++-- src/containers/Stake/StakeContainer.jsx | 15 +++-- .../components/ClaimConfirmationModal.jsx | 2 +- .../Stake/components/ClaimsArea.jsx | 25 ++++++-- src/containers/Stake/components/FarmPools.jsx | 11 ++-- src/containers/Stake/components/StakeArea.jsx | 2 + .../components/StakeConfirmationModal.jsx | 50 ++++++++++----- .../Stake/components/StakeInfoText.jsx | 2 +- .../Stake/components/StakeInputArea.jsx | 10 ++- .../components/ProtocolDetails.jsx | 4 +- src/hooks/bonds/index.js | 10 ++- src/hooks/helpers.js | 17 ++++- src/style.scss | 5 ++ 37 files changed, 342 insertions(+), 144 deletions(-) diff --git a/package.json b/package.json index 994f8f0..c6776a4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ghost-dao-interface", "private": true, - "version": "0.7.50", + "version": "0.7.51", "type": "module", "scripts": { "dev": "vite", diff --git a/src/App.jsx b/src/App.jsx index dca6759..bc78fc0 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -198,7 +198,7 @@ function App() { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/src/components/Modal/Modal.jsx b/src/components/Modal/Modal.jsx index 1a7069e..81e8c07 100644 --- a/src/components/Modal/Modal.jsx +++ b/src/components/Modal/Modal.jsx @@ -84,22 +84,20 @@ const Modal = ({ // getModalStyle is not a pure function, we roll the style only on the first render const [modalStyle] = useState(getModalStyle); const closeButton = ( - { if (props.onClose) { props.onClose(e, "escapeKeyDown"); } }} - > - - + /> ); //modal must have a close position. Close position and topLeft or topRight cant be used for the same position. - const topRightPos = closePosition === "right" ? closeButton : topRight; + const topRightPos = topRight ? topRight : closeButton; const topLeftPos = closePosition === "left" ? closeButton : topLeft; return ( @@ -113,7 +111,7 @@ const Modal = ({ {...props} minHeight={minHeight} maxWidth={maxWidth} - > + > - {topLeft &&
{topLeft}
} + {topLeft && {topLeft}} {headerText && !headerContent && ( @@ -83,7 +83,7 @@ const Paper = ({ )} {headerContent} -
{topRight}
+ {topRight}
{subHeader && {subHeader}} diff --git a/src/components/Swap/SwapCard.jsx b/src/components/Swap/SwapCard.jsx index 160549e..15ca9a6 100644 --- a/src/components/Swap/SwapCard.jsx +++ b/src/components/Swap/SwapCard.jsx @@ -44,6 +44,7 @@ const SwapCard = ({ tokenName, inputWidth, inputFontSize, + chainTokenName, maxWidth = "416px", ...props }) => { @@ -72,12 +73,26 @@ const SwapCard = ({ cursor: tokenOnClick ? "pointer" : "default", }} borderRadius="6px" - paddingX="9px" - paddingY="6.5px" + paddingX="7px" + paddingY="2px" alignItems="center" {...onClickProps} > - {typeof token === "string" ? : token} + {typeof token === "string" + ? + : token} {(typeof token === "string" || tokenName) && ( diff --git a/src/components/Token/Token.jsx b/src/components/Token/Token.jsx index 073bd67..d278eac 100644 --- a/src/components/Token/Token.jsx +++ b/src/components/Token/Token.jsx @@ -69,27 +69,28 @@ export const parseKnownToken = (name) => { return icon; } -const Token = ({ chainTokenName, name, viewBox = "0 0 260 260", fontSize = "large", ...props }) => { +const Token = ({ chainTokenName, name, isNative, parentSx, viewBox = "0 0 260 260", fontSize = "large", ...props }) => { return ( - + {chainTokenName && ( )} diff --git a/src/components/TokenStack/TokenStack.jsx b/src/components/TokenStack/TokenStack.jsx index 53b8c6d..f9d1361 100644 --- a/src/components/TokenStack/TokenStack.jsx +++ b/src/components/TokenStack/TokenStack.jsx @@ -1,11 +1,12 @@ import { Avatar, Box } from "@mui/material"; import Token from "../Token/Token"; -const TokenStack = ({ tokens, style, images, network, ...props }) => { +const TokenStack = ({ chainTokenNames, tokens, style, images, network, ...props }) => { const imageStyles = { height: "27px", width: "27px", ...style, + }; return ( @@ -20,18 +21,25 @@ const TokenStack = ({ tokens, style, images, network, ...props }) => { ))} {tokens?.map((token, i) => ( ))} diff --git a/src/components/TopBar/Wallet/InitialWalletView.tsx b/src/components/TopBar/Wallet/InitialWalletView.tsx index 761deee..1a229e0 100644 --- a/src/components/TopBar/Wallet/InitialWalletView.tsx +++ b/src/components/TopBar/Wallet/InitialWalletView.tsx @@ -132,7 +132,6 @@ function InitialWalletView({ isWalletOpen, address, chainId, onClose }) { useEffect(() => { if (isWalletOpen) { - console.log(`/${chainName.toLowerCase()}/sidebar`) ReactGA.send({ hitType: "pageview", page: `/${chainName.toLowerCase()}/sidebar` }); } }, [isWalletOpen, chainName]) @@ -143,7 +142,6 @@ function InitialWalletView({ isWalletOpen, address, chainId, onClose }) { } }, [isWalletOpen, tokens]) - return ( diff --git a/src/components/TopBar/Wallet/Token.tsx b/src/components/TopBar/Wallet/Token.tsx index ccc85d9..dfcb609 100644 --- a/src/components/TopBar/Wallet/Token.tsx +++ b/src/components/TopBar/Wallet/Token.tsx @@ -130,6 +130,7 @@ export const Token = (props) => { height: "28px", }} tokens={props.icons} + chainTokenNames={props.chainTokenNames} /> {symbol} @@ -207,8 +208,8 @@ export const useWallet = (chainId, userAddress) => { const nativeSymbol = useMemo(() => { return config?.getClient()?.chain?.nativeCurrency?.symbol; - }, [config]); - + }, [chainId, config]); + const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE"); const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO"); const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST"); @@ -223,7 +224,7 @@ export const useWallet = (chainId, userAddress) => { if (token0?.at(0) === reserveSymbol) { tokenAddresses = [lpReserveFtsoTokens?.token0, lpReserveFtsoTokens?.token1]; - let tokenNames = [...token0, ...token1]; + tokenNames = [...token0, ...token1]; } return { tokenAddresses, tokenNames } @@ -251,6 +252,7 @@ export const useWallet = (chainId, userAddress) => { address: ftsoAddress, balance: ftsoBalance, price: ftsoPrice, + chainTokenNames: [nativeSymbol], icons: ["FTSO"], externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/eGHST.svg", refetch: ftsoRefetch, @@ -261,6 +263,7 @@ export const useWallet = (chainId, userAddress) => { balance: ghstBalance, price: ghstPrice, icons: ["GHST"], + chainTokenNames: [nativeSymbol], externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/GHST.svg", refetch: ghstRefetch, }, @@ -271,6 +274,10 @@ export const useWallet = (chainId, userAddress) => { balance: lpReserveFtsoBalance, price: lpReserveFtsoPrice, icons: lpReserveFtsoTokenNames?.tokenNames, + chainTokenNames: [ + lpReserveFtsoTokenNames?.tokenNames?.at(0) !== reserveSymbol && nativeSymbol, + lpReserveFtsoTokenNames?.tokenNames?.at(1) !== reserveSymbol && nativeSymbol, + ], externalUrl: "https://ghostchain.io/wp-content/uploads/2025/03/uni-v2.svg", refetch: lpReserveFtsoRefetch, } diff --git a/src/constants/dexes.js b/src/constants/dexes.js index bd988fd..c9b80f0 100644 --- a/src/constants/dexes.js +++ b/src/constants/dexes.js @@ -9,6 +9,7 @@ export const AVAILABLE_DEXES = { name: "Uniswap", icon: UniswapIcon, viewBox: "0 0 195 230", + isFork: true, }, ], [NetworkId.TESTNET_HOODI]: [ @@ -16,6 +17,7 @@ export const AVAILABLE_DEXES = { name: "Uniswap", icon: UniswapIcon, viewBox: "0 0 195 230", + isFork: true, }, ], [NetworkId.TESTNET_MORDOR]: [ @@ -23,6 +25,7 @@ export const AVAILABLE_DEXES = { name: "Uniswap", icon: UniswapIcon, viewBox: "0 0 195 230", + isFork: true, }, ], }; diff --git a/src/containers/Bond/BondModal.jsx b/src/containers/Bond/BondModal.jsx index 244b79d..1409d08 100644 --- a/src/containers/Bond/BondModal.jsx +++ b/src/containers/Bond/BondModal.jsx @@ -91,6 +91,7 @@ export const BondModal = ({ bond, chainId, address, config, connect }) => { if (isNetworkLegacy(chainId)) { return { address: bond.quoteToken.quoteTokenAddress, + chainNames: bond.quoteToken.chainNames, icons: bond.quoteToken.icons, name: bond.quoteToken.name, } @@ -112,7 +113,11 @@ export const BondModal = ({ bond, chainId, address, config, connect }) => { - + {preparedQuoteToken.name} diff --git a/src/containers/Bond/components/BondConfirmModal.jsx b/src/containers/Bond/components/BondConfirmModal.jsx index 8e3901f..893dd73 100644 --- a/src/containers/Bond/components/BondConfirmModal.jsx +++ b/src/containers/Bond/components/BondConfirmModal.jsx @@ -42,6 +42,7 @@ const BondConfirmModal = ({ isNative, bondQuoteTokenName, bondQuoteTokenIcons, + bondQuoteTokenChainNames, handleConfirmClose }) => { const theme = useTheme(); @@ -127,16 +128,16 @@ const BondConfirmModal = ({ maxWidth="476px" minHeight="200px" open={isOpen} - headerContent={ - - - - {bondQuoteTokenName} - - - } + headerContent={{bondQuoteTokenName} Bond} onClose={!isPending && handleConfirmCloseMaster} - topLeft={} + topRight={ + + } > <> @@ -145,19 +146,58 @@ const BondConfirmModal = ({ label="Assets to Bond" metric={spendAmount} /> - + + {bondQuoteTokenName} - + + {bond.baseToken.name} - + } /> } /> } /> diff --git a/src/containers/Bond/components/BondInputArea.jsx b/src/containers/Bond/components/BondInputArea.jsx index 386f883..eccc359 100644 --- a/src/containers/Bond/components/BondInputArea.jsx +++ b/src/containers/Bond/components/BondInputArea.jsx @@ -100,12 +100,19 @@ const BondInputArea = ({ } + token={ + + } tokenName={preparedQuoteToken.name} info={formatCurrency(balance, formatDecimals, preparedQuoteToken.name)} endString="Max" @@ -119,7 +126,13 @@ const BondInputArea = ({ maxWidth="476px" inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"} id="to" - token={} + token={ + + } tokenName={bond.baseToken.name} value={amountInBaseToken.toString({ decimals: 9 })} inputProps={{ "data-testid": "toInput" }} @@ -229,6 +242,7 @@ const BondInputArea = ({ receiveAmount={formatNumber(amountInBaseToken, formatDecimals)} bondQuoteTokenName={preparedQuoteToken.name} bondQuoteTokenIcons={preparedQuoteToken.icons} + bondQuoteTokenChainNames={preparedQuoteToken.chainNames} isNative={preparedQuoteToken.address === undefined} handleSettingsOpen={handleSettingsOpen} isOpen={confirmOpen} diff --git a/src/containers/Bond/components/BondList.jsx b/src/containers/Bond/components/BondList.jsx index eee1dfb..d388869 100644 --- a/src/containers/Bond/components/BondList.jsx +++ b/src/containers/Bond/components/BondList.jsx @@ -72,7 +72,7 @@ const BondCard = ({ bond, secondsTo, chainName }) => { return ( - + {bond.quoteToken.name} @@ -237,7 +237,7 @@ const BondRow = ({ bond, secondsTo, chainName }) => { const TokenIcons = ({ token, chainId, explorer }) => ( - + {token.name} diff --git a/src/containers/Bond/components/ClaimBonds.jsx b/src/containers/Bond/components/ClaimBonds.jsx index 89ac294..49321c6 100644 --- a/src/containers/Bond/components/ClaimBonds.jsx +++ b/src/containers/Bond/components/ClaimBonds.jsx @@ -103,7 +103,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => { headerContent={ - Your Bonds + My Bonds } @@ -143,7 +143,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => { {notes.map((note, index) => ( - + {note.quoteToken.name} @@ -205,7 +205,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => { - + {note.quoteToken.name} diff --git a/src/containers/Breakout/BreakoutModal.jsx b/src/containers/Breakout/BreakoutModal.jsx index e714a4f..490a359 100644 --- a/src/containers/Breakout/BreakoutModal.jsx +++ b/src/containers/Breakout/BreakoutModal.jsx @@ -5,7 +5,8 @@ import { getBlockNumber } from "@wagmi/core"; import { useConfig } from "wagmi"; import { ss58Decode } from "@polkadot-labs/hdkd-helpers"; import { toHex } from "@polkadot-api/utils"; -import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import CheckIcon from '@mui/icons-material/CheckCircle'; +import CancelIcon from '@mui/icons-material/Cancel'; import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import { CheckBoxOutlineBlank, CheckBoxOutlined } from "@mui/icons-material"; @@ -165,6 +166,7 @@ const BridgeView = ({ incomingFee }) => { const theme = useTheme(); + const [inputFocused, setInputFocused] = useState(false); const config = useConfig(); const { gatekeeperAddress } = useGatekeeperAddress(chainId); @@ -189,13 +191,17 @@ const BridgeView = ({ setReceiver(convertedReceiver ? "" : event.currentTarget.value)} + onBlur={() => setInputFocused(true)} + onFocus={() => setInputFocused(false)} + onChange={event => setReceiver(event.currentTarget.value)} + placeholder={convertedReceiver ? shorten(receiver, 15, -10) : "GHOST address (sf prefixed)"} + value={convertedReceiver ? "" : receiver} inputProps={{ "data-testid": "fromInput" }} - placeholder="GHOST address (sf prefixed)" endString={convertedReceiver - ? - : undefined + ? + : inputFocused && receiver !== "" + ? + : undefined } type="text" maxWidth="100%" @@ -274,7 +280,7 @@ const WelcomeView = ({ <> {warmupPeriod <= 0 ? `You have succesfully warmed-up your ${isStakingOpened ? " " : "bonded "}${ftsoSymbol} ${isStakingOpened ? "(3, 3)" : "(1, 1)"} Staked at:` - : `${isStakingOpened ? "Stake" : "Bond"} is in warm-up${isStakingOpened ? "" : ", which extends with each purchase"}. Your ${ftsoSymbol} ${isStakingOpened ? "(3, 3)" : "(1, 1)"} is Staked at:` + : `${isStakingOpened ? "Stake" : "Bond"} is in warm-up${isStakingOpened ? "" : ", which extends with each purchase"}. Your ${ftsoSymbol} (3, 3) Staked at:` } @@ -421,7 +427,7 @@ const ConfirmStep = ({ - + {ghstSymbol} @@ -493,7 +499,7 @@ const ConfirmStep = ({ disabled={isPending || !acknowledgeWalletCustody || !acknowledgeBridgingRisk} fullWidth > - {isPending ? "Confirming..." : "I Confirm"} + {isPending ? "Confirming..." : "Confirm"} ) diff --git a/src/containers/Bridge/BridgeCard.jsx b/src/containers/Bridge/BridgeCard.jsx index 1f9bf74..9ce9369 100644 --- a/src/containers/Bridge/BridgeCard.jsx +++ b/src/containers/Bridge/BridgeCard.jsx @@ -28,7 +28,8 @@ import SwapCollection from "../../components/Swap/SwapCollection"; import { ghost } from "../../hooks/staking"; import { useBalance } from "../../hooks/tokens"; -import CheckIcon from '@mui/icons-material/Check'; +import CheckIcon from '@mui/icons-material/CheckCircle'; +import CancelIcon from '@mui/icons-material/Cancel'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; @@ -58,6 +59,7 @@ export const BridgeCardAction = ({ storeTransactionHash, }) => { const [isPending, setIsPending] = useState(false); + const [inputFocused, setInputFocused] = useState(false); const [receiver, setReceiver] = useState(""); const [convertedReceiver, setConvertedReceiver] = useState(undefined); const [amount, setAmount] = useState(""); @@ -166,13 +168,17 @@ export const BridgeCardAction = ({ UpperSwapCard={ setReceiver(convertedReceiver ? "" : event.currentTarget.value)} + value={convertedReceiver ? "" : receiver} + onBlur={() => setInputFocused(true)} + onFocus={() => setInputFocused(false)} + onChange={event => setReceiver(event.currentTarget.value)} inputProps={{ "data-testid": "fromInput" }} - placeholder="GHOST address (sf prefixed)" + placeholder={convertedReceiver ? sliceString(receiver, 15, -10) : "GHOST address (sf prefixed)"} endString={convertedReceiver ? - : undefined + : inputFocused && receiver !== "" + ? + : undefined } type="text" maxWidth="100%" diff --git a/src/containers/Bridge/BridgeRoute.jsx b/src/containers/Bridge/BridgeRoute.jsx index 8cc7fd8..ee59747 100644 --- a/src/containers/Bridge/BridgeRoute.jsx +++ b/src/containers/Bridge/BridgeRoute.jsx @@ -33,11 +33,23 @@ const RouteHop = ({ theme, token, chainTokenName, arrowNeeded }) => { sx={{ backgroundColor: theme.colors.gray[600] }} borderRadius="6px" paddingX="9px" - paddingY="6.5px" + paddingY="2px" alignItems="center" > - - + + {token} diff --git a/src/containers/Dex/Dex.jsx b/src/containers/Dex/Dex.jsx index 773b220..8056e26 100644 --- a/src/containers/Dex/Dex.jsx +++ b/src/containers/Dex/Dex.jsx @@ -32,6 +32,7 @@ import { EMPTY_ADDRESS, WETH_ADDRESSES, } from "../../constants/addresses"; +import { AVAILABLE_DEXES } from "../../constants/dexes"; import { useLocalStorage } from "../../hooks/localstorage"; import { useTokenSymbol } from "../../hooks/tokens"; import { getTokenAddress } from "../../hooks/helpers"; @@ -184,6 +185,13 @@ const Dex = ({ chainId, address, connect, config }) => { setSearchParams(newQueryParameters); } + const isDexFork = useMemo(() => { + const dexInfo = AVAILABLE_DEXES[chainId]?.find(elem => + elem.name.toLowerCase() == pathname.name.toLowerCase() + ) + return dexInfo ? dexInfo.isFork : false; + }, [chainId, pathname]) + const setSlippageInner = useCallback((value) => { const maybeValue = parseFloat(value); if (!maybeValue || parseFloat(value) <= 100) { @@ -242,7 +250,7 @@ const Dex = ({ chainId, address, connect, config }) => { { {isSwap ? { /> : } + token={tokenNameTop} + chainTokenName={tokenNameTop !== chainSymbol && chainSymbol} tokenName={tokenNameTop} info={(!isSmallScreen ? "Balance: " : "") + formatCurrency(balanceTop, formatDecimals, tokenNameTop)} endString="Max" @@ -233,7 +235,8 @@ const PoolContainer = ({ LowerSwapCard={ } + token={tokenNameBottom} + chainTokenName={tokenNameBottom !== chainSymbol && chainSymbol} tokenName={tokenNameBottom} value={amountBottom} onChange={event => emptyPool ? setAmountBottom(event.currentTarget.value) : {}} diff --git a/src/containers/Dex/SwapContainer.jsx b/src/containers/Dex/SwapContainer.jsx index 9f89b8b..856ded1 100644 --- a/src/containers/Dex/SwapContainer.jsx +++ b/src/containers/Dex/SwapContainer.jsx @@ -25,6 +25,7 @@ import { import { EMPTY_ADDRESS } from "../../constants/addresses"; const SwapContainer = ({ + chainSymbol, tokenNameTop, tokenNameBottom, address, @@ -212,7 +213,8 @@ const SwapContainer = ({ } + token={tokenNameTop} + chainTokenName={tokenNameTop !== chainSymbol && chainSymbol} tokenName={tokenNameTop} info={ (!isSmallScreen ? "Balance: " : "") + @@ -230,8 +232,8 @@ const SwapContainer = ({ } - tokenName={tokenNameBottom} + token={tokenNameBottom} + chainTokenName={tokenNameBottom !== chainSymbol && chainSymbol} value={amountBottom} inputProps={{ "data-testid": "toInput" }} tokenOnClick={() => setBottomTokenListOpen(true)} diff --git a/src/containers/Dex/TokenModal.jsx b/src/containers/Dex/TokenModal.jsx index ce452fc..f2317ed 100644 --- a/src/containers/Dex/TokenModal.jsx +++ b/src/containers/Dex/TokenModal.jsx @@ -15,7 +15,7 @@ import { isAddress, getAddress } from "@ethersproject/address"; import Modal from "../../components/Modal/Modal"; import SwapCard from "../../components/Swap/SwapCard"; -import TokenStack from "../../components/TokenStack/TokenStack"; +import Token from "../../components/Token/Token"; import { DecimalBigNumber } from "../../helpers/DecimalBigNumber"; import { formatNumber } from "../../helpers/"; @@ -65,26 +65,24 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT return [ { name: chainSymbol, - icons: [chainSymbol], balance: nativeBalance, address: EMPTY_ADDRESS, }, { name: reserveSymbol, - icons: [chainSymbol], balance: reserveBalance, address: RESERVE_ADDRESSES[chainId] }, { name: ftsoSymbol, - icons: ["FTSO"], balance: ftsoBalance, + chainTokenName: chainSymbol, address: FTSO_ADDRESSES[chainId] }, { name: ghstSymbol, - icons: ["GHST"], balance: ghstBalance, + chainTokenName: chainSymbol, address: GHST_ADDRESSES[chainId] } ] @@ -105,7 +103,7 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT maxWidth="476px" minHeight="200px" open={listOpen} - headerText={"Select a token"} + headerText={"Select a Token"} onClose={() => setListOpen(false)} > setUsedAddress(token)} hover key={index} id={index + `--token`} data-testid={index + `--token`}> - + - + {token.name} diff --git a/src/containers/Governance/ProposalDetails.jsx b/src/containers/Governance/ProposalDetails.jsx index e18d30c..f563473 100644 --- a/src/containers/Governance/ProposalDetails.jsx +++ b/src/containers/Governance/ProposalDetails.jsx @@ -110,8 +110,6 @@ const ProposalDetails = ({ chainId, address, connect, config }) => { const { pastTotalSupply: totalSupply } = usePastTotalSupply(chainId, "GHST", proposalSnapshot); const { pastVotes } = usePastVotes(chainId, "GHST", proposalSnapshot, address); - console.log(location.pathname) - useEffect(() => { ReactGA.send({ hitType: "pageview", page: `${chainId}/governance/${id}` }); }, []); @@ -239,10 +237,10 @@ const ProposalDetails = ({ chainId, address, connect, config }) => { - For: {formatNumber(forVotes.toString(), 2)} ({formatNumber(forPercentage?.toString(), 1)}%) + For: {formatNumber(forVotes.toString(), 2)} ({formatNumber(forPercentage?.toString(), 2)}%) - Against: {formatNumber(againstVotes.toString(), 2)} ({formatNumber(againstPercentage?.toString(), 1)}%) + Against: {formatNumber(againstVotes.toString(), 2)} ({formatNumber(againstPercentage?.toString(), 2)}%) { Locked - {formatCurrency(proposalLocked, 4, ghstSymbol)} + {formatCurrency(proposalLocked, 5, ghstSymbol)}
@@ -273,7 +271,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => { Quorum
- {formatNumber(proposalQuorum.toString(), 4)} ({formatNumber(quorumPercentage, 1)}%) + {formatNumber(proposalQuorum.toString(), 5)} ({formatNumber(quorumPercentage, 2)}%)
@@ -281,7 +279,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => { Total - {formatNumber(totalSupply.toString(), 4)} ({formatNumber(votePercentage, 1)}%) + {formatNumber(totalSupply.toString(), 5)} ({formatNumber(votePercentage, 2)}%)
@@ -289,7 +287,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => { Votes - {formatNumber(pastVotes.toString(), 4)} ({formatNumber(voteWeightPercentage, 1)}%) + {formatNumber(pastVotes.toString(), 5)} ({formatNumber(voteWeightPercentage, 2)}%)
diff --git a/src/containers/Governance/components/functions/index.jsx b/src/containers/Governance/components/functions/index.jsx index 5544d7b..83dc6d4 100644 --- a/src/containers/Governance/components/functions/index.jsx +++ b/src/containers/Governance/components/functions/index.jsx @@ -81,7 +81,7 @@ export const parseFunctionCalldata = ({ case allPossibleFunctions[1].value: return ; case allPossibleFunctions[2].value: - return ; + return ; case allPossibleFunctions[3].value: return ; case allPossibleFunctions[4].value: @@ -288,7 +288,7 @@ export const ParsedCell = (props) => { - {formatCurrency(props.value, 4, props.nativeCoin)} + {formatCurrency(props.value, 5, props.nativeCoin)} @@ -330,7 +330,7 @@ export const ParsedCell = (props) => { Value - {formatCurrency(props.value, 4, props.nativeCoin)} + {formatCurrency(props.value, 5, props.nativeCoin)} diff --git a/src/containers/Stake/Stake.jsx b/src/containers/Stake/Stake.jsx index 9162a51..d5ea9dd 100644 --- a/src/containers/Stake/Stake.jsx +++ b/src/containers/Stake/Stake.jsx @@ -14,7 +14,7 @@ import Paper from "../../components/Paper/Paper"; import TokenStack from "../../components/TokenStack/TokenStack"; import { useTokenSymbol } from "../../hooks/tokens"; -const Stake = ({ chainId, address, isOpened, closeModal, connect }) => { +const Stake = ({ chainId, chainSymbol, address, isOpened, closeModal, connect }) => { const [action, setAction] = useState("STAKE"); const [settingsModalOpen, setSettingsModalOpen] = useState(false); @@ -31,13 +31,13 @@ const Stake = ({ chainId, address, isOpened, closeModal, connect }) => { useEffect(() => { switch (true) { case (upperToken === ftsoSymbol && bottomToken === ghstSymbol): - setAction("STAKE") + setAction("Stake") break; case (upperToken === ghstSymbol && bottomToken === ftsoSymbol): - setAction("UNSTAKE") + setAction("Unstake") break; default: - setAction("STAKE") + setAction("Stake") } }, [ftsoSymbol, ghstSymbol, upperToken, bottomToken]) @@ -46,10 +46,10 @@ const Stake = ({ chainId, address, isOpened, closeModal, connect }) => { headerContent={ {action} - + } - topLeft={ + topRight={ { > setSettingsModalOpenInner(false)} upperToken={upperToken} diff --git a/src/containers/Stake/StakeContainer.jsx b/src/containers/Stake/StakeContainer.jsx index ae803e4..00802dc 100644 --- a/src/containers/Stake/StakeContainer.jsx +++ b/src/containers/Stake/StakeContainer.jsx @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction, useState, useEffect } from "react"; +import { Dispatch, SetStateAction, useState, useEffect, useMemo } from "react"; import { Box, Container, Grid, Divider, Typography, useMediaQuery, useTheme } from "@mui/material"; import { useLocation } from "react-router-dom"; import ReactGA from "react-ga4"; @@ -19,7 +19,7 @@ import { Apy, CurrentIndex, TotalDeposit } from "./components/Metric"; import { useEpoch } from "../../hooks/staking"; import { useTokenSymbol } from "../../hooks/tokens"; -export const StakeContainer = ({ chainId, address, connect }) => { +export const StakeContainer = ({ chainId, address, config, connect }) => { const location = useLocation(); const [isModalOpened, handleModal] = useState(false); @@ -32,6 +32,12 @@ export const StakeContainer = ({ chainId, address, connect }) => { const { epoch, refetch: refetchEpoch } = useEpoch(chainId); + const chainSymbol = useMemo(() => { + const chainSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol; + if (chainSymbol) return chainSymbol; + return "WTF"; + }, [config, chainId]) + useEffect(() => { ReactGA.send({ hitType: "pageview", page: location.pathname }); }, [location]) @@ -39,6 +45,7 @@ export const StakeContainer = ({ chainId, address, connect }) => { if (isModalOpened) { return ( { - + @@ -104,7 +111,7 @@ export const StakeContainer = ({ chainId, address, connect }) => {
- + diff --git a/src/containers/Stake/components/ClaimConfirmationModal.jsx b/src/containers/Stake/components/ClaimConfirmationModal.jsx index 4a57c06..c4e08d3 100644 --- a/src/containers/Stake/components/ClaimConfirmationModal.jsx +++ b/src/containers/Stake/components/ClaimConfirmationModal.jsx @@ -42,7 +42,7 @@ const ClaimConfirmationModal = (props) => { maxWidth="356px" topLeft={<>} headerContent={ - + {`Confirm ${capitalize(props.action)}`} } diff --git a/src/containers/Stake/components/ClaimsArea.jsx b/src/containers/Stake/components/ClaimsArea.jsx index 702dc3d..ff2441a 100644 --- a/src/containers/Stake/components/ClaimsArea.jsx +++ b/src/containers/Stake/components/ClaimsArea.jsx @@ -50,7 +50,7 @@ const StyledTableHeader = styled(TableHead)(({ theme }) => ({ }, })); -export const ClaimsArea = ({ chainId, address, epoch }) => { +export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => { const isSmallScreen = useMediaQuery("(max-width: 745px)"); const { breakoutFromStaking } = useBreakoutModal(); @@ -70,7 +70,17 @@ export const ClaimsArea = ({ chainId, address, epoch }) => { const claimableBalance = useMemo(() => { if (isNetworkLegacy(chainId)) { - return isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares; + return isPayoutGhst + ? new DecimalBigNumber( + balanceForShares && currentIndex && currentIndex._value !== 0n + ? (balanceForShares._value * (10n ** BigInt(9 + currentIndex._decimals - balanceForShares._decimals))) / currentIndex._value + : 0n, + 9 + ) + : new DecimalBigNumber( + balanceForShares ? balanceForShares._value : 0n, + balanceForShares ? balanceForShares._decimals : 9 + ); } const toClaim = new DecimalBigNumber(claim.shares, 18); return isPayoutGhst ? toClaim : toClaim.mul(currentIndex); @@ -108,7 +118,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => { if (claim.shares === 0n) return <>; - const warmupTooltip = `Your claim earns rebases during warm-up. You can emergency withdraw, but this forfeits the rebases`; + const warmupTooltip = `Claim earns rebases during warm-up. You can emergency withdraw, but this forfeits the rebases`; return ( <> @@ -134,7 +144,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => { justifyContent="space-between" flexDirection={isSmallScreen ? "column" : "row"} > - Your active {isPayoutGhst ? ghstSymbol : stnkSymbol} claim + My active {isPayoutGhst ? ghstSymbol : stnkSymbol} claim } tooltip={warmupTooltip} @@ -164,6 +174,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => { { }; const ClaimInfo = ({ + chainSymbol, setConfirmationModalOpen, prepareBalance, claim, @@ -200,7 +212,10 @@ const ClaimInfo = ({ - + {isPayoutGhst ? ghstSymbol : stnkSymbol} diff --git a/src/containers/Stake/components/FarmPools.jsx b/src/containers/Stake/components/FarmPools.jsx index 36e81d6..5c25fcd 100644 --- a/src/containers/Stake/components/FarmPools.jsx +++ b/src/containers/Stake/components/FarmPools.jsx @@ -23,7 +23,7 @@ import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens"; import { EMPTY_ADDRESS, FTSO_ADDRESSES } from "../../../constants/addresses"; -const FarmPools = ({ chainId }) => { +const FarmPools = ({ chainId, chainSymbol }) => { const isSmallScreen = useMediaQuery("(max-width: 775px)"); const { network } = useParams(); @@ -35,8 +35,9 @@ const FarmPools = ({ chainId }) => { const pools = [ { - icons: ["FTSO", tokenNameConverter(chainId, reserveSymbol)], - name: `${ftsoSymbol}-${reserveSymbol}`, + icons: [tokenNameConverter(chainId, reserveSymbol), "FTSO"], + chainTokenNames: [undefined, chainSymbol], + name: `${reserveSymbol}-${ftsoSymbol}`, dex: "Uniswap V2", url: `/${network}/dex/uniswap`, tvl: reserveFtsoUniValuation, @@ -101,7 +102,7 @@ const FarmPoolCard = ({ id, pool }) => { - + {pool.name} @@ -127,7 +128,7 @@ const FarmPoolRow = ({ id, pool }) => { - + {pool.name} diff --git a/src/containers/Stake/components/StakeArea.jsx b/src/containers/Stake/components/StakeArea.jsx index 5e0bfc5..7084a8d 100644 --- a/src/containers/Stake/components/StakeArea.jsx +++ b/src/containers/Stake/components/StakeArea.jsx @@ -5,6 +5,7 @@ import { useAccount } from "wagmi"; import { StakeInputArea } from "./StakeInputArea"; export const StakeArea = ({ + chainSymbol, upperToken, setUpperToken, bottomToken, @@ -19,6 +20,7 @@ export const StakeArea = ({ return ( { const actionAmount = new DecimalBigNumber(props.amount, props.spendDecimals); let isRebase = false; - switch (props.action) { + switch (props.action.toUpperCase()) { case "STAKE": isRebase = props.bottomToken === props.stnkSymbol; await stake( @@ -128,11 +129,8 @@ const StakeConfirmationModal = (props) => { } headerContent={ - - {`Confirm ${props.action}`} - + {`Confirm ${props.action}`} } open={props.open} onClose={() => isPending ? {} : props.onClose()} @@ -140,15 +138,25 @@ const StakeConfirmationModal = (props) => { > - + - - - {props.upperToken} - + + + {props.upperToken} @@ -157,15 +165,25 @@ const StakeConfirmationModal = (props) => { label="Assets to Receive" metric={formatNumber(new DecimalBigNumber(props.receiveAmount, props.receiveDecimals), 5)} /> - - - {props.bottomToken} - + + + {props.bottomToken} - + {acknowledgedWarmup || props.action !== "STAKE" ? { fontSize="0.875em" lineHeight="15px" > - Staking drives value accrual, rewarding stakers with rebase yields that fluctuate based on ghostDAO monetary policy and are backed by bond proceeds. + Staking generates rebase yields governed by ghostDAO monetary policy and backed by bonds, Protocol Owned Liquidity (POL), and allocators.   ({ })); export const StakeInputArea = ({ + chainSymbol, upperToken, setUpperToken, bottomToken, @@ -198,7 +199,7 @@ export const StakeInputArea = ({ id={`${tokenName.toLowerCase()}-input`} token={tokenName} tokenName={realTokenName} - tokenOnClick={() => handleModal(true)} + chainTokenName={chainSymbol} inputProps={{ "data-testid": `${tokenName.toLowerCase()}-input`, min: "0" }} value={tokenAmount} onChange={event => setAmount(event.target.value)} @@ -240,11 +241,7 @@ export const StakeInputArea = ({ loading={false} disabled={exceedsAmount} > - {exceedsAmount ? - "Exceeds amount" - : - action[0] + String(action.toLowerCase()).slice(1) - } + {exceedsAmount ? "Exceeds amount" : action } @@ -261,6 +258,7 @@ export const StakeInputArea = ({ onTriggerRebaseChange={setIsTriggerInner} /> closeAndUpdate()} chainId={chainId} diff --git a/src/containers/TreasuryDashboard/components/ProtocolDetails.jsx b/src/containers/TreasuryDashboard/components/ProtocolDetails.jsx index 02a35a8..274166d 100644 --- a/src/containers/TreasuryDashboard/components/ProtocolDetails.jsx +++ b/src/containers/TreasuryDashboard/components/ProtocolDetails.jsx @@ -116,7 +116,7 @@ const ProtocolDetails = ({ chainId, isMobileScreen, theme, }) => { theme={theme} url={`/${networkName.toLowerCase()}/stake`} name="(3, 3) Stake" - sideName={`${formatNumber(apyInner, 0)}% APY`} + sideName={`${formatNumber(apyInner, 2)}% APY`} description={`Staking enables (3, 3) coordination by aligning long-term incentives, sustainably backed by (1, 1) Bonds, LP fees, and Farming. Stake ${ftsoSymbol} to earn rewards and unlock ${bridgeNumbers} Stake\u00B2.`} /> @@ -125,7 +125,7 @@ const ProtocolDetails = ({ chainId, isMobileScreen, theme, }) => { theme={theme} url={`/${networkName.toLowerCase()}/bridge`} name={`${bridgeNumbers} Stake\u00B2`} - sideName={`${formatNumber(gatekeepedApy, 0)}% APY`} + sideName={`${formatNumber(gatekeepedApy, 2)}% APY`} description={`Staking\u00B2 strategy further deepens long-term incentives powered by sustainable crosschain bridging revenue. ${bridgeNumbers} Stake\u00B2 your ${csprSymbol} to receive organic APY with no warm-up and no dilution.`} /> diff --git a/src/hooks/bonds/index.js b/src/hooks/bonds/index.js index af49386..923bdeb 100644 --- a/src/hooks/bonds/index.js +++ b/src/hooks/bonds/index.js @@ -16,6 +16,7 @@ import { useTokenSymbol, useTokenSymbols } from "../tokens"; import { getTokenAddress, getTokenIcons, + getChainTokenNames, getBondNameDisplayName, getTokenPurchaseLink, executeOnChainTransaction @@ -123,7 +124,7 @@ export const useLiveBonds = (chainId, chainName) => { const marketCapacity = markets?.at(index).result?.at(0) ? markets.at(index).result.at(0) : 0n; const quoteTokenAddress = markets?.at(index).result?.at(1) ? markets.at(index).result.at(1) : ""; const capacityInQuote = markets?.at(index).result?.at(2) ? markets.at(index).result.at(2) : 0n; - const marketMaxPayout = markets?.at(index).result?.at(4) ? markets.at(index).result.at(4) : 0n; + const marketMaxPayout = markets?.at(index).result?.at(4) ? markets.at(index).result.at(4) : 0n; const quoteTokenDecimals = metas?.at(index).result?.at(5) ? metas.at(index).result.at(5) : 18; const quoteTokenPerUsd = quotePrices?.at(index).result ? new DecimalBigNumber(quotePrices.at(index).result * (10n ** 9n), quoteTokenDecimals) @@ -162,13 +163,15 @@ export const useLiveBonds = (chainId, chainName) => { baseToken: { name: baseTokenSymbol, purchaseUrl: getTokenPurchaseLink(chainId, "", chainName), + tokenAddress: getTokenAddress(chainId, "FTSO"), + chainNames: getChainTokenNames(chainId, "FTSO"), icons: ["FTSO"], - tokenAddress: getTokenAddress(chainId, "FTSO") }, quoteToken: { name: tokenNameConverter(chainId, quoteTokenSymbol), purchaseUrl: getTokenPurchaseLink(chainId, quoteTokenAddress, chainName), icons: getTokenIcons(chainId, quoteTokenAddress), + chainNames: getChainTokenNames(chainId, quoteTokenAddress), decimals: quoteTokenDecimals, quoteTokenAddress, }, @@ -190,7 +193,7 @@ export const useLiveBonds = (chainId, chainName) => { inQuoteToken: maxPayoutInQuoteToken, }, }; - }).sort((a, b) => (a.id > b.id ? -1 : 1)) : []; + }).sort((a, b) => (a.id > b.id ? -1 : 1)) || []; return { liveBonds, refetch }; } @@ -255,6 +258,7 @@ export const useNotes = (chainId, address) => { quoteToken: { name: tokenNameConverter(chainId, quoteTokenSymbol), icons: getTokenIcons(chainId, quoteTokenAddress), + chainNames: getChainTokenNames(chainId, quoteTokenAddress), }, vesting: terms?.at(index).result?.at(2) ? terms.at(index).result.at(2) : 0, created: notesRaw?.at(index).result?.at(1) ? notesRaw.at(index).result.at(1) : 0, diff --git a/src/hooks/helpers.js b/src/hooks/helpers.js index c3a1651..89dac6f 100644 --- a/src/hooks/helpers.js +++ b/src/hooks/helpers.js @@ -174,7 +174,7 @@ export const getTokenIcons = (chainId, address) => { icons = ["GHST"]; break; case FTSO_DAI_LP_ADDRESSES[chainId]: - icons = ["FTSO", "WETH"]; + icons = ["WETH", "FTSO"]; break; default: icons = [""] @@ -182,6 +182,21 @@ export const getTokenIcons = (chainId, address) => { return icons; } +export const getChainTokenNames = (chainId, address) => { + let icons = [undefined]; + switch (address) { + case FTSO_DAI_LP_ADDRESSES[chainId]: + icons = [undefined, "WETH"]; + break; + case RESERVE_ADDRESSES[chainId]: + icons = [undefined] + break; + default: + icons = ["WETH"] + } + return icons; +} + export const getBondNameDisplayName = (chainId, tokenAddress, baseTokenSymbol) => { let stringValue = tokenNameConverter(chainId, "WETH") if (tokenAddress.toUpperCase() === FTSO_DAI_LP_ADDRESSES[chainId].toUpperCase()) { diff --git a/src/style.scss b/src/style.scss index 9ca57cf..1516f59 100644 --- a/src/style.scss +++ b/src/style.scss @@ -173,3 +173,8 @@ input:-webkit-autofill { color: #ffffff !important; -webkit-text-fill-color: #ffffff !important; } + +@keyframes spinTokenIcon { + from { transform: rotate(360deg); } + to { transform: rotate(0deg); } +}