Compare commits

..

No commits in common. "421f2cef27eff871827b513053ee8641c3974c42" and "3f9003883d50a316b69ecda150f1c57aba48e83b" have entirely different histories.

13 changed files with 187 additions and 260 deletions

View File

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

View File

@ -160,7 +160,7 @@ function App() {
setWrongNetworkToastId(null);
}
}
}, [chainId, addressChainId, isConnected, wrongNetworkToastId])
}, [chainId, addressChainId, isConnected])
useEffect(() => {
if (errorMessage) {
@ -215,7 +215,7 @@ function App() {
<Route path="/:network" element={<AvailableNetworkGuard allowedNetworks={chains.map(chain => chain.name.toLowerCase())} /> }>
<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="bonds/:id" element={<BondModalContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
<Route path="stake" element={<StakeContainer connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
<Route path="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} />} />

View File

@ -144,9 +144,9 @@ const NavContent = ({ chainId, addressChainId }) => {
to={`/${chainName}/bonds`}
children={
<AccordionDetails style={{ margin: "0 0 -20px", display: "flex", flexDirection: "column", gap: "10px" }}>
{ghostBonds.length > 0 && <Box width="180px" mb="10px" ml="auto">
<Box width="180px" mb="10px" ml="auto">
<Typography component="span" variant="body2">Bond Discounts</Typography>
</Box>}
</Box>
{sortBondsByDiscount(ghostBonds).map((bond, index) => {
return (
<Link
@ -192,8 +192,8 @@ const NavContent = ({ chainId, addressChainId }) => {
</div>
<Box>
<NavItem href="https://ghostchain.io/game-theory-3-3" icon={CasinoIcon} label={`${bridgeNumbers} Game Theory`} />
<NavItem href="http://ecosystem.ghostchain.io" icon={PublicIcon} label={`Ecosystem`} />
<NavItem href="https://ghostchain.io/game-theory-3-3" icon={CasinoIcon} label={`(3, 3) Game Theory`} />
<NavItem href="https://docs.ghostchain.io/" icon={BookIcon} label={`Documentation`} />
<StyledBox display="flex" justifyContent="space-around" paddingY="24px">
<Link href="https://git.ghostchain.io/ghostchain/ghost-dao-contracts" target="_blank" rel="noopener noreferrer">

View File

@ -12,8 +12,8 @@ import { isNetworkAvailable } from "../../constants";
import { parseKnownToken } from "../../components/Token/Token";
import { useSwitchChain } from 'wagmi';
import { useNavigate, useLocation } from 'react-router-dom';
import toast from "react-hot-toast";
import { useNavigate, useLocation } from 'react-router-dom';
function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, small }) {
const theme = useTheme();
@ -25,43 +25,29 @@ function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, s
const [networkId, setNetworkId] = useState(chainId);
useEffect(() => {
const parts = pathname.split('/');
if (parts.length > 2) {
let targetChain = chains.at(0);
const chainName = parts[1].toLowerCase();
const chain = chains.find(chain => chain.name.toLowerCase() === chainName);
if (chain && targetChain.name !== chain.name) {
targetChain = chain;
}
changeNetworkId(targetChain.name, targetChain.id)
}
}, [])
if (chainId !== networkId) setNetworkId(chainId);
}, [chainId])
useEffect(() => {
if (chainId !== networkId) setNetworkId(chainId);
}, [chainId, networkId])
const chainName = chains.find((chain) => chain.id === chainId).name;
const parts = pathname.split('/');
if (parts.length > 2) {
parts[1] = chainName.toLowerCase();
const newPath = parts.join("/");
navigate(newPath);
}
}, [chains, chainId])
const changeNetworkId = (chainName, newNetworkId) => {
const handleChange = (event) => {
const chainName = chains.find((chain) => chain.id === event.target.value).name;
toast.dismiss(wrongNetworkToastId);
const toastId = toast.loading(`Trying to connect to ${chainName} network... Wait please`, {
position: 'bottom-right'
});
setWrongNetworkToastId(toastId);
setNetworkId(newNetworkId);
switchChain({ chainId: newNetworkId });
}
const handleChange = (event) => {
const chainName = chains.find((chain) => chain.id === event.target.value).name;
changeNetworkId(chainName, event.target.value);
const parts = pathname.split('/');
if (parts.length > 2) {
parts[1] = chainName.toLowerCase();
const newPath = parts.join("/");
navigate(newPath, { replace: true });
}
setNetworkId(event.target.value);
switchChain({ chainId: event.target.value });
}
return(

View File

@ -18,24 +18,24 @@ import BondSettingsModal from "./components/BondSettingsModal";
import NotFound from "../NotFound/NotFound";
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { isNetworkLegacy } from "../../constants";
import { NetworkId } from "../../constants";
import { formatCurrency } from "../../helpers";
import { useLocalStorage } from "../../hooks/localstorage";
import { useLiveBonds } from "../../hooks/bonds";
import { useFtsoPrice } from "../../hooks/prices";
const BondModalContainer = ({ chainId, address, config, connect }) => {
const BondModalContainer = ({ chainId, address, connect }) => {
const { id, network } = useParams();
const { liveBonds } = useLiveBonds(chainId, network);
const bond = liveBonds.find(bond => bond.id === Number(id));
if (!bond) return <NotFound />;
return <BondModal config={config} chainId={chainId} bond={bond} address={address} connect={connect} />;
return <BondModal chainId={chainId} bond={bond} address={address} connect={connect} />;
};
export const BondModal = ({ bond, chainId, address, config, connect }) => {
export const BondModal = ({ bond, chainId, address, connect }) => {
const navigate = useNavigate();
const { network } = useParams();
const { pathname } = useLocation();
@ -81,23 +81,6 @@ export const BondModal = ({ bond, chainId, address, config, connect }) => {
return () => window.removeEventListener("keydown", handleKeyDown);
}, [network, navigate, isSettingsOpen]);
const chainSymbol = useMemo(() => {
const chainSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
if (chainSymbol) return chainSymbol;
return "WTF";
}, [config]);
const preparedQuoteToken = useMemo(() => {
if (isNetworkLegacy(chainId)) {
return {
address: bond.quoteToken.quoteTokenAddress,
icons: bond.quoteToken.icons,
name: bond.quoteToken.name,
}
}
return { address: undefined, icons: [chainSymbol], name: chainSymbol };
}, [bond, chainSymbol, chainId])
return (
<Box>
<PageTitle
@ -112,10 +95,10 @@ export const BondModal = ({ bond, chainId, address, config, connect }) => {
</Box>
</Link>
<TokenStack tokens={preparedQuoteToken.icons} sx={{ fontSize: "27px" }} />
<TokenStack tokens={bond.quoteToken.icons} sx={{ fontSize: "27px" }} />
<Box display="flex" flexDirection="column" ml={1} justifyContent="center" alignItems="center">
<Typography variant="h4" fontWeight={500}>
{preparedQuoteToken.name}
{bond.quoteToken.name}
</Typography>
</Box>
</Box>
@ -161,12 +144,10 @@ export const BondModal = ({ bond, chainId, address, config, connect }) => {
<BondInputArea
chainId={chainId}
bond={bond}
config={config}
connect={connect}
address={address}
slippage={slippage}
recipientAddress={recipientAddress}
preparedQuoteToken={preparedQuoteToken}
handleSettingsOpen={() => setSettingsOpen(true)}
formatDecimals={formatDecimals}
/>

View File

@ -37,9 +37,6 @@ const BondConfirmModal = ({
sender,
handleSettingsOpen,
isOpen,
isNative,
bondQuoteTokenName,
bondQuoteTokenIcons,
handleConfirmClose
}) => {
const theme = useTheme();
@ -56,16 +53,15 @@ const BondConfirmModal = ({
const maxPrice = bond.price.inBaseToken._value * bigIntSlippage / one;
const referral = import.meta.env.VITE_APP_REFERRAL_ADDRESS;
await purchaseBond({
await purchaseBond(
chainId,
bondId: bond.id,
amount: spendAmountValue._value.toBigInt(),
bond.id,
spendAmountValue._value.toBigInt(),
maxPrice,
user: recipientAddress,
recipientAddress,
sender,
referral,
isNative
});
referral
);
setIsPending(false);
handleConfirmClose();
@ -78,9 +74,9 @@ const BondConfirmModal = ({
open={isOpen}
headerContent={
<Box display="flex" flexDirection="row">
<TokenStack tokens={bondQuoteTokenIcons} sx={{ fontSize: "27px" }} />
<TokenStack tokens={bond.quoteToken.icons} sx={{ fontSize: "27px" }} />
<Typography variant="h4" sx={{ marginLeft: "6px" }}>
{bondQuoteTokenName}
{bond.quoteToken.name}
</Typography>
</Box>
}
@ -95,7 +91,7 @@ const BondConfirmModal = ({
metric={spendAmount}
/>
<Box display="flex" flexDirection="row" justifyContent="center">
<Typography>{bondQuoteTokenName}</Typography>
<Typography>{bond.quoteToken.name}</Typography>
</Box>
</Box>
<GhostStyledIcon sx={{ transform: "rotate(-90deg)" }} component={ArrowDropDownIcon} />

View File

@ -30,7 +30,6 @@ const BondInputArea = ({
formatDecimals,
handleSettingsOpen,
address,
preparedQuoteToken,
connect
}) => {
const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
@ -38,7 +37,7 @@ const BondInputArea = ({
const { pathname } = useLocation();
const { currentIndex } = useCurrentIndex(chainId);
const { balance, refetch } = useBalance(chainId, preparedQuoteToken.address, address);
const { balance, refetch } = useBalance(chainId, bond.quoteToken.quoteTokenAddress, address);
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
@ -101,14 +100,15 @@ const BondInputArea = ({
inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
id="from"
token={<TokenStack tokens={bond.quoteToken.icons} sx={{ fontSize: "21px" }} />}
tokenName={preparedQuoteToken.name}
info={formatCurrency(balance, formatDecimals, preparedQuoteToken.name)}
endString={preparedQuoteToken.address && "Max"}
tokenName={bond.quoteToken.name}
info={formatCurrency(balance, formatDecimals, bond.quoteToken.name)}
endString="Max"
endStringOnClick={setMax}
value={amount}
onChange={event => setAmount(event.currentTarget.value)}
inputProps={{ "data-testid": "fromInput" }}
/>}
/>
}
LowerSwapCard={
<SwapCard
maxWidth="476px"
@ -134,7 +134,6 @@ const BondInputArea = ({
connect={connect}
width="100%"
height="60px"
isNative={preparedQuoteToken.address === undefined}
isVertical
message={
<>
@ -222,9 +221,6 @@ const BondInputArea = ({
spendAmountValue={parsedAmount}
spendAmount={formatNumber(parsedAmount, formatDecimals)}
receiveAmount={formatNumber(amountInBaseToken, formatDecimals)}
bondQuoteTokenName={preparedQuoteToken.name}
bondQuoteTokenIcons={preparedQuoteToken.icons}
isNative={preparedQuoteToken.address === undefined}
handleSettingsOpen={handleSettingsOpen}
isOpen={confirmOpen}
sender={address}

View File

@ -132,10 +132,9 @@ const BondCard = ({ bond, secondsTo, chainName }) => {
<Link
component={NavLink}
to={`/${chainName}/bonds/${bond.id}`}
sx={{ pointerEvents: bond.isSoldOut ? 'none' : 'auto' }}
>
<TertiaryButton fullWidth disabled={bond.isSoldOut}>
{bond.isSoldOut ? "Sold Out" : `Bond`}
<TertiaryButton fullWidth>
Bond
</TertiaryButton>
</Link>
</Box>
@ -224,7 +223,6 @@ const BondRow = ({ bond, secondsTo, chainName }) => {
<Link
component={NavLink}
to={`/${chainName}/bonds/${bond.id}`}
sx={{ pointerEvents: bond.isSoldOut ? 'none' : 'auto' }}
>
<TertiaryButton fullWidth disabled={bond.isSoldOut}>
{bond.isSoldOut ? "Sold Out" : `Bond`}

View File

@ -56,12 +56,12 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
setIsWapmup(true);
} else {
setIsPending(true);
await redeem({
await redeem(
chainId,
user: address,
isGhst: isPayoutGhst,
address,
isPayoutGhst,
indexes
});
);
await notesRefetch();
setIsPending(false);
}
@ -99,9 +99,8 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
? formatCurrency(totalClaimableBalance, 5, ghstSymbol)
: formatCurrency(currentIndex.mul(totalClaimableBalance), 5, stnkSymbol)
}
</Typography>
<Typography variant="subtitle1" align="center">
{formatCurrency(totalClaimableBalance * ghstPrice, 2)}
&nbsp;
({formatCurrency(totalClaimableBalance * ghstPrice, 2)})
</Typography>
</Box>

View File

@ -31,6 +31,7 @@ export default function NotFound({
});
setWrongNetworkToastId(toastId);
setNetworkId(newChainId);
switchChain({ chainId: newChainId });
}

View File

@ -28,8 +28,7 @@ import { formatNumber, formatCurrency } from "../../../helpers";
import { STAKING_ADDRESSES } from "../../../constants/addresses";
import { useCurrentIndex, useWarmupInfo } from "../../../hooks/staking";
import { useBalanceForShares, useTokenSymbol } from "../../../hooks/tokens";
import { useGhstPrice, useStnkPrice } from "../../../hooks/prices";
import { isNetworkLegacy } from "../../../constants";
import { useGhstPrice } from "../../../hooks/prices";
import ClaimConfirmationModal from "./ClaimConfirmationModal";
@ -56,8 +55,6 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
const [isPayoutGhst, _] = useState(true);
const ghstPrice = useGhstPrice(chainId);
const stnkPrice = useStnkPrice(chainId);
const { warmupInfo: claim, refetch: claimRefetch } = useWarmupInfo(chainId, address);
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
const { balanceForShares } = useBalanceForShares(chainId, "STNK", claim.shares);
@ -66,14 +63,6 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
const claimableBalance = useMemo(() => {
if (isNetworkLegacy(chainId)) {
return isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares;
}
const toClaim = new DecimalBigNumber(claim.shares, 18);
return isPayoutGhst ? toClaim : toClaim.mul(currentIndex);
}, [chainId, claim, currentIndex, balanceForShares]);
const closeConfirmationModal = () => {
setConfirmationModalOpen(false);
claimRefetch();
@ -91,7 +80,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
onClose={() => closeConfirmationModal()}
chainid={chainId}
receiver={address}
receiveAmount={claim.expiry > epoch.number ? claim.deposit : claimableBalance}
receiveAmount={claim.expiry > epoch.number ? claim.deposit : isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
outputToken={claim.expiry > epoch.number ? ftsoSymbol : isPayoutGhst ? ghstSymbol : stnkSymbol}
stnkSymbol={stnkSymbol}
ghstSymbol={ghstSymbol}
@ -118,35 +107,34 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
{isSmallScreen ? (
<MobileClaimInfo
setConfirmationModalOpen={setConfirmationModalOpen}
prepareBalance={claimableBalance}
prepareBalance={isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
isPayoutGhst={isPayoutGhst}
claim={claim}
epoch={epoch}
isClaimable={claim.expiry > epoch.number}
stnkSymbol={stnkSymbol}
ghstSymbol={ghstSymbol}
tokenPrice={isPayoutGhst ? ghstPrice : stnkPrice}
/>
) : (
<Table>
<StyledTableHeader className={classes.stakePoolHeaderText}>
<TableRow>
<TableCell style={{ width: "200px", padding: "8px 0" }}>Asset</TableCell>
<TableCell style={{ width: "200px", padding: "8px 0" }}>Staked Amount</TableCell>
<TableCell style={{ width: "200px", padding: "8px 0" }}>Amount</TableCell>
<TableCell style={{ width: "150px", padding: "8px 0" }}>Claimable In</TableCell>
<TableCell></TableCell>
</TableRow>
</StyledTableHeader>
<ClaimInfo
setConfirmationModalOpen={setConfirmationModalOpen}
prepareBalance={claimableBalance}
prepareBalance={isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
isPayoutGhst={isPayoutGhst}
claim={claim}
epoch={epoch}
isClaimable={claim.expiry > epoch.number}
stnkSymbol={stnkSymbol}
ghstSymbol={ghstSymbol}
tokenPrice={isPayoutGhst ? ghstPrice : stnkPrice}
ghstPrice={ghstPrice}
/>
</Table>
@ -165,7 +153,7 @@ const ClaimInfo = ({
isPayoutGhst,
stnkSymbol,
ghstSymbol,
tokenPrice
ghstPrice
}) => {
return (
<TableBody>
@ -183,7 +171,7 @@ const ClaimInfo = ({
{formatCurrency(prepareBalance, 5, isPayoutGhst ? ghstSymbol : stnkSymbol)}
</Typography>
<Typography variant="body2" gutterBottom={false} style={{ lineHeight: 1.4 }}>
{formatCurrency(prepareBalance * tokenPrice, 2)}
{formatCurrency(prepareBalance * ghstPrice, 2)}
</Typography>
</TableCell>
<TableCell style={{ padding: "8px 8px 8px 0" }}>
@ -200,17 +188,7 @@ const ClaimInfo = ({
);
};
const MobileClaimInfo = ({
setConfirmationModalOpen,
prepareBalance,
epoch,
claim,
isPayoutGhst,
isClaimable,
ghstSymbol,
stnkSymbol,
tokenPrice,
}) => {
const MobileClaimInfo = ({ setConfirmationModalOpen, prepareBalance, epoch, claim, isPayoutGhst, isClaimable, ghstSymbol, stnkSymbol }) => {
return (
<Box mt="10px">
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
@ -221,15 +199,10 @@ const MobileClaimInfo = ({
</Box>
<DataRow
title="Staked Amount"
title="Amount"
balance={formatNumber(prepareBalance, 7)}
/>
<DataRow
title="Price Estimation"
balance={formatCurrency(prepareBalance * tokenPrice, 2)}
/>
<DataRow
title="Claimed in"
balance={prettifySecondsInDays(epoch.length * (claim.expiry - epoch.number))}

View File

@ -151,11 +151,12 @@ export const useLiveBonds = (chainId, chainName) => {
);
const zero = new DecimalBigNumber(0n, 0);
const bondName = `${baseTokenSymbol}/${tokenNameConverter(chainId, "WETH")}`;
return {
id,
discount,
displayName: getBondNameDisplayName(chainId, quoteTokenAddress, baseTokenSymbol),
displayName: getBondNameDisplayName(chainId, bondName, quoteTokenAddress),
baseToken: {
name: baseTokenSymbol,
purchaseUrl: getTokenPurchaseLink(chainId, "", chainName),
@ -266,7 +267,7 @@ export const useNotes = (chainId, address) => {
return { notes, refetch };
}
export const purchaseBond = async ({ chainId, bondId, amount, maxPrice, user, sender, referral, isNative }) => {
export const purchaseBond = async (chainId, bondId, amount, maxPrice, user, sender, referral) => {
const args = [
bondId,
amount,
@ -284,12 +285,11 @@ export const purchaseBond = async ({ chainId, bondId, amount, maxPrice, user, se
"deposit",
args,
sender,
messages,
isNative ? amount : undefined
messages
);
}
export const redeem = async ({ chainId, user, isGhst, indexes }) => {
export const redeem = async (chainId, user, isGhst, indexes) => {
const args = [
user,
isGhst,
@ -314,8 +314,7 @@ const executeOnChainTransaction = async (
functionName,
args,
account,
messages,
value
messages
) => {
try {
const { request } = await simulateContract(config, {
@ -326,7 +325,6 @@ const executeOnChainTransaction = async (
account,
chainId,
type: isNetworkLegacyType(chainId) ? 'legacy' : 'eip1559',
value: value,
});
const txHash = await writeContract(config, request);

View File

@ -178,10 +178,9 @@ export const getTokenIcons = (chainId, address) => {
return icons;
}
export const getBondNameDisplayName = (chainId, tokenAddress, baseTokenSymbol) => {
let stringValue = tokenNameConverter(chainId, "WETH")
export const getBondNameDisplayName = (chainId, stringValue, tokenAddress) => {
if (tokenAddress.toUpperCase() === FTSO_DAI_LP_ADDRESSES[chainId].toUpperCase()) {
stringValue = `${baseTokenSymbol}-${stringValue} LP`;
stringValue = `${stringValue} LP`;
}
return stringValue;
}