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", "name": "ghost-dao-interface",
"private": true, "private": true,
"version": "0.7.5", "version": "0.7.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

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

View File

@ -144,9 +144,9 @@ const NavContent = ({ chainId, addressChainId }) => {
to={`/${chainName}/bonds`} to={`/${chainName}/bonds`}
children={ children={
<AccordionDetails style={{ margin: "0 0 -20px", display: "flex", flexDirection: "column", gap: "10px" }}> <AccordionDetails style={{ margin: "0 0 -20px", display: "flex", flexDirection: "column", gap: "10px" }}>
{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> <Typography component="span" variant="body2">Bond Discounts</Typography>
</Box>} </Box>
{sortBondsByDiscount(ghostBonds).map((bond, index) => { {sortBondsByDiscount(ghostBonds).map((bond, index) => {
return ( return (
<Link <Link
@ -192,8 +192,8 @@ const NavContent = ({ chainId, addressChainId }) => {
</div> </div>
<Box> <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="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`} /> <NavItem href="https://docs.ghostchain.io/" icon={BookIcon} label={`Documentation`} />
<StyledBox display="flex" justifyContent="space-around" paddingY="24px"> <StyledBox display="flex" justifyContent="space-around" paddingY="24px">
<Link href="https://git.ghostchain.io/ghostchain/ghost-dao-contracts" target="_blank" rel="noopener noreferrer"> <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 { parseKnownToken } from "../../components/Token/Token";
import { useSwitchChain } from 'wagmi'; import { useSwitchChain } from 'wagmi';
import { useNavigate, useLocation } from 'react-router-dom';
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { useNavigate, useLocation } from 'react-router-dom';
function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, small }) { function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, small }) {
const theme = useTheme(); const theme = useTheme();
@ -25,43 +25,29 @@ function SelectNetwork({ chainId, wrongNetworkToastId, setWrongNetworkToastId, s
const [networkId, setNetworkId] = useState(chainId); const [networkId, setNetworkId] = useState(chainId);
useEffect(() => { useEffect(() => {
const parts = pathname.split('/'); if (chainId !== networkId) setNetworkId(chainId);
if (parts.length > 2) { }, [chainId])
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)
}
}, [])
useEffect(() => { useEffect(() => {
if (chainId !== networkId) setNetworkId(chainId); const chainName = chains.find((chain) => chain.id === chainId).name;
}, [chainId, networkId]) 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); toast.dismiss(wrongNetworkToastId);
const toastId = toast.loading(`Trying to connect to ${chainName} network... Wait please`, { const toastId = toast.loading(`Trying to connect to ${chainName} network... Wait please`, {
position: 'bottom-right' position: 'bottom-right'
}); });
setWrongNetworkToastId(toastId); setWrongNetworkToastId(toastId);
setNetworkId(newNetworkId); setNetworkId(event.target.value);
switchChain({ chainId: newNetworkId }); switchChain({ chainId: event.target.value });
}
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 });
}
} }
return( return(

View File

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

View File

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

View File

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

View File

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

View File

@ -56,12 +56,12 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
setIsWapmup(true); setIsWapmup(true);
} else { } else {
setIsPending(true); setIsPending(true);
await redeem({ await redeem(
chainId, chainId,
user: address, address,
isGhst: isPayoutGhst, isPayoutGhst,
indexes indexes
}); );
await notesRefetch(); await notesRefetch();
setIsPending(false); setIsPending(false);
} }
@ -99,137 +99,136 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
? formatCurrency(totalClaimableBalance, 5, ghstSymbol) ? formatCurrency(totalClaimableBalance, 5, ghstSymbol)
: formatCurrency(currentIndex.mul(totalClaimableBalance), 5, stnkSymbol) : formatCurrency(currentIndex.mul(totalClaimableBalance), 5, stnkSymbol)
} }
</Typography> &nbsp;
<Typography variant="subtitle1" align="center"> ({formatCurrency(totalClaimableBalance * ghstPrice, 2)})
{formatCurrency(totalClaimableBalance * ghstPrice, 2)} </Typography>
</Typography> </Box>
<PrimaryButton
disabled={isPending || totalClaimableBalance._value === 0n}
fullWidth
className=""
onClick={() => onSubmit(notes.filter((note) => secondsTo > note.matured).map(note => note.id))}
>
Claim All
</PrimaryButton>
</Box> </Box>
<PrimaryButton
disabled={isPending || totalClaimableBalance._value === 0n}
fullWidth
className=""
onClick={() => onSubmit(notes.filter((note) => secondsTo > note.matured).map(note => note.id))}
>
Claim All
</PrimaryButton>
</Box> </Box>
</Box>
<Box mt="48px"> <Box mt="48px">
{isSmallScreen ? ( {isSmallScreen ? (
<> <>
{notes.map((note, index) => ( {notes.map((note, index) => (
<Box key={index} mt="32px"> <Box key={index} mt="32px">
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">
<TokenStack tokens={note.quoteToken.icons} /> <TokenStack tokens={note.quoteToken.icons} />
<Box ml="8px"> <Box ml="8px">
<Typography>{note.quoteToken.name}</Typography> <Typography>{note.quoteToken.name}</Typography>
</Box>
</Box> </Box>
</Box>
<Box display="flex" justifyContent="space-between" mt="16px"> <Box display="flex" justifyContent="space-between" mt="16px">
<Typography>Duration</Typography> <Typography>Duration</Typography>
<Typography>
<BondVesting vesting={note.vesting} />
</Typography>
</Box>
<Box display="flex" justifyContent="space-between" mt="8px">
<Typography>Remaining</Typography>
<Typography>
<BondDuration msg="Matured" secondsTo={secondsTo} duration={note.matured} />
</Typography>
</Box>
<Box display="flex" justifyContent="space-between" mt="8px">
<Typography>Payout</Typography>
<Box display="flex" flexDirection="column" alignItems="flex-end">
<Typography> <Typography>
{isPayoutGhst <BondVesting vesting={note.vesting} />
? formatCurrency(note.payout, 5, ghstSymbol)
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
}
</Typography> </Typography>
<Typography>{formatCurrency(note.payout * ghstPrice, 2)}</Typography> </Box>
<Box display="flex" justifyContent="space-between" mt="8px">
<Typography>Remaining</Typography>
<Typography>
<BondDuration msg="Matured" secondsTo={secondsTo} duration={note.matured} />
</Typography>
</Box>
<Box display="flex" justifyContent="space-between" mt="8px">
<Typography>Payout</Typography>
<Box display="flex" flexDirection="column" alignItems="flex-end">
<Typography>
{isPayoutGhst
? formatCurrency(note.payout, 5, ghstSymbol)
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
}
</Typography>
<Typography>{formatCurrency(note.payout * ghstPrice, 2)}</Typography>
</Box>
</Box>
<Box mt="16px">
<TertiaryButton
fullWidth
disabled={isPending || secondsTo < note.matured}
onClick={() => onSubmit([note.id])}
>
Claim
</TertiaryButton>
</Box> </Box>
</Box> </Box>
))}
<Box mt="16px"> </>
<TertiaryButton ) : (
fullWidth <TableContainer>
disabled={isPending || secondsTo < note.matured} <Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
onClick={() => onSubmit([note.id])} <TableHead>
> <TableRow>
Claim <TableCell style={{ width: "180px", padding: "8px 0" }}>Bond</TableCell>
</TertiaryButton> <TableCell style={{ padding: "8px 0" }}>Duration</TableCell>
</Box> <TableCell style={{ padding: "8px 0" }}>Remaining</TableCell>
</Box> <TableCell style={{ padding: "8px 0" }}>Payout</TableCell>
))}
</>
) : (
<TableContainer>
<Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
<TableHead>
<TableRow>
<TableCell style={{ width: "180px", padding: "8px 0" }}>Bond</TableCell>
<TableCell style={{ padding: "8px 0" }}>Duration</TableCell>
<TableCell style={{ padding: "8px 0" }}>Remaining</TableCell>
<TableCell style={{ padding: "8px 0" }}>Payout</TableCell>
</TableRow>
</TableHead>
<TableBody>
{notes.map((note, index) => (
<TableRow key={index}>
<TableCell style={{ padding: "8px 0" }}>
<Box display="flex" alignItems="center">
<TokenStack tokens={note.quoteToken.icons} />
<Box display="flex" flexDirection="column" ml="16px">
<Typography>{note.quoteToken.name}</Typography>
</Box>
</Box>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<Typography>
<BondVesting vesting={note.vesting} />
</Typography>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<Typography>
<BondDuration msg="Matured" secondsTo={secondsTo} duration={note.matured} />
</Typography>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<Box display="flex" flexDirection="column" alignItems="flex-start">
<Typography>
{isPayoutGhst
? formatCurrency(note.payout, 5, ghstSymbol)
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
}
</Typography>
<Typography variant="body2">{formatCurrency(note.payout * ghstPrice, 2)}</Typography>
</Box>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<TertiaryButton
fullWidth
disabled={isPending || secondsTo < note.matured}
onClick={() => onSubmit([note.id])}
>
Claim
</TertiaryButton>
</TableCell>
</TableRow> </TableRow>
))} </TableHead>
</TableBody> <TableBody>
</Table> {notes.map((note, index) => (
</TableContainer> <TableRow key={index}>
)} <TableCell style={{ padding: "8px 0" }}>
</Box> <Box display="flex" alignItems="center">
<TokenStack tokens={note.quoteToken.icons} />
<Box display="flex" flexDirection="column" ml="16px">
<Typography>{note.quoteToken.name}</Typography>
</Box>
</Box>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<Typography>
<BondVesting vesting={note.vesting} />
</Typography>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<Typography>
<BondDuration msg="Matured" secondsTo={secondsTo} duration={note.matured} />
</Typography>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<Box display="flex" flexDirection="column" alignItems="flex-start">
<Typography>
{isPayoutGhst
? formatCurrency(note.payout, 5, ghstSymbol)
: formatCurrency(currentIndex.mul(note.payout), 5, stnkSymbol)
}
</Typography>
<Typography variant="body2">{formatCurrency(note.payout * ghstPrice, 2)}</Typography>
</Box>
</TableCell>
<TableCell style={{ padding: "8px 0" }}>
<TertiaryButton
fullWidth
disabled={isPending || secondsTo < note.matured}
onClick={() => onSubmit([note.id])}
>
Claim
</TertiaryButton>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)}
</Box>
</Paper> </Paper>
</> </>
); );

View File

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

View File

@ -28,8 +28,7 @@ import { formatNumber, formatCurrency } from "../../../helpers";
import { STAKING_ADDRESSES } from "../../../constants/addresses"; import { STAKING_ADDRESSES } from "../../../constants/addresses";
import { useCurrentIndex, useWarmupInfo } from "../../../hooks/staking"; import { useCurrentIndex, useWarmupInfo } from "../../../hooks/staking";
import { useBalanceForShares, useTokenSymbol } from "../../../hooks/tokens"; import { useBalanceForShares, useTokenSymbol } from "../../../hooks/tokens";
import { useGhstPrice, useStnkPrice } from "../../../hooks/prices"; import { useGhstPrice } from "../../../hooks/prices";
import { isNetworkLegacy } from "../../../constants";
import ClaimConfirmationModal from "./ClaimConfirmationModal"; import ClaimConfirmationModal from "./ClaimConfirmationModal";
@ -56,8 +55,6 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
const [isPayoutGhst, _] = useState(true); const [isPayoutGhst, _] = useState(true);
const ghstPrice = useGhstPrice(chainId); const ghstPrice = useGhstPrice(chainId);
const stnkPrice = useStnkPrice(chainId);
const { warmupInfo: claim, refetch: claimRefetch } = useWarmupInfo(chainId, address); const { warmupInfo: claim, refetch: claimRefetch } = useWarmupInfo(chainId, address);
const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId); const { currentIndex, refetch: currentIndexRefetch } = useCurrentIndex(chainId);
const { balanceForShares } = useBalanceForShares(chainId, "STNK", claim.shares); const { balanceForShares } = useBalanceForShares(chainId, "STNK", claim.shares);
@ -66,14 +63,6 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK"); const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST"); const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
const 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 = () => { const closeConfirmationModal = () => {
setConfirmationModalOpen(false); setConfirmationModalOpen(false);
claimRefetch(); claimRefetch();
@ -91,7 +80,7 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
onClose={() => closeConfirmationModal()} onClose={() => closeConfirmationModal()}
chainid={chainId} chainid={chainId}
receiver={address} 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} outputToken={claim.expiry > epoch.number ? ftsoSymbol : isPayoutGhst ? ghstSymbol : stnkSymbol}
stnkSymbol={stnkSymbol} stnkSymbol={stnkSymbol}
ghstSymbol={ghstSymbol} ghstSymbol={ghstSymbol}
@ -118,35 +107,34 @@ export const ClaimsArea = ({ chainId, address, epoch }) => {
{isSmallScreen ? ( {isSmallScreen ? (
<MobileClaimInfo <MobileClaimInfo
setConfirmationModalOpen={setConfirmationModalOpen} setConfirmationModalOpen={setConfirmationModalOpen}
prepareBalance={claimableBalance} prepareBalance={isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
isPayoutGhst={isPayoutGhst} isPayoutGhst={isPayoutGhst}
claim={claim} claim={claim}
epoch={epoch} epoch={epoch}
isClaimable={claim.expiry > epoch.number} isClaimable={claim.expiry > epoch.number}
stnkSymbol={stnkSymbol} stnkSymbol={stnkSymbol}
ghstSymbol={ghstSymbol} ghstSymbol={ghstSymbol}
tokenPrice={isPayoutGhst ? ghstPrice : stnkPrice}
/> />
) : ( ) : (
<Table> <Table>
<StyledTableHeader className={classes.stakePoolHeaderText}> <StyledTableHeader className={classes.stakePoolHeaderText}>
<TableRow> <TableRow>
<TableCell style={{ width: "200px", padding: "8px 0" }}>Asset</TableCell> <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 style={{ width: "150px", padding: "8px 0" }}>Claimable In</TableCell>
<TableCell></TableCell> <TableCell></TableCell>
</TableRow> </TableRow>
</StyledTableHeader> </StyledTableHeader>
<ClaimInfo <ClaimInfo
setConfirmationModalOpen={setConfirmationModalOpen} setConfirmationModalOpen={setConfirmationModalOpen}
prepareBalance={claimableBalance} prepareBalance={isPayoutGhst ? balanceForShares.div(currentIndex) : balanceForShares}
isPayoutGhst={isPayoutGhst} isPayoutGhst={isPayoutGhst}
claim={claim} claim={claim}
epoch={epoch} epoch={epoch}
isClaimable={claim.expiry > epoch.number} isClaimable={claim.expiry > epoch.number}
stnkSymbol={stnkSymbol} stnkSymbol={stnkSymbol}
ghstSymbol={ghstSymbol} ghstSymbol={ghstSymbol}
tokenPrice={isPayoutGhst ? ghstPrice : stnkPrice} ghstPrice={ghstPrice}
/> />
</Table> </Table>
@ -165,7 +153,7 @@ const ClaimInfo = ({
isPayoutGhst, isPayoutGhst,
stnkSymbol, stnkSymbol,
ghstSymbol, ghstSymbol,
tokenPrice ghstPrice
}) => { }) => {
return ( return (
<TableBody> <TableBody>
@ -183,7 +171,7 @@ const ClaimInfo = ({
{formatCurrency(prepareBalance, 5, isPayoutGhst ? ghstSymbol : stnkSymbol)} {formatCurrency(prepareBalance, 5, isPayoutGhst ? ghstSymbol : stnkSymbol)}
</Typography> </Typography>
<Typography variant="body2" gutterBottom={false} style={{ lineHeight: 1.4 }}> <Typography variant="body2" gutterBottom={false} style={{ lineHeight: 1.4 }}>
{formatCurrency(prepareBalance * tokenPrice, 2)} {formatCurrency(prepareBalance * ghstPrice, 2)}
</Typography> </Typography>
</TableCell> </TableCell>
<TableCell style={{ padding: "8px 8px 8px 0" }}> <TableCell style={{ padding: "8px 8px 8px 0" }}>
@ -200,17 +188,7 @@ const ClaimInfo = ({
); );
}; };
const MobileClaimInfo = ({ const MobileClaimInfo = ({ setConfirmationModalOpen, prepareBalance, epoch, claim, isPayoutGhst, isClaimable, ghstSymbol, stnkSymbol }) => {
setConfirmationModalOpen,
prepareBalance,
epoch,
claim,
isPayoutGhst,
isClaimable,
ghstSymbol,
stnkSymbol,
tokenPrice,
}) => {
return ( return (
<Box mt="10px"> <Box mt="10px">
<Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}> <Box display="flex" flexDirection="row" alignItems="center" style={{ whiteSpace: "nowrap" }}>
@ -221,15 +199,10 @@ const MobileClaimInfo = ({
</Box> </Box>
<DataRow <DataRow
title="Staked Amount" title="Amount"
balance={formatNumber(prepareBalance, 7)} balance={formatNumber(prepareBalance, 7)}
/> />
<DataRow
title="Price Estimation"
balance={formatCurrency(prepareBalance * tokenPrice, 2)}
/>
<DataRow <DataRow
title="Claimed in" title="Claimed in"
balance={prettifySecondsInDays(epoch.length * (claim.expiry - epoch.number))} 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 zero = new DecimalBigNumber(0n, 0);
const bondName = `${baseTokenSymbol}/${tokenNameConverter(chainId, "WETH")}`;
return { return {
id, id,
discount, discount,
displayName: getBondNameDisplayName(chainId, quoteTokenAddress, baseTokenSymbol), displayName: getBondNameDisplayName(chainId, bondName, quoteTokenAddress),
baseToken: { baseToken: {
name: baseTokenSymbol, name: baseTokenSymbol,
purchaseUrl: getTokenPurchaseLink(chainId, "", chainName), purchaseUrl: getTokenPurchaseLink(chainId, "", chainName),
@ -266,7 +267,7 @@ export const useNotes = (chainId, address) => {
return { notes, refetch }; 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 = [ const args = [
bondId, bondId,
amount, amount,
@ -284,12 +285,11 @@ export const purchaseBond = async ({ chainId, bondId, amount, maxPrice, user, se
"deposit", "deposit",
args, args,
sender, sender,
messages, messages
isNative ? amount : undefined
); );
} }
export const redeem = async ({ chainId, user, isGhst, indexes }) => { export const redeem = async (chainId, user, isGhst, indexes) => {
const args = [ const args = [
user, user,
isGhst, isGhst,
@ -314,8 +314,7 @@ const executeOnChainTransaction = async (
functionName, functionName,
args, args,
account, account,
messages, messages
value
) => { ) => {
try { try {
const { request } = await simulateContract(config, { const { request } = await simulateContract(config, {
@ -326,7 +325,6 @@ const executeOnChainTransaction = async (
account, account,
chainId, chainId,
type: isNetworkLegacyType(chainId) ? 'legacy' : 'eip1559', type: isNetworkLegacyType(chainId) ? 'legacy' : 'eip1559',
value: value,
}); });
const txHash = await writeContract(config, request); const txHash = await writeContract(config, request);

View File

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