Compare commits

..

No commits in common. "3ad84a886e9f737348efade560340debec6a555d" and "7f01cc4c609fa8f2c1969ffe80ae4f32851dbf3a" have entirely different histories.

42 changed files with 152 additions and 351 deletions

View File

@ -1,7 +1,7 @@
{
"name": "ghost-dao-interface",
"private": true,
"version": "0.7.51",
"version": "0.7.49",
"type": "module",
"scripts": {
"dev": "vite",

View File

@ -198,7 +198,7 @@ function App() {
<Route path="dashboard" element={<TreasuryDashboard chainId={addressChainId ? addressChainId : chainId} />} />
<Route path="bonds" element={<Bonds connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
<Route path="bonds/:id" element={<BondModalContainer config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
<Route path="stake" element={<StakeContainer config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
<Route path="stake" element={<StakeContainer 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="governance" element={<Governance config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />

View File

@ -84,20 +84,22 @@ const Modal = ({
// getModalStyle is not a pure function, we roll the style only on the first render
const [modalStyle] = useState(getModalStyle);
const closeButton = (
<GhostStyledIcon
<IconButton
aria-label="close"
component={CloseIcon}
sx={{ cursor: "pointer" }}
color="inherit"
size="small"
onClick={e => {
if (props.onClose) {
props.onClose(e, "escapeKeyDown");
}
}}
/>
>
<GhostStyledIcon component={CloseIcon} />
</IconButton>
);
//modal must have a close position. Close position and topLeft or topRight cant be used for the same position.
const topRightPos = topRight ? topRight : closeButton;
const topRightPos = closePosition === "right" ? closeButton : topRight;
const topLeftPos = closePosition === "left" ? closeButton : topLeft;
return (
@ -111,7 +113,7 @@ const Modal = ({
{...props}
minHeight={minHeight}
maxWidth={maxWidth}
>
>
<Paper
style={modalStyle}
className={classes.paper}

View File

@ -64,7 +64,7 @@ const Paper = ({
{(topLeft || headerText || topRight || headerContent) && (
<Grid item className="card-header">
<Box display="flex" justifyContent="space-between">
{topLeft && <Box className="top-left" display="flex" justifyContent="center" alignItems="center">{topLeft}</Box>}
{topLeft && <div className="top-left">{topLeft}</div>}
{headerText && !headerContent && (
<Box display="flex" flexDirection="row" alignItems="center">
<Typography fontSize="24px" className="header-text" fontWeight={700} lineHeight="33px">
@ -83,7 +83,7 @@ const Paper = ({
</Box>
)}
{headerContent}
<Box className="top-right" display="flex" justifyContent="center" alignItems="center">{topRight}</Box>
<div className="top-right">{topRight}</div>
</Box>
{subHeader && <Box display="flex">{subHeader}</Box>}
</Grid>

View File

@ -44,7 +44,6 @@ const SwapCard = ({
tokenName,
inputWidth,
inputFontSize,
chainTokenName,
maxWidth = "416px",
...props
}) => {
@ -73,26 +72,12 @@ const SwapCard = ({
cursor: tokenOnClick ? "pointer" : "default",
}}
borderRadius="6px"
paddingX="7px"
paddingY="2px"
paddingX="9px"
paddingY="6.5px"
alignItems="center"
{...onClickProps}
>
{typeof token === "string"
? <Token
chainTokenName={chainTokenName}
name={token}
parentSx={{
"& svg:nth-of-type(2)": {
transform: "scale(0.52)",
}
}}
sx={{
transform: "scale(0.65)",
transformOrigin: "center"
}}
/>
: token}
{typeof token === "string" ? <Token name={token} sx={{ fontSize: "21px" }} /> : token}
{(typeof token === "string" || tokenName) && (
<Typography fontSize="15px" lineHeight="24px" marginLeft="9px">

View File

@ -69,28 +69,27 @@ export const parseKnownToken = (name) => {
return icon;
}
const Token = ({ chainTokenName, name, isNative, parentSx, viewBox = "0 0 260 260", fontSize = "large", ...props }) => {
const Token = ({ chainTokenName, name, viewBox = "0 0 260 260", fontSize = "large", ...props }) => {
return (
<Box display="flex" justifyContent="center" alignItems="center" position="relative" sx={{ ...parentSx }} >
<Box display="flex" justifyContent="center" alignItems="center" position="relative">
<StyledSvgIcon
inheritViewBox
fontSize={fontSize}
component={parseKnownToken(name)}
style={{ animation: `spinTokenIcon ${isNative ? 10 : 0}s linear infinite` }}
{...props}
></StyledSvgIcon>
{chainTokenName && (
<StyledSvgIcon
inheritViewBox
component={parseKnownToken(chainTokenName)}
sx={{
style={{
position: "absolute",
bottom: 0,
right: 0,
transform: "translate(15%, 15%) scale(0.8)",
borderRadius: "100%",
zIndex: 10,
marginLeft: "70%",
marginTop: "45%",
width: "45%",
height: "45%",
border: "1px solid #fff",
borderRadius: "100%"
}}
></StyledSvgIcon>
)}

View File

@ -1,12 +1,11 @@
import { Avatar, Box } from "@mui/material";
import Token from "../Token/Token";
const TokenStack = ({ chainTokenNames, tokens, style, images, network, ...props }) => {
const TokenStack = ({ tokens, style, images, network, ...props }) => {
const imageStyles = {
height: "27px",
width: "27px",
...style,
};
return (
<Box display="flex" flexDirection="row" marginTop={network ? "3px" : "0px"} marginLeft={network ? "3px" : "0px"}>
@ -21,25 +20,18 @@ const TokenStack = ({ chainTokenNames, tokens, style, images, network, ...props
<Avatar
src={image}
style={{
...(i !== 0 ? { marginLeft: -7, zIndex: 100 - i, ...imageStyles } : { zIndex: 100 - i, ...imageStyles }),
...(i !== 0 ? { marginLeft: -7, zIndex: 1, ...imageStyles } : { zIndex: 1, ...imageStyles }),
}}
/>
))}
{tokens?.map((token, i) => (
<Token
{...props}
key={i}
name={token}
style={{
...(i !== 0 ? { marginLeft: -12, zIndex: 100 - i, ...style } : { zIndex: 100 - i, ...style }),
...(i !== 0 ? { marginLeft: -12, zIndex: 1, ...style } : { zIndex: 2, ...style }),
}}
parentSx={{
"& svg:nth-of-type(2)": {
transform: "translate(22%, 22%) scale(0.6)",
zIndex: 100,
}
}}
chainTokenName={chainTokenNames?.at(i)}
{...props}
/>
))}
</Box>

View File

@ -132,6 +132,7 @@ function InitialWalletView({ isWalletOpen, address, chainId, onClose }) {
useEffect(() => {
if (isWalletOpen) {
console.log(`/${chainName.toLowerCase()}/sidebar`)
ReactGA.send({ hitType: "pageview", page: `/${chainName.toLowerCase()}/sidebar` });
}
}, [isWalletOpen, chainName])
@ -142,6 +143,7 @@ function InitialWalletView({ isWalletOpen, address, chainId, onClose }) {
}
}, [isWalletOpen, tokens])
return (
<Paper>
<Box sx={{ padding: theme.spacing(0, 3), display: "flex", flexDirection: "column", minHeight: "100vh" }}>

View File

@ -130,7 +130,6 @@ export const Token = (props) => {
height: "28px",
}}
tokens={props.icons}
chainTokenNames={props.chainTokenNames}
/>
<Typography>{symbol}</Typography>
</Box>
@ -208,8 +207,8 @@ export const useWallet = (chainId, userAddress) => {
const nativeSymbol = useMemo(() => {
return config?.getClient()?.chain?.nativeCurrency?.symbol;
}, [chainId, config]);
}, [config]);
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
@ -224,7 +223,7 @@ export const useWallet = (chainId, userAddress) => {
if (token0?.at(0) === reserveSymbol) {
tokenAddresses = [lpReserveFtsoTokens?.token0, lpReserveFtsoTokens?.token1];
tokenNames = [...token0, ...token1];
let tokenNames = [...token0, ...token1];
}
return { tokenAddresses, tokenNames }
@ -252,7 +251,6 @@ 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,
@ -263,7 +261,6 @@ 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,
},
@ -274,10 +271,6 @@ 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,
}

View File

@ -9,7 +9,6 @@ export const AVAILABLE_DEXES = {
name: "Uniswap",
icon: UniswapIcon,
viewBox: "0 0 195 230",
isFork: true,
},
],
[NetworkId.TESTNET_HOODI]: [
@ -17,7 +16,6 @@ export const AVAILABLE_DEXES = {
name: "Uniswap",
icon: UniswapIcon,
viewBox: "0 0 195 230",
isFork: true,
},
],
[NetworkId.TESTNET_MORDOR]: [
@ -25,7 +23,6 @@ export const AVAILABLE_DEXES = {
name: "Uniswap",
icon: UniswapIcon,
viewBox: "0 0 195 230",
isFork: true,
},
],
};

View File

@ -91,7 +91,6 @@ 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,
}
@ -113,11 +112,7 @@ export const BondModal = ({ bond, chainId, address, config, connect }) => {
</Box>
</Link>
<TokenStack
chainTokenNames={preparedQuoteToken.chainNames}
tokens={preparedQuoteToken.icons}
sx={{ fontSize: "27px" }}
/>
<TokenStack tokens={preparedQuoteToken.icons} sx={{ fontSize: "27px" }} />
<Box display="flex" flexDirection="column" ml={1} justifyContent="center" alignItems="center">
<Typography variant="h4" fontWeight={500}>
{preparedQuoteToken.name}

View File

@ -49,7 +49,7 @@ const Bonds = ({ chainId, address, connect }) => {
return (
<Box>
<PageTitle name={"Protocol Bonds"} subtitle={`(1, 1) Buy ${ftsoSymbol} at a treasury-backed discount`} />
<PageTitle name={"Protocol Bonding"} subtitle={`Buy ${ftsoSymbol} from the protocol at a discount`} />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",

View File

@ -42,7 +42,6 @@ const BondConfirmModal = ({
isNative,
bondQuoteTokenName,
bondQuoteTokenIcons,
bondQuoteTokenChainNames,
handleConfirmClose
}) => {
const theme = useTheme();
@ -128,16 +127,16 @@ const BondConfirmModal = ({
maxWidth="476px"
minHeight="200px"
open={isOpen}
headerContent={<Typography variant="h4">{bondQuoteTokenName} Bond</Typography>}
onClose={!isPending && handleConfirmCloseMaster}
topRight={
<GhostStyledIcon
viewBox="0 0 23 23"
component={SettingsIcon}
style={{ cursor: "pointer" }}
onClick={handleSettingsOpen}
/>
headerContent={
<Box display="flex" flexDirection="row">
<TokenStack tokens={bondQuoteTokenIcons} sx={{ fontSize: "27px" }} />
<Typography variant="h4" sx={{ marginLeft: "6px" }}>
{bondQuoteTokenName}
</Typography>
</Box>
}
onClose={!isPending && handleConfirmCloseMaster}
topLeft={<GhostStyledIcon viewBox="0 0 23 23" component={SettingsIcon} style={{ cursor: "pointer" }} onClick={handleSettingsOpen} />}
>
<>
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
@ -146,58 +145,19 @@ const BondConfirmModal = ({
label="Assets to Bond"
metric={spendAmount}
/>
<Box
sx={{ background: "" }}
height="120px"
display="flex"
flexDirection="column"
justifyContent="center"
alignItems="center"
>
<TokenStack
parentSx={{
height: "80px",
"& svg:nth-of-type(2)": {
transform: "translate(50%, -30%)",
zIndex: 100,
}
}}
sx={{ transform: "scale(1.65)", }}
tokens={bond.quoteToken.icons}
chainTokenNames={bond.quoteToken.chainNames}
/>
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>{bondQuoteTokenName}</Typography>
</Box>
</Box>
<GhostStyledIcon sx={{ transform: "rotate(-90deg)" }} component={ArrowDropDownIcon} />
<Box display="flex" flexDirection="column">
<Metric label="Assets to Receive" metric={receiveAmount} />
<Box
sx={{ background: "" }}
height="120px"
display="flex"
flexDirection="column"
justifyContent="center"
alignItems="center"
gap="0"
>
<TokenStack
parentSx={{
height: "80px",
"& svg:nth-of-type(2)": {
transform: "translate(50%, -30%)",
zIndex: 100,
}
}}
sx={{ transform: "scale(1.65)", }}
tokens={bond.baseToken.icons}
chainTokenNames={bond.baseToken.chainNames}
/>
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>{bond.baseToken.name}</Typography>
</Box>
</Box>
</Box>
<Box mt="10px" mb="18px" borderTop={`1px solid ${theme.colors.gray[500]}`}></Box>
<Box mt="21px" mb="21px" borderTop={`1px solid ${theme.colors.gray[500]}`}></Box>
<DataRow title="ROI" balance={<BondDiscount discount={bond.discount} textOnly />} />
<DataRow title="Bond Slippage" balance={<BondSlippage slippage={slippage} textOnly />} />
<DataRow title="Vesting Term" balance={<BondVesting vesting={bond.vesting} />} />

View File

@ -100,19 +100,12 @@ const BondInputArea = ({
<Box display="flex" flexDirection="column" width="100%" maxWidth="476px">
<Box mb="21px">
<SwapCollection
iconNotNeeded
UpperSwapCard={
<SwapCard
maxWidth="476px"
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
id="from"
token={
<TokenStack
chainTokenNames={bond.quoteToken.chainNames}
tokens={bond.quoteToken.icons}
sx={{ fontSize: "25px", height: "30px" }}
/>
}
token={<TokenStack tokens={bond.quoteToken.icons} sx={{ fontSize: "21px" }} />}
tokenName={preparedQuoteToken.name}
info={formatCurrency(balance, formatDecimals, preparedQuoteToken.name)}
endString="Max"
@ -126,13 +119,7 @@ const BondInputArea = ({
maxWidth="476px"
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
id="to"
token={
<TokenStack
chainTokenNames={bond.baseToken.chainNames}
tokens={bond.baseToken.icons}
sx={{ fontSize: "25px", height: "30px" }}
/>
}
token={<TokenStack tokens={bond.baseToken.icons} sx={{ fontSize: "21px" }} />}
tokenName={bond.baseToken.name}
value={amountInBaseToken.toString({ decimals: 9 })}
inputProps={{ "data-testid": "toInput" }}
@ -242,7 +229,6 @@ const BondInputArea = ({
receiveAmount={formatNumber(amountInBaseToken, formatDecimals)}
bondQuoteTokenName={preparedQuoteToken.name}
bondQuoteTokenIcons={preparedQuoteToken.icons}
bondQuoteTokenChainNames={preparedQuoteToken.chainNames}
isNative={preparedQuoteToken.address === undefined}
handleSettingsOpen={handleSettingsOpen}
isOpen={confirmOpen}

View File

@ -72,7 +72,7 @@ const BondCard = ({ bond, secondsTo, chainName }) => {
return (
<Box key={bond.id} id={bond.id + `--bond`} mt="32px">
<Box display="flex" alignItems="center">
<TokenStack chainTokenNames={bond.quoteToken.chainNames} tokens={bond.quoteToken.icons} />
<TokenStack tokens={bond.quoteToken.icons} />
<Box display="flex" flexDirection="column" ml="8px">
<Typography>{bond.quoteToken.name}</Typography>
@ -237,7 +237,7 @@ const BondRow = ({ bond, secondsTo, chainName }) => {
const TokenIcons = ({ token, chainId, explorer }) => (
<Box display="flex" alignItems="center">
<TokenStack chainTokenNames={token.chainNames} tokens={token.icons} />
<TokenStack tokens={token.icons} />
<Box display="flex" flexDirection="column" ml="16px">
<Typography style={{ fontSize: "12px", fontWeight: 600, lineHeight: "18px" }}>{token.name}</Typography>

View File

@ -103,7 +103,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
headerContent={
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
<Typography variant="h6">
My Bonds
Your Bonds
</Typography>
</Box>
}
@ -143,7 +143,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
{notes.map((note, index) => (
<Box key={index} mt="32px">
<Box display="flex" alignItems="center">
<TokenStack chainTokenNames={note.quoteToken.chainNames} tokens={note.quoteToken.icons} />
<TokenStack tokens={note.quoteToken.icons} />
<Box ml="8px">
<Typography>{note.quoteToken.name}</Typography>
</Box>
@ -205,7 +205,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
<TableRow key={index}>
<TableCell style={{ padding: "8px 0" }}>
<Box display="flex" alignItems="center">
<TokenStack chainTokenNames={note.quoteToken.chainNames} tokens={note.quoteToken.icons} />
<TokenStack tokens={note.quoteToken.icons} />
<Box display="flex" flexDirection="column" ml="16px">
<Typography>{note.quoteToken.name}</Typography>
</Box>

View File

@ -5,8 +5,7 @@ import { getBlockNumber } from "@wagmi/core";
import { useConfig } from "wagmi";
import { ss58Decode } from "@polkadot-labs/hdkd-helpers";
import { toHex } from "@polkadot-api/utils";
import CheckIcon from '@mui/icons-material/CheckCircle';
import CancelIcon from '@mui/icons-material/Cancel';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import { CheckBoxOutlineBlank, CheckBoxOutlined } from "@mui/icons-material";
@ -166,7 +165,6 @@ const BridgeView = ({
incomingFee
}) => {
const theme = useTheme();
const [inputFocused, setInputFocused] = useState(false);
const config = useConfig();
const { gatekeeperAddress } = useGatekeeperAddress(chainId);
@ -191,17 +189,13 @@ const BridgeView = ({
<SwapCard
id={`bridge-token-receiver`}
inputWidth={"100%"}
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}
value={convertedReceiver ? shorten(receiver, 15, -10) : receiver}
onChange={event => setReceiver(convertedReceiver ? "" : event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
placeholder="GHOST address (sf prefixed)"
endString={convertedReceiver
? <GhostStyledIcon color="success" viewBox="0 0 25 25" component={CheckIcon} />
: inputFocused && receiver !== ""
? <GhostStyledIcon color="error" viewBox="0 0 25 25" component={CancelIcon} />
: undefined
? <GhostStyledIcon color="success" viewBox="0 0 25 25" component={CheckCircleIcon} />
: undefined
}
type="text"
maxWidth="100%"
@ -280,7 +274,7 @@ const WelcomeView = ({
<>
<Typography>{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} (3, 3) 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:`
}</Typography>
<Box display="flex" justifyContent="center">
@ -427,7 +421,7 @@ const ConfirmStep = ({
<Box display="flex" flexDirection="column" justifyContent="space-between" alignItems="center" gap="10px">
<Metric label="To Receive" metric={formatNumber(receivedEstimation, 5)} />
<Box width="100%" display="flex" flexDirection="column" justifyContent="center" alignItems="center">
<Token isNative name={"GHST"} sx={{ fontSize: "55px" }} />
<Token name={"GHST"} sx={{ fontSize: "55px" }} />
<Typography>{ghstSymbol}</Typography>
</Box>
</Box>
@ -499,7 +493,7 @@ const ConfirmStep = ({
disabled={isPending || !acknowledgeWalletCustody || !acknowledgeBridgingRisk}
fullWidth
>
{isPending ? "Confirming..." : "Confirm"}
{isPending ? "Confirming..." : "I Confirm"}
</PrimaryButton>
</>
)

View File

@ -320,7 +320,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
return (
<>
<PageTitle name="GHOST Bridge" subtitle={`(10, 10) Bridge ${ghstSymbol} into (10, 10) Stake²`} />
<PageTitle name="GHOST Bridge" subtitle={`Bridge $${ghstSymbol} via the only pure Web3 protocol`} />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",

View File

@ -28,8 +28,7 @@ import SwapCollection from "../../components/Swap/SwapCollection";
import { ghost } from "../../hooks/staking";
import { useBalance } from "../../hooks/tokens";
import CheckIcon from '@mui/icons-material/CheckCircle';
import CancelIcon from '@mui/icons-material/Cancel';
import CheckIcon from '@mui/icons-material/Check';
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
@ -59,7 +58,6 @@ 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("");
@ -168,17 +166,13 @@ export const BridgeCardAction = ({
UpperSwapCard={<SwapCard
id={`bridge-token-receiver`}
inputWidth={"100%"}
value={convertedReceiver ? "" : receiver}
onBlur={() => setInputFocused(true)}
onFocus={() => setInputFocused(false)}
onChange={event => setReceiver(event.currentTarget.value)}
value={convertedReceiver ? sliceString(receiver, 15, -10) : receiver}
onChange={event => setReceiver(convertedReceiver ? "" : event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
placeholder={convertedReceiver ? sliceString(receiver, 15, -10) : "GHOST address (sf prefixed)"}
placeholder="GHOST address (sf prefixed)"
endString={convertedReceiver
? <GhostStyledIcon color="success" viewBox="0 0 25 25" component={CheckCircleIcon} />
: inputFocused && receiver !== ""
? <GhostStyledIcon color="error" viewBox="0 0 25 25" component={CancelIcon} />
: undefined
: undefined
}
type="text"
maxWidth="100%"

View File

@ -33,23 +33,11 @@ const RouteHop = ({ theme, token, chainTokenName, arrowNeeded }) => {
sx={{ backgroundColor: theme.colors.gray[600] }}
borderRadius="6px"
paddingX="9px"
paddingY="2px"
paddingY="6.5px"
alignItems="center"
>
<Token
chainTokenName={chainTokenName}
name={token}
parentSx={{
"& svg:nth-of-type(2)": {
transform: "scale(0.52)",
}
}}
sx={{
transform: "scale(0.65)",
transformOrigin: "center"
}}
/>
<Typography fontSize="15px" lineHeight="24px" marginLeft="5px">
<Token chainTokenName={chainTokenName} name={token} sx={{ fontSize: "21px" }} />
<Typography fontSize="15px" lineHeight="24px" marginLeft="9px">
{token}
</Typography>
</Box>

View File

@ -32,7 +32,6 @@ 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";
@ -68,7 +67,6 @@ const Dex = ({ chainId, address, connect, config }) => {
const [tokenAddressTop, setTokenAddressTop] = useState(EMPTY_ADDRESS);
const [tokenAddressBottom, setTokenAddressBottom] = useState(FTSO_ADDRESSES[chainId]);
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
const { symbol: tokenNameTopInner } = useTokenSymbol(chainId, tokenAddressTop);
const { symbol: tokenNameBottomInner } = useTokenSymbol(chainId, tokenAddressBottom);
@ -185,13 +183,6 @@ 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) {
@ -249,8 +240,8 @@ const Dex = ({ chainId, address, connect, config }) => {
</Helmet>
<PageTitle
name="DEX Swap"
subtitle={`(3, 3) Swap ${chainSymbol} for ${ftsoSymbol} and ${ftsoSymbol}-${chainSymbol} LP powered by ${pathname.name.charAt(0).toUpperCase() + pathname.name.slice(1).toLowerCase()} V2${isDexFork ? " Fork" : ""}`}
name={`${pathname.name.charAt(0).toUpperCase() + pathname.name.slice(1).toLowerCase()} V2 Classic`}
subtitle="Swap via Uniswap V2 Fork"
/>
<Container
style={{
@ -405,7 +396,6 @@ const Dex = ({ chainId, address, connect, config }) => {
<Box height="350px">
{isSwap ?
<SwapContainer
chainSymbol={chainSymbol}
tokenNameTop={tokenNameTop}
tokenNameBottom={tokenNameBottom}
onCardsSwap={onCardsSwap}
@ -425,7 +415,6 @@ const Dex = ({ chainId, address, connect, config }) => {
/>
:
<PoolContainer
chainSymbol={chainSymbol}
tokenNameTop={tokenNameTop}
tokenNameBottom={tokenNameBottom}
onCardsSwap={onCardsSwap}

View File

@ -20,7 +20,6 @@ import {
} from "../../hooks/uniswapv2";
const PoolContainer = ({
chainSymbol,
tokenNameTop,
tokenNameBottom,
onCardsSwap,
@ -220,8 +219,7 @@ const PoolContainer = ({
UpperSwapCard={
<SwapCard
id="from"
token={tokenNameTop}
chainTokenName={tokenNameTop !== chainSymbol && chainSymbol}
token={<TokenStack tokens={[tokenNameTop]} sx={{ fontSize: "21px" }} />}
tokenName={tokenNameTop}
info={(!isSmallScreen ? "Balance: " : "") + formatCurrency(balanceTop, formatDecimals, tokenNameTop)}
endString="Max"
@ -235,8 +233,7 @@ const PoolContainer = ({
LowerSwapCard={
<SwapCard
id="to"
token={tokenNameBottom}
chainTokenName={tokenNameBottom !== chainSymbol && chainSymbol}
token={<TokenStack tokens={[tokenNameBottom]} sx={{ fontSize: "21px" }} />}
tokenName={tokenNameBottom}
value={amountBottom}
onChange={event => emptyPool ? setAmountBottom(event.currentTarget.value) : {}}

View File

@ -25,7 +25,6 @@ import {
import { EMPTY_ADDRESS } from "../../constants/addresses";
const SwapContainer = ({
chainSymbol,
tokenNameTop,
tokenNameBottom,
address,
@ -213,8 +212,7 @@ const SwapContainer = ({
<SwapCard
maxWidth="356px"
id="from"
token={tokenNameTop}
chainTokenName={tokenNameTop !== chainSymbol && chainSymbol}
token={<TokenStack tokens={[tokenNameTop]} sx={{ fontSize: "21px" }} />}
tokenName={tokenNameTop}
info={
(!isSmallScreen ? "Balance: " : "") +
@ -232,8 +230,8 @@ const SwapContainer = ({
<SwapCard
maxWidth="356px"
id="to"
token={tokenNameBottom}
chainTokenName={tokenNameBottom !== chainSymbol && chainSymbol}
token={<TokenStack tokens={[tokenNameBottom]} sx={{ fontSize: "21px" }} />}
tokenName={tokenNameBottom}
value={amountBottom}
inputProps={{ "data-testid": "toInput" }}
tokenOnClick={() => setBottomTokenListOpen(true)}

View File

@ -15,7 +15,7 @@ import { isAddress, getAddress } from "@ethersproject/address";
import Modal from "../../components/Modal/Modal";
import SwapCard from "../../components/Swap/SwapCard";
import Token from "../../components/Token/Token";
import TokenStack from "../../components/TokenStack/TokenStack";
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { formatNumber } from "../../helpers/";
@ -65,24 +65,26 @@ 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]
}
]
@ -103,7 +105,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)}
>
<SwapCard
@ -130,18 +132,10 @@ const TokenModal = ({ chainId, account, chainSymbol, listOpen, setListOpen, setT
return (
<TableRow onClick={() => setUsedAddress(token)} hover key={index} id={index + `--token`} data-testid={index + `--token`}>
<TableCell style={{ padding: "8px 0" }}>
<Token
chainTokenName={token.chainTokenName}
name={token.name}
parentSx={{
"& svg:nth-of-type(2)": {
transform: "translate(-5%, 10%) scale(0.8)",
}
}}
/>
<TokenStack style={{ width: "32px", height: "32px" }} tokens={token.icons} />
</TableCell>
<TableCell style={{ padding: "8px", height: "32px" }}>
<TableCell style={{ padding: "8px 0", height: "32px" }}>
<Typography>{token.name}</Typography>
</TableCell>

View File

@ -31,7 +31,7 @@ const Governance = ({ connect, config, address, chainId }) => {
return (
<Box>
<PageTitle name="Protocol Governance" subtitle={`Vote with ${ghstSymbol} on DAO proposals`} />
<PageTitle name="Protocol Governance" subtitle={`Cast $${ghstSymbol} to facilitate DAO decisions`} />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",

View File

@ -107,7 +107,7 @@ const NewProposal = ({ config, address, connect, chainId }) => {
closeModal={() => setIsModalOpened(false)}
/>
<Box>
<PageTitle name="Create Proposal" subtitle="Submit proposals to strengthen the DAO" />
<PageTitle name="Create Proposal" subtitle="Submit your proposal to strengthen the DAO" />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",

View File

@ -110,6 +110,8 @@ 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}` });
}, []);
@ -191,7 +193,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
name={`GDP-${id.slice(-5)}`}
subtitle={
<Typography component="span">
{`Cast ${ghstSymbol} to shape this proposal's outcome`}
{`Cast $${ghstSymbol} to shape this proposal's outcome`}
</Typography>
}
/>
@ -237,10 +239,10 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
<Box display="flex" flexDirection="column">
<Box display="flex" justifyContent="space-between">
<Typography sx={{ textShadow: "0 0 black", fontWeight: 600 }} variant="body1" color={theme.colors.feedback.success}>
For: {formatNumber(forVotes.toString(), 2)} ({formatNumber(forPercentage?.toString(), 2)}%)
For: {formatNumber(forVotes.toString(), 2)} ({formatNumber(forPercentage?.toString(), 1)}%)
</Typography>
<Typography sx={{ textShadow: "0 0 black", fontWeight: 600 }} variant="body1" color={theme.colors.feedback.error}>
Against: {formatNumber(againstVotes.toString(), 2)} ({formatNumber(againstPercentage?.toString(), 2)}%)
Against: {formatNumber(againstVotes.toString(), 2)} ({formatNumber(againstPercentage?.toString(), 1)}%)
</Typography>
</Box>
<LinearProgressBar
@ -261,7 +263,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
</Box>
<Box display="flex" justifyContent="space-between">
<Typography>Locked</Typography>
<Typography>{formatCurrency(proposalLocked, 5, ghstSymbol)}</Typography>
<Typography>{formatCurrency(proposalLocked, 4, ghstSymbol)}</Typography>
</Box>
<hr width="100%" />
@ -271,7 +273,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
<Typography>Quorum</Typography>
<InfoTooltip message={`Minimum $${ghstSymbol} turnout required for the proposal to become valid, as percentage of the total $${ghstSymbol} supply at the time when proposal was created`} />
</Box>
<Typography>{formatNumber(proposalQuorum.toString(), 5)} ({formatNumber(quorumPercentage, 2)}%)</Typography>
<Typography>{formatNumber(proposalQuorum.toString(), 4)} ({formatNumber(quorumPercentage, 1)}%)</Typography>
</Box>
<Box display="flex" justifyContent="space-between">
@ -279,7 +281,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
<Typography>Total</Typography>
<InfoTooltip message={`Total votes for the proposal, as percentage of the total $${ghstSymbol} supply at the time when proposal was created`}/>
</Box>
<Typography>{formatNumber(totalSupply.toString(), 5)} ({formatNumber(votePercentage, 2)}%)</Typography>
<Typography>{formatNumber(totalSupply.toString(), 4)} ({formatNumber(votePercentage, 1)}%)</Typography>
</Box>
<Box display="flex" justifyContent="space-between">
@ -287,7 +289,7 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
<Typography>Votes</Typography>
<InfoTooltip message={`Your voting power, as percentage of total $${ghstSymbol} at the time when proposal was created`} />
</Box>
<Typography>{formatNumber(pastVotes.toString(), 5)} ({formatNumber(voteWeightPercentage, 2)}%)</Typography>
<Typography>{formatNumber(pastVotes.toString(), 4)} ({formatNumber(voteWeightPercentage, 1)}%)</Typography>
</Box>
</Box>

View File

@ -81,7 +81,7 @@ export const parseFunctionCalldata = ({
case allPossibleFunctions[1].value:
return <SetAdjustmentParsed key={index} {...props} />;
case allPossibleFunctions[2].value:
return <CreateBondParsed key={index} {...props} />;
return <CreateBondParsed {...props} />;
case allPossibleFunctions[3].value:
return <SetProposalThresholdParsed key={index} {...props} />;
case allPossibleFunctions[4].value:
@ -288,7 +288,7 @@ export const ParsedCell = (props) => {
</TableCell>
<TableCell align="center" style={{ padding: "8px 0" }}>
<Typography>{formatCurrency(props.value, 5, props.nativeCoin)}</Typography>
<Typography>{formatCurrency(props.value, 4, props.nativeCoin)}</Typography>
</TableCell>
<TableCell>
@ -330,7 +330,7 @@ export const ParsedCell = (props) => {
<Box display="flex" justifyContent="space-between">
<Typography>Value</Typography>
<Link onClick={handleCalldataCopy} target="_blank" rel="noopener noreferrer">
<Typography>{formatCurrency(props.value, 5, props.nativeCoin)}</Typography>
<Typography>{formatCurrency(props.value, 4, props.nativeCoin)}</Typography>
</Link>
</Box>

View File

@ -14,7 +14,7 @@ import Paper from "../../components/Paper/Paper";
import TokenStack from "../../components/TokenStack/TokenStack";
import { useTokenSymbol } from "../../hooks/tokens";
const Stake = ({ chainId, chainSymbol, address, isOpened, closeModal, connect }) => {
const Stake = ({ chainId, address, isOpened, closeModal, connect }) => {
const [action, setAction] = useState("STAKE");
const [settingsModalOpen, setSettingsModalOpen] = useState(false);
@ -31,13 +31,13 @@ const Stake = ({ chainId, chainSymbol, 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, chainSymbol, address, isOpened, closeModal, connect })
headerContent={
<Box display="flex" justifyContent="center" alignItems="center" gap="15px">
<Typography variant="h4">{action}</Typography>
<TokenStack tokens={[upperToken, bottomToken, chainSymbol]} />
<TokenStack tokens={[upperToken, bottomToken]} />
</Box>
}
topRight={
topLeft={
<GhostStyledIcon
viewBox="0 0 23 23"
component={SettingsIcon}
@ -64,7 +64,6 @@ const Stake = ({ chainId, chainSymbol, address, isOpened, closeModal, connect })
>
<Box display="flex" alignItems="center" justifyContent="center" flexDirection="column">
<StakeArea
chainSymbol={chainSymbol}
settingsModalOpen={settingsModalOpen}
closeSettingModal={() => setSettingsModalOpenInner(false)}
upperToken={upperToken}

View File

@ -1,4 +1,4 @@
import { Dispatch, SetStateAction, useState, useEffect, useMemo } from "react";
import { Dispatch, SetStateAction, useState, useEffect } 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, config, connect }) => {
export const StakeContainer = ({ chainId, address, connect }) => {
const location = useLocation();
const [isModalOpened, handleModal] = useState(false);
@ -32,12 +32,6 @@ export const StakeContainer = ({ chainId, address, config, 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])
@ -45,7 +39,6 @@ export const StakeContainer = ({ chainId, address, config, connect }) => {
if (isModalOpened) {
return (
<Stake
chainSymbol={chainSymbol}
chainId={chainId}
address={address}
isOpened={isModalOpened}
@ -57,7 +50,7 @@ export const StakeContainer = ({ chainId, address, config, connect }) => {
return (
<Box>
<PageTitle name="Protocol Staking" subtitle={`(3, 3) Stake ${ftsoSymbol} to earn rebase yields backed by protocol revenue`} />
<PageTitle name="Protocol Staking" subtitle={`Stake your ${ftsoSymbol} to earn rebase yields`} />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
@ -95,7 +88,7 @@ export const StakeContainer = ({ chainId, address, config, connect }) => {
</Grid>
<Divider sx={{ marginTop: "30px" }} />
<ClaimsArea chainId={chainId} address={address} chainSymbol={chainSymbol} epoch={epoch} />
<ClaimsArea chainId={chainId} address={address} epoch={epoch} />
<Divider />
<Box mt="15px" display="flex" flexDirection="column" alignItems="center" justifyContent="center">
@ -111,7 +104,7 @@ export const StakeContainer = ({ chainId, address, config, connect }) => {
</Box>
</Box>
</Paper>
<FarmPools chainId={chainId} chainSymbol={chainSymbol} />
<FarmPools chainId={chainId} />
</Box>
</Container>
</Box>

View File

@ -42,7 +42,7 @@ const ClaimConfirmationModal = (props) => {
maxWidth="356px"
topLeft={<></>}
headerContent={
<Box display="flex" flexDirection="column">
<Box display="flex" flexDirection="row">
<Typography variant="h5">{`Confirm ${capitalize(props.action)}`}</Typography>
</Box>
}

View File

@ -50,7 +50,7 @@ const StyledTableHeader = styled(TableHead)(({ theme }) => ({
},
}));
export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => {
export const ClaimsArea = ({ chainId, address, epoch }) => {
const isSmallScreen = useMediaQuery("(max-width: 745px)");
const { breakoutFromStaking } = useBreakoutModal();
@ -70,17 +70,7 @@ export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => {
const claimableBalance = useMemo(() => {
if (isNetworkLegacy(chainId)) {
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
);
return isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares;
}
const toClaim = new DecimalBigNumber(claim.shares, 18);
return isPayoutGhst ? toClaim : toClaim.mul(currentIndex);
@ -118,7 +108,7 @@ export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => {
if (claim.shares === 0n) return <></>;
const warmupTooltip = `Claim earns rebases during warm-up. You can emergency withdraw, but this forfeits the rebases`;
const warmupTooltip = `Your claim earns rebases during warm-up. You can emergency withdraw, but this forfeits the rebases`;
return (
<>
@ -144,7 +134,7 @@ export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => {
justifyContent="space-between"
flexDirection={isSmallScreen ? "column" : "row"}
>
<Typography variant="h6">My active {isPayoutGhst ? ghstSymbol : stnkSymbol} claim</Typography>
<Typography variant="h6">Your active {isPayoutGhst ? ghstSymbol : stnkSymbol} claim</Typography>
</Box>
}
tooltip={warmupTooltip}
@ -174,7 +164,6 @@ export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => {
</TableRow>
</StyledTableHeader>
<ClaimInfo
chainSymbol={chainSymbol}
setConfirmationModalOpen={setConfirmationModalOpen}
prepareBalance={claimableBalance}
isPayoutGhst={isPayoutGhst}
@ -195,7 +184,6 @@ export const ClaimsArea = ({ chainId, address, chainSymbol, epoch }) => {
};
const ClaimInfo = ({
chainSymbol,
setConfirmationModalOpen,
prepareBalance,
claim,
@ -212,10 +200,7 @@ const ClaimInfo = ({
<TableRow>
<TableCell style={{ padding: "8px 8px 8px 0" }}>
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
<Token
chainTokenName={chainSymbol}
name={isPayoutGhst ? ghstSymbol : stnkSymbol}
/>
<Token key={isPayoutGhst ? ghstSymbol : stnkSymbol} name={isPayoutGhst ? ghstSymbol : stnkSymbol} />
<Box marginLeft="14px" marginRight="10px">
<Typography>{isPayoutGhst ? ghstSymbol : stnkSymbol}</Typography>
</Box>

View File

@ -23,7 +23,7 @@ import { useTotalSupply, useTokenSymbol } from "../../../hooks/tokens";
import { EMPTY_ADDRESS, FTSO_ADDRESSES } from "../../../constants/addresses";
const FarmPools = ({ chainId, chainSymbol }) => {
const FarmPools = ({ chainId }) => {
const isSmallScreen = useMediaQuery("(max-width: 775px)");
const { network } = useParams();
@ -35,9 +35,8 @@ const FarmPools = ({ chainId, chainSymbol }) => {
const pools = [
{
icons: [tokenNameConverter(chainId, reserveSymbol), "FTSO"],
chainTokenNames: [undefined, chainSymbol],
name: `${reserveSymbol}-${ftsoSymbol}`,
icons: ["FTSO", tokenNameConverter(chainId, reserveSymbol)],
name: `${ftsoSymbol}-${reserveSymbol}`,
dex: "Uniswap V2",
url: `/${network}/dex/uniswap`,
tvl: reserveFtsoUniValuation,
@ -102,7 +101,7 @@ const FarmPoolCard = ({ id, pool }) => {
<Box id={id + `--bond`}>
<Box display="flex" alignItems="center" flexDirection="column" gap="20px">
<Box display="flex" alignItems="center" gap="20px">
<TokenStack chainTokenNames={pool.chainTokenNames} tokens={pool.icons} />
<TokenStack tokens={pool.icons} />
<Typography>{pool.name}</Typography>
</Box>
@ -128,7 +127,7 @@ const FarmPoolRow = ({ id, pool }) => {
<TableRow key={id} id={id + `--pool`} data-testid={id + `--pool`}>
<TableCell style={{ padding: "8px 0" }}>
<Box display="flex" alignItems="center" gap="20px">
<TokenStack chainTokenNames={pool.chainTokenNames} tokens={pool.icons} />
<TokenStack tokens={pool.icons} />
<Typography>{pool.name}</Typography>
</Box>
</TableCell>

View File

@ -5,7 +5,6 @@ import { useAccount } from "wagmi";
import { StakeInputArea } from "./StakeInputArea";
export const StakeArea = ({
chainSymbol,
upperToken,
setUpperToken,
bottomToken,
@ -20,7 +19,6 @@ export const StakeArea = ({
return (
<Box width="100%">
<StakeInputArea
chainSymbol={chainSymbol}
upperToken={upperToken}
setUpperToken={setUpperToken}
bottomToken={bottomToken}

View File

@ -7,9 +7,8 @@ import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
import GhostStyledIcon from "../../../components/Icon/GhostIcon";
import Modal from "../../../components/Modal/Modal";
import Metric from "../../../components/Metric/Metric";
import Token from "../../../components/Token/Token";
import { PrimaryButton, SecondaryButton } from "../../../components/Button";
import Metric from "../../../components/Metric/Metric";
import { TokenAllowanceGuard } from "../../../components/TokenAllowanceGuard/TokenAllowanceGuard";
import { useWarmupLength, stake, unstake, wrap, unwrap } from "../../../hooks/staking";
@ -74,7 +73,7 @@ const StakeConfirmationModal = (props) => {
const actionAmount = new DecimalBigNumber(props.amount, props.spendDecimals);
let isRebase = false;
switch (props.action.toUpperCase()) {
switch (props.action) {
case "STAKE":
isRebase = props.bottomToken === props.stnkSymbol;
await stake(
@ -129,8 +128,11 @@ const StakeConfirmationModal = (props) => {
<Modal
data-testid="stake-confirmation-modal"
maxWidth="476px"
topLeft={<></>}
headerContent={
<Typography variant="h4">{`Confirm ${props.action}`}</Typography>
<Box display="flex" flexDirection="row">
<Typography variant="h5">{`Confirm ${props.action}`}</Typography>
</Box>
}
open={props.open}
onClose={() => isPending ? {} : props.onClose()}
@ -138,25 +140,15 @@ const StakeConfirmationModal = (props) => {
>
<Box display="flex" flexDirection="column">
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
<Box height="170px" display="flex" flexDirection="column">
<Box display="flex" flexDirection="column">
<Metric
label={`Assets to Spend`}
metric={formatNumber(new DecimalBigNumber(props.amount, props.spendDecimals), 5)}
/>
<Box display="flex" flexDirection="column" justifyContent="center" alignItems="center">
<Token
parentSx={{
height: "80px",
"& svg:nth-of-type(2)": {
transform: "translate(50%, -30%)",
zIndex: 100,
}
}}
sx={{ transform: "scale(1.65)", }}
chainTokenName={props.chainSymbol}
name={props.upperToken}
/>
<Typography>{props.upperToken}</Typography>
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>
{props.upperToken}
</Typography>
</Box>
</Box>
<GhostStyledIcon component={ArrowRightIcon} />
@ -165,25 +157,15 @@ const StakeConfirmationModal = (props) => {
label="Assets to Receive"
metric={formatNumber(new DecimalBigNumber(props.receiveAmount, props.receiveDecimals), 5)}
/>
<Box display="flex" flexDirection="column" justifyContent="center" alignItems="center">
<Token
parentSx={{
height: "80px",
"& svg:nth-of-type(2)": {
transform: "translate(50%, -30%)",
zIndex: 100,
}
}}
sx={{ transform: "scale(1.65)", }}
chainTokenName={props.chainSymbol}
name={props.upperToken === props.ftsoSymbol ? props.ghstSymbol : props.ftsoSymbol}
/>
<Typography>{props.bottomToken}</Typography>
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>
{props.bottomToken}
</Typography>
</Box>
</Box>
</Box>
<Box sx={{ marginTop: "1.5rem" }}>
<Box sx={{ marginTop: "2rem" }}>
{acknowledgedWarmup || props.action !== "STAKE" ?
<TokenAllowanceGuard
spendAmount={new DecimalBigNumber(props.amount, props.spendDecimals)}

View File

@ -9,7 +9,7 @@ const StakeInfoText = () => {
fontSize="0.875em"
lineHeight="15px"
>
Staking generates rebase yields governed by ghostDAO monetary policy and backed by bonds, Protocol Owned Liquidity (POL), and allocators.
Staking drives value accrual, rewarding stakers with rebase yields that fluctuate based on ghostDAO monetary policy and are backed by bond proceeds.
&nbsp;<Link
color={theme.colors.primary[300]}
href="https://ghostchain.io/ghostdao_litepaper"

View File

@ -68,7 +68,6 @@ const StyledBox = styled(Box)(({ theme }) => ({
}));
export const StakeInputArea = ({
chainSymbol,
upperToken,
setUpperToken,
bottomToken,
@ -199,7 +198,7 @@ export const StakeInputArea = ({
id={`${tokenName.toLowerCase()}-input`}
token={tokenName}
tokenName={realTokenName}
chainTokenName={chainSymbol}
tokenOnClick={() => handleModal(true)}
inputProps={{ "data-testid": `${tokenName.toLowerCase()}-input`, min: "0" }}
value={tokenAmount}
onChange={event => setAmount(event.target.value)}
@ -241,7 +240,11 @@ export const StakeInputArea = ({
loading={false}
disabled={exceedsAmount}
>
{exceedsAmount ? "Exceeds amount" : action }
{exceedsAmount ?
"Exceeds amount"
:
action[0] + String(action.toLowerCase()).slice(1)
}
</PrimaryButton>
</Box>
</Box>
@ -258,7 +261,6 @@ export const StakeInputArea = ({
onTriggerRebaseChange={setIsTriggerInner}
/>
<StakeConfirmationModal
chainSymbol={chainSymbol}
open={confirmationModalOpen}
onClose={() => closeAndUpdate()}
chainId={chainId}

View File

@ -82,7 +82,7 @@ const TreasuryDashboard = ({ chainId }) => {
return (
<>
<PageTitle name="Protocol Overview" subtitle="Confirm protocol health by monitoring supply and reserves" />
<PageTitle name="Protocol Metrics" subtitle="Confirm protocol health by auditing supply and reserves" />
<Container
style={{
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",

View File

@ -116,7 +116,7 @@ const ProtocolDetails = ({ chainId, isMobileScreen, theme, }) => {
theme={theme}
url={`/${networkName.toLowerCase()}/stake`}
name="(3, 3) Stake"
sideName={`${formatNumber(apyInner, 2)}% APY`}
sideName={`${formatNumber(apyInner, 0)}% 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, 2)}% APY`}
sideName={`${formatNumber(gatekeepedApy, 0)}% 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.`}
/>
</Box>

View File

@ -16,7 +16,6 @@ import { useTokenSymbol, useTokenSymbols } from "../tokens";
import {
getTokenAddress,
getTokenIcons,
getChainTokenNames,
getBondNameDisplayName,
getTokenPurchaseLink,
executeOnChainTransaction
@ -124,7 +123,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)
@ -163,15 +162,13 @@ 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,
},
@ -192,7 +189,7 @@ export const useLiveBonds = (chainId, chainName) => {
inBaseToken: maxPayoutInBaseToken,
inQuoteToken: maxPayoutInQuoteToken,
},
}
};
}).sort((a, b) => (a.id > b.id ? -1 : 1)) : [];
return { liveBonds, refetch };
}
@ -258,7 +255,6 @@ 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,

View File

@ -174,7 +174,7 @@ export const getTokenIcons = (chainId, address) => {
icons = ["GHST"];
break;
case FTSO_DAI_LP_ADDRESSES[chainId]:
icons = ["WETH", "FTSO"];
icons = ["FTSO", "WETH"];
break;
default:
icons = [""]
@ -182,21 +182,6 @@ 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()) {

View File

@ -173,8 +173,3 @@ input:-webkit-autofill {
color: #ffffff !important;
-webkit-text-fill-color: #ffffff !important;
}
@keyframes spinTokenIcon {
from { transform: rotate(360deg); }
to { transform: rotate(0deg); }
}