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); }
+}