Compare commits
3 Commits
39118c3b93
...
6f4d38efb3
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f4d38efb3 | |||
| 92819639d0 | |||
| d1d4313851 |
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-dao-interface",
|
"name": "ghost-dao-interface",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.0",
|
"version": "0.4.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -30,7 +30,6 @@ const StyledArrow = styled(Box)(
|
|||||||
|
|
||||||
const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick, iconNotNeeded, maxWidth}) => {
|
const SwapCollection = ({ UpperSwapCard, LowerSwapCard, arrowOnClick, iconNotNeeded, maxWidth}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flexDirection="column" maxWidth={maxWidth ? maxWidth : "476px"}>
|
<Box display="flex" flexDirection="column" maxWidth={maxWidth ? maxWidth : "476px"}>
|
||||||
{UpperSwapCard}
|
{UpperSwapCard}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const Tooltip = ({ message, children }) => {
|
|||||||
slotProps={undefined}
|
slotProps={undefined}
|
||||||
slots={undefined}
|
slots={undefined}
|
||||||
>
|
>
|
||||||
<Paper className="info-tooltip">
|
<Paper style={{ boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px" }} className="info-tooltip">
|
||||||
{typeof message === "string" ? (
|
{typeof message === "string" ? (
|
||||||
<Typography variant="body1" className="info-tooltip-text">
|
<Typography variant="body1" className="info-tooltip-text">
|
||||||
{message}
|
{message}
|
||||||
|
|||||||
@ -171,9 +171,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
const applaused = transactionApplaused?.finalized ?? false;
|
const applaused = transactionApplaused?.finalized ?? false;
|
||||||
const clappedAmount = transactionApplaused?.clapped_amount ?? 0n;
|
const clappedAmount = transactionApplaused?.clapped_amount ?? 0n;
|
||||||
const clappedPercentage = clappedAmount * 100n / (totalStakedAmount ?? 1n);
|
const clappedPercentage = clappedAmount * 100n / (totalStakedAmount ?? 1n);
|
||||||
const step = finalization > 0
|
const clapsPercentage = (numberOfClaps ?? 0) * 100 / (authorities?.length ?? 1);
|
||||||
? 0
|
|
||||||
: applaused ? 2 : 1;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...watchTransaction,
|
...watchTransaction,
|
||||||
@ -182,14 +180,15 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
numberOfClaps,
|
numberOfClaps,
|
||||||
clappedAmount,
|
clappedAmount,
|
||||||
clappedPercentage,
|
clappedPercentage,
|
||||||
step,
|
clapsPercentage,
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
transactionApplaused,
|
transactionApplaused,
|
||||||
finalityDelay,
|
finalityDelay,
|
||||||
watchTransaction,
|
watchTransaction,
|
||||||
blockNumber,
|
blockNumber,
|
||||||
totalStakedAmount
|
totalStakedAmount,
|
||||||
|
authorities
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const filteredStoredTransactions = useMemo(() => {
|
const filteredStoredTransactions = useMemo(() => {
|
||||||
@ -242,12 +241,12 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
let certainty = 0n;
|
let certainty = 0n;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const commit = latestCommits.at(i);
|
const commit = latestCommits.at(i);
|
||||||
if (commit.disabled) {
|
if (commit.disabled || blockNumber < blocksInFourHours) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
certainty += (commit?.lastStoredBlock ?? 0n) - (blockNumber - blocksInFourHours);
|
certainty += (commit?.lastStoredBlock ?? 0n) - (blockNumber - blocksInFourHours);
|
||||||
}
|
}
|
||||||
return Number(certainty * 100n / (blocksInFourHours * BigInt(length)));
|
return Math.max(Number(certainty * 100n / (blocksInFourHours * BigInt(length))), 0);
|
||||||
}, [latestCommits, blockNumber]);
|
}, [latestCommits, blockNumber]);
|
||||||
|
|
||||||
const timeToNextEpoch = useMemo(() => {
|
const timeToNextEpoch = useMemo(() => {
|
||||||
@ -284,10 +283,10 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
const newStoredTransactions = [...storedTransactions, transaction];
|
const newStoredTransactions = [transaction, ...storedTransactions];
|
||||||
setStoredTransactions(newStoredTransactions);
|
setStoredTransactions(newStoredTransactions);
|
||||||
localStorage.setItem(STORAGE_PREFIX, JSON.stringify(newStoredTransactions));
|
localStorage.setItem(STORAGE_PREFIX, JSON.stringify(newStoredTransactions));
|
||||||
setActiveTxIndex(newStoredTransactions.length - 1)
|
setActiveTxIndex(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -322,7 +321,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
<Grid item xs={12} height="100%">
|
<Grid item xs={12} height="100%">
|
||||||
<Paper
|
<Paper
|
||||||
sx={{ paddingBottom: "0 !important", marginBottom: "0 !important" }}
|
sx={{ height: isBigScreen ? "100%" : "142px", paddingBottom: "0 !important", marginBottom: "0 !important" }}
|
||||||
fullWidth
|
fullWidth
|
||||||
enableBackground
|
enableBackground
|
||||||
>
|
>
|
||||||
@ -362,6 +361,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
style={{ height: "434px" }}
|
||||||
fullWidth
|
fullWidth
|
||||||
enableBackground
|
enableBackground
|
||||||
>
|
>
|
||||||
@ -383,6 +383,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
/>
|
/>
|
||||||
: <BridgeCardHistory
|
: <BridgeCardHistory
|
||||||
isSemiSmallScreen={isSemiSmallScreen}
|
isSemiSmallScreen={isSemiSmallScreen}
|
||||||
|
isBigScreen={isBigScreen}
|
||||||
filteredStoredTransactions={filteredStoredTransactions}
|
filteredStoredTransactions={filteredStoredTransactions}
|
||||||
ghstSymbol={ghstSymbol}
|
ghstSymbol={ghstSymbol}
|
||||||
blockNumber={blockNumber}
|
blockNumber={blockNumber}
|
||||||
@ -407,6 +408,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
}</Typography>
|
}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
|
style={{ height: "434px" }}
|
||||||
enableBackground
|
enableBackground
|
||||||
fullWidth
|
fullWidth
|
||||||
>
|
>
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {
|
|||||||
TableCell,
|
TableCell,
|
||||||
Modal,
|
Modal,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
useMediaQuery,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import { useConfig } from "wagmi";
|
import { useConfig } from "wagmi";
|
||||||
@ -23,13 +24,13 @@ import { PrimaryButton } from "../../components/Button";
|
|||||||
import GhostStyledIcon from "../../components/Icon/GhostIcon";
|
import GhostStyledIcon from "../../components/Icon/GhostIcon";
|
||||||
import SwapCard from "../../components/Swap/SwapCard";
|
import SwapCard from "../../components/Swap/SwapCard";
|
||||||
import SwapCollection from "../../components/Swap/SwapCollection";
|
import SwapCollection from "../../components/Swap/SwapCollection";
|
||||||
import InfoTooltip from "../../components/Tooltip/InfoTooltip";
|
|
||||||
|
|
||||||
import { ghost } from "../../hooks/staking";
|
import { ghost } from "../../hooks/staking";
|
||||||
import { useBalance } from "../../hooks/tokens";
|
import { useBalance } from "../../hooks/tokens";
|
||||||
|
|
||||||
import CheckIcon from '@mui/icons-material/Check';
|
import CheckIcon from '@mui/icons-material/Check';
|
||||||
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
|
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
|
||||||
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||||
|
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { formatNumber, formatCurrency, timeConverter } from "../../helpers";
|
import { formatNumber, formatCurrency, timeConverter } from "../../helpers";
|
||||||
@ -158,16 +159,21 @@ export const BridgeCardAction = ({
|
|||||||
}, [receiver])
|
}, [receiver])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box width="100%" height="320px" display="flex" flexDirection="column" justifyContent="space-between">
|
<Box width="100%" height="340px" display="flex" flexDirection="column" justifyContent="space-between">
|
||||||
<SwapCollection
|
<SwapCollection
|
||||||
iconNotNeeded
|
iconNotNeeded
|
||||||
|
maxWidth="100%"
|
||||||
UpperSwapCard={<SwapCard
|
UpperSwapCard={<SwapCard
|
||||||
id={`bridge-token-receiver`}
|
id={`bridge-token-receiver`}
|
||||||
inputWidth={"100%"}
|
inputWidth={"100%"}
|
||||||
value={receiver}
|
value={convertedReceiver ? sliceString(receiver, 15, -10) : receiver}
|
||||||
onChange={event => setReceiver(event.currentTarget.value)}
|
onChange={event => setReceiver(convertedReceiver ? "" : event.currentTarget.value)}
|
||||||
inputProps={{ "data-testid": "fromInput" }}
|
inputProps={{ "data-testid": "fromInput" }}
|
||||||
placeholder="GHOST address (sf prefixed)"
|
placeholder="GHOST address (sf prefixed)"
|
||||||
|
endString={convertedReceiver
|
||||||
|
? <GhostStyledIcon color="success" viewBox="0 0 25 25" component={CheckCircleIcon} />
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
type="text"
|
type="text"
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
/>}
|
/>}
|
||||||
@ -189,18 +195,18 @@ export const BridgeCardAction = ({
|
|||||||
gap="10px"
|
gap="10px"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
>
|
>
|
||||||
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
<Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
{gatekeeperAddressEmpty && (
|
{gatekeeperAddressEmpty && (
|
||||||
<Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
<Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
<Typography mr="10px" variant="body2" color="textSecondary">
|
<Typography align="justify" mr="10px" variant="body2" color="textSecondary">
|
||||||
<em>
|
<em>
|
||||||
There is no connected gatekeeper on {chainName} network. Propose gatekeeper on this network to make authorities listen to it.
|
There is no connected gatekeeper on {chainName} network yet.
|
||||||
</em>
|
</em>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{!gatekeeperAddressEmpty && (
|
{!gatekeeperAddressEmpty && (
|
||||||
<>
|
<Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Gatekeeper:</Typography>}
|
{!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Gatekeeper:</Typography>}
|
||||||
<Link
|
<Link
|
||||||
fontSize="12px"
|
fontSize="12px"
|
||||||
@ -211,7 +217,7 @@ export const BridgeCardAction = ({
|
|||||||
>
|
>
|
||||||
{sliceString(gatekeeperAddress, 10, -8)}
|
{sliceString(gatekeeperAddress, 10, -8)}
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
<Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
|
||||||
@ -248,12 +254,15 @@ export const BridgeCardAction = ({
|
|||||||
|
|
||||||
export const BridgeCardHistory = ({
|
export const BridgeCardHistory = ({
|
||||||
isSemiSmallScreen,
|
isSemiSmallScreen,
|
||||||
|
isBigScreen,
|
||||||
filteredStoredTransactions,
|
filteredStoredTransactions,
|
||||||
ghstSymbol,
|
ghstSymbol,
|
||||||
blockNumber,
|
blockNumber,
|
||||||
finalityDelay,
|
finalityDelay,
|
||||||
setActiveTxIndex
|
setActiveTxIndex
|
||||||
}) => {
|
}) => {
|
||||||
|
const isVeryBigScreen = useMediaQuery("(max-width: 1360px)");
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const background = (index) => {
|
const background = (index) => {
|
||||||
return index % 2 === 1 ? "" : theme.colors.gray[750];
|
return index % 2 === 1 ? "" : theme.colors.gray[750];
|
||||||
@ -274,9 +283,9 @@ export const BridgeCardHistory = ({
|
|||||||
<Table sx={{ marginTop: "0px" }} stickyHeader aria-label="sticky available transactions">
|
<Table sx={{ marginTop: "0px" }} stickyHeader aria-label="sticky available transactions">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow sx={{ height: "40px" }}>
|
<TableRow sx={{ height: "40px" }}>
|
||||||
<TableCell align="left" style={{ padding: "0px", paddingLeft: "16px", fontSize: "12px", borderTopLeftRadius: "3px", background: theme.colors.paper.cardHover }}>
|
{!(isBigScreen ^ isVeryBigScreen) && <TableCell align="left" style={{ padding: "0px", paddingLeft: "16px", fontSize: "12px", borderTopLeftRadius: "3px", background: theme.colors.paper.cardHover }}>
|
||||||
Transaction
|
Transaction
|
||||||
</TableCell>
|
</TableCell>}
|
||||||
<TableCell align="center" style={{ padding: "0px", fontSize: "12px", background: theme.colors.paper.cardHover }}>
|
<TableCell align="center" style={{ padding: "0px", fontSize: "12px", background: theme.colors.paper.cardHover }}>
|
||||||
Datetime
|
Datetime
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@ -294,7 +303,7 @@ export const BridgeCardHistory = ({
|
|||||||
data-testid={idx + `--tx-history`}
|
data-testid={idx + `--tx-history`}
|
||||||
onClick={() => setActiveTxIndex(idx)}
|
onClick={() => setActiveTxIndex(idx)}
|
||||||
>
|
>
|
||||||
<TableCell style={{ background: background(idx) }}>
|
{!(isBigScreen ^ isVeryBigScreen) && <TableCell style={{ background: background(idx) }}>
|
||||||
<Box display="flex" flexDirection="column" justifyContent="center">
|
<Box display="flex" flexDirection="column" justifyContent="center">
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
{formatCurrency(
|
{formatCurrency(
|
||||||
@ -311,7 +320,7 @@ export const BridgeCardHistory = ({
|
|||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>}
|
||||||
|
|
||||||
<TableCell style={{ background: background(idx) }}>
|
<TableCell style={{ background: background(idx) }}>
|
||||||
<Box display="flex" flexDirection="column" alignItems="center" paddingLeft="5px">
|
<Box display="flex" flexDirection="column" alignItems="center" paddingLeft="5px">
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Box, Paper, Grid, Typography, LinearProgress, useTheme } from "@mui/mat
|
|||||||
|
|
||||||
import Metric from "../../components/Metric/Metric";
|
import Metric from "../../components/Metric/Metric";
|
||||||
import Countdown from "../../components/Countdown/Countdown";
|
import Countdown from "../../components/Countdown/Countdown";
|
||||||
|
import InfoTooltip from "../../components/Tooltip/InfoTooltip";
|
||||||
import { formatNumber } from "../../helpers";
|
import { formatNumber } from "../../helpers";
|
||||||
|
|
||||||
export const BridgeHeader = ({
|
export const BridgeHeader = ({
|
||||||
@ -83,7 +84,7 @@ export const BridgeHeader = ({
|
|||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
<Grid item xs={isSmallScreen ? 12 : 4}>
|
||||||
<Metric
|
<Metric
|
||||||
isLoading={timeToNextEpoch === undefined}
|
isLoading={timeToNextEpoch === undefined}
|
||||||
metric={formatTime(timeToNextEpoch)}
|
metric={timeToNextEpoch < 30 ? "Rotating..." : formatTime(timeToNextEpoch)}
|
||||||
label="Rotation in"
|
label="Rotation in"
|
||||||
tooltip="Bridge Stability Index refreshes every 10 minutes with new validator blocks; resets each Era when the validator set is updated."
|
tooltip="Bridge Stability Index refreshes every 10 minutes with new validator blocks; resets each Era when the validator set is updated."
|
||||||
/>
|
/>
|
||||||
@ -91,12 +92,12 @@ export const BridgeHeader = ({
|
|||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
<Grid item xs={isSmallScreen ? 12 : 4}>
|
||||||
<Metric
|
<Metric
|
||||||
isLoading={transactionEta === undefined}
|
isLoading={transactionEta === undefined}
|
||||||
metric={formatTime(transactionEta)}
|
metric={transactionEta > 14400 ? "∞" : formatTime(transactionEta)}
|
||||||
label="Max Bridge ETA"
|
label="Max Bridge ETA"
|
||||||
tooltip="Maximum estimated time for finalizing bridge transactions based on the latest update."
|
tooltip="Maximum estimated time for finalizing bridge transactions based on the latest update."
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item gap={2} xs={12} sx={{ marginTop: "20px" }}>
|
<Grid item gap={2} xs={12} style={{ paddingTop: "0" }} >
|
||||||
<Box position="relative" margin="4.5px 0">
|
<Box position="relative" margin="4.5px 0">
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
variant="determinate"
|
variant="determinate"
|
||||||
@ -122,9 +123,18 @@ export const BridgeHeader = ({
|
|||||||
<Typography variant="body1" sx={{ fontWeight: 'bold' }}>
|
<Typography variant="body1" sx={{ fontWeight: 'bold' }}>
|
||||||
Bridge Stability {bridgeStability
|
Bridge Stability {bridgeStability
|
||||||
? `${formatNumber(bridgeStability, 0)}% ${progressBarPostfix}`
|
? `${formatNumber(bridgeStability, 0)}% ${progressBarPostfix}`
|
||||||
: "Unknown"
|
: "N/A"
|
||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<InfoTooltip message={
|
||||||
|
<Box width="220px">
|
||||||
|
<Typography>0% - 50%: ❌ Do NOT Bridge</Typography>
|
||||||
|
<Typography>50% - 70%: ⚠️ Critical Risk</Typography>
|
||||||
|
<Typography>70% - 80%: ⚠️ High Risk</Typography>
|
||||||
|
<Typography>80% - 90%: ✅ Moderate Risk</Typography>
|
||||||
|
<Typography>90% - 100%: ✅ Safe</Typography>
|
||||||
|
</Box>
|
||||||
|
} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import ThumbDownAltIcon from '@mui/icons-material/ThumbDownAlt';
|
|||||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||||
import CheckIcon from '@mui/icons-material/Check';
|
import CheckIcon from '@mui/icons-material/Check';
|
||||||
import AssuredWorkloadIcon from '@mui/icons-material/AssuredWorkload';
|
import AssuredWorkloadIcon from '@mui/icons-material/AssuredWorkload';
|
||||||
|
import AccountBalanceIcon from '@mui/icons-material/AccountBalance';
|
||||||
|
|
||||||
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
|
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
|
||||||
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
|
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
|
||||||
@ -88,11 +89,13 @@ export const BridgeModal = ({
|
|||||||
>
|
>
|
||||||
<Box display="flex" gap="1.5rem" flexDirection="column" marginTop=".8rem">
|
<Box display="flex" gap="1.5rem" flexDirection="column" marginTop=".8rem">
|
||||||
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
|
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
|
||||||
|
{currentRecord?.finalization > 0 && (
|
||||||
|
<>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
transition: "all 0.8s ease",
|
transition: "all 0.8s ease",
|
||||||
transform: currentRecord?.step === 0 && "scale(1.2)",
|
transform: currentRecord?.finalization > 0 && "scale(1.2)",
|
||||||
color: currentRecord?.step > 0 && theme.colors.primary[300]
|
color: currentRecord?.finalization === 0 && theme.colors.primary[300]
|
||||||
}}
|
}}
|
||||||
width="120px"
|
width="120px"
|
||||||
display="flex"
|
display="flex"
|
||||||
@ -104,7 +107,7 @@ export const BridgeModal = ({
|
|||||||
sx={{
|
sx={{
|
||||||
width: "35px",
|
width: "35px",
|
||||||
height: "35px",
|
height: "35px",
|
||||||
animation: currentRecord?.step === 0 && 'rotateHourGlass 2s ease-in-out infinite',
|
animation: currentRecord?.finalization > 0 && 'rotateHourGlass 2s ease-in-out infinite',
|
||||||
'@keyframes rotateHourGlass': {
|
'@keyframes rotateHourGlass': {
|
||||||
'0%': { transform: 'rotate(0deg)' },
|
'0%': { transform: 'rotate(0deg)' },
|
||||||
'15%': { transform: 'rotate(0deg)' },
|
'15%': { transform: 'rotate(0deg)' },
|
||||||
@ -122,16 +125,64 @@ export const BridgeModal = ({
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<GhostStyledIcon
|
<GhostStyledIcon
|
||||||
sx={{ transition: "all 0.3s ease", opacity: currentRecord?.step < 1 && "0.2" }}
|
sx={{
|
||||||
|
transition: "all 0.3s ease",
|
||||||
|
opacity: currentRecord?.finalization > 0 && "0.2"
|
||||||
|
}}
|
||||||
|
component={ArrowRightIcon}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
transition: "all 0.3s ease",
|
||||||
|
opacity: currentRecord?.finalization > 0 && "0.2",
|
||||||
|
transform: currentRecord?.finalization === 0 && currentRecord?.clappedPercentage < 50n && "scale(1.2)",
|
||||||
|
color: currentRecord?.clappedPercentage > 50n && theme.colors.primary[300]
|
||||||
|
}}
|
||||||
|
width="120px"
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Box display="flex" flexDirection="column" justifyContent="center" alignItems="center">
|
||||||
|
{currentRecord?.clappedPercentage < 50n
|
||||||
|
? <GhostStyledIcon
|
||||||
|
sx={{
|
||||||
|
width: "35px",
|
||||||
|
height: "35px",
|
||||||
|
animation: currentRecord?.finalization === 0 && 'bounce 2s ease-in-out infinite',
|
||||||
|
'@keyframes bounce': {
|
||||||
|
'0%, 20%, 50%, 80%, 75%, 100%': { transform: 'translateY(0)' },
|
||||||
|
'40%': { transform: 'translateY(-4px)' },
|
||||||
|
'60%': { transform: 'translateY(-2px)' },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
viewBox="0 0 25 25"
|
||||||
|
component={AccountBalanceIcon}
|
||||||
|
/>
|
||||||
|
: <GhostStyledIcon sx={{ width: "35px", height: "35px" }} viewBox="0 0 25 25" component={AssuredWorkloadIcon} />
|
||||||
|
}
|
||||||
|
<Typography variant="caption">Capital Backed</Typography>
|
||||||
|
<Typography variant="caption">
|
||||||
|
{(currentRecord?.clappedAmount ?? 0n) / 10n**18n} {ghstSymbol} ({currentRecord?.clappedPercentage ?? 0}%)
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<GhostStyledIcon
|
||||||
|
sx={{ transition: "all 0.3s ease", opacity: currentRecord?.clappedPercentage < 50n && "0.2" }}
|
||||||
component={ArrowRightIcon}
|
component={ArrowRightIcon}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
transition: "all 0.3s ease",
|
transition: "all 0.3s ease",
|
||||||
opacity: currentRecord?.step < 1 && "0.2",
|
opacity: currentRecord?.finalization > 0 && "0.2",
|
||||||
transform: currentRecord?.step === 1 && "scale(1.2)",
|
transform: currentRecord?.finalization === 0 && currentRecord?.clapsPercentage < 50 && "scale(1.2)",
|
||||||
color: currentRecord?.step > 1 && theme.colors.primary[300]
|
color: currentRecord?.clapsPercentage > 50 && theme.colors.primary[300]
|
||||||
}}
|
}}
|
||||||
width="120px"
|
width="120px"
|
||||||
display="flex"
|
display="flex"
|
||||||
@ -140,14 +191,14 @@ export const BridgeModal = ({
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
>
|
>
|
||||||
<Box display="flex" flexDirection="row" justifyContent="center" alignItems="center">
|
<Box display="flex" flexDirection="row" justifyContent="center" alignItems="center">
|
||||||
{currentRecord?.step <= 1
|
{currentRecord?.clapsPercentage < 50
|
||||||
? (
|
? (
|
||||||
<>
|
<>
|
||||||
<GhostStyledIcon
|
<GhostStyledIcon
|
||||||
sx={{
|
sx={{
|
||||||
width: "35px",
|
width: "35px",
|
||||||
height: "35px",
|
height: "35px",
|
||||||
animation: currentRecord?.step === 1 && 'rotateRightHand 2s ease-in-out infinite',
|
animation: currentRecord?.finalization === 0 && 'rotateRightHand 2s ease-in-out infinite',
|
||||||
'@keyframes rotateRightHand': {
|
'@keyframes rotateRightHand': {
|
||||||
'0%': { transform: 'rotateX(360deg)' },
|
'0%': { transform: 'rotateX(360deg)' },
|
||||||
'15%': { transform: 'rotateX(360deg)' },
|
'15%': { transform: 'rotateX(360deg)' },
|
||||||
@ -163,7 +214,7 @@ export const BridgeModal = ({
|
|||||||
sx={{
|
sx={{
|
||||||
width: "35px",
|
width: "35px",
|
||||||
height: "35px",
|
height: "35px",
|
||||||
animation: currentRecord?.step === 1 && 'rotateRightHand 2s ease-in-out infinite',
|
animation: currentRecord?.finalization === 0 && 'rotateRightHand 2s ease-in-out infinite',
|
||||||
'@keyframes rotateRightHand': {
|
'@keyframes rotateRightHand': {
|
||||||
'0%': { transform: 'rotateX(0deg)' },
|
'0%': { transform: 'rotateX(0deg)' },
|
||||||
'15%': { transform: 'rotateX(0deg)' },
|
'15%': { transform: 'rotateX(0deg)' },
|
||||||
@ -195,20 +246,19 @@ export const BridgeModal = ({
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{currentRecord?.finalization === 0 && (
|
||||||
|
<>
|
||||||
<GhostStyledIcon
|
<GhostStyledIcon
|
||||||
sx={{
|
sx={{ transition: "all 0.3s ease", opacity: !currentRecord?.applaused && "0.2" }}
|
||||||
transition: "all 0.3s ease",
|
|
||||||
opacity: currentRecord?.step < 2 && "0.2"
|
|
||||||
}}
|
|
||||||
component={ArrowRightIcon}
|
component={ArrowRightIcon}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
transition: "all 0.3s ease",
|
transition: "all 0.3s ease",
|
||||||
opacity: currentRecord?.step < 2 && "0.2",
|
opacity: !currentRecord?.applaused && "0.2",
|
||||||
transform: currentRecord?.step === 2 && "scale(1.2)",
|
transform: currentRecord?.applaused && "scale(1.2)",
|
||||||
color: currentRecord?.step === 2 && theme.colors.primary[300]
|
color: currentRecord?.applaused && theme.colors.primary[300]
|
||||||
}}
|
}}
|
||||||
width="120px"
|
width="120px"
|
||||||
display="flex"
|
display="flex"
|
||||||
@ -216,8 +266,6 @@ export const BridgeModal = ({
|
|||||||
justifyContent="start"
|
justifyContent="start"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
>
|
>
|
||||||
{currentRecord?.applaused
|
|
||||||
? <>
|
|
||||||
<GhostStyledIcon
|
<GhostStyledIcon
|
||||||
sx={{ width: "35px", height: "35px" }}
|
sx={{ width: "35px", height: "35px" }}
|
||||||
viewBox="0 0 25 25"
|
viewBox="0 0 25 25"
|
||||||
@ -225,20 +273,9 @@ export const BridgeModal = ({
|
|||||||
/>
|
/>
|
||||||
<Typography variant="caption">Applaused</Typography>
|
<Typography variant="caption">Applaused</Typography>
|
||||||
<Typography variant="caption">Check Receiver</Typography>
|
<Typography variant="caption">Check Receiver</Typography>
|
||||||
</>
|
|
||||||
: <>
|
|
||||||
<GhostStyledIcon
|
|
||||||
sx={{ width: "35px", height: "35px" }}
|
|
||||||
viewBox="0 0 25 25"
|
|
||||||
component={AssuredWorkloadIcon}
|
|
||||||
/>
|
|
||||||
<Typography variant="caption">Capital Backed</Typography>
|
|
||||||
<Typography variant="caption">
|
|
||||||
{(currentRecord?.clappedAmount ?? 0n) / 10n**18n} {ghstSymbol} ({currentRecord?.clappedPercentage ?? 0}%)
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</Box>
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display="flex" flexDirection="column" gap="5px" padding="0.6rem 0">
|
<Box display="flex" flexDirection="column" gap="5px" padding="0.6rem 0">
|
||||||
@ -300,7 +337,10 @@ export const BridgeModal = ({
|
|||||||
}</Typography>
|
}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
<Box display="flex" flexDirection="row" justifyContent="space-between">
|
||||||
|
<Box display="flex" flexDirection="row">
|
||||||
<Typography variant="body2">Executed at:</Typography>
|
<Typography variant="body2">Executed at:</Typography>
|
||||||
|
<InfoTooltip message="The timestamp when the bridge transaction was submitted." />
|
||||||
|
</Box>
|
||||||
<Typography variant="body2">{
|
<Typography variant="body2">{
|
||||||
new Date(currentRecord ? currentRecord.timestamp : 0).toLocaleString('en-US')
|
new Date(currentRecord ? currentRecord.timestamp : 0).toLocaleString('en-US')
|
||||||
}</Typography>
|
}</Typography>
|
||||||
@ -378,7 +418,7 @@ export const BridgeConfirmModal = ({
|
|||||||
}}
|
}}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
href="https://google.com"
|
href="https://ghostchain.io/bridge-disclaimer"
|
||||||
>
|
>
|
||||||
Learn more.
|
Learn more.
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@ -10,10 +10,13 @@ import {
|
|||||||
TableHead,
|
TableHead,
|
||||||
TableRow,
|
TableRow,
|
||||||
Typography,
|
Typography,
|
||||||
|
Link,
|
||||||
LinearProgress,
|
LinearProgress,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
|
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||||
|
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||||
@ -31,6 +34,7 @@ export const ValidatorTable = ({
|
|||||||
providerDetail,
|
providerDetail,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const [sortedBy, setsortedBy] = useState(undefined);
|
||||||
|
|
||||||
const stabilityColor = useMemo(() => {
|
const stabilityColor = useMemo(() => {
|
||||||
const red = Math.round(255 * (1 - bridgeStability / 100));
|
const red = Math.round(255 * (1 - bridgeStability / 100));
|
||||||
@ -38,12 +42,72 @@ export const ValidatorTable = ({
|
|||||||
return `rgb(${red}, ${green}, 0)`;
|
return `rgb(${red}, ${green}, 0)`;
|
||||||
}, [bridgeStability]);
|
}, [bridgeStability]);
|
||||||
|
|
||||||
|
const sortedCommits = useMemo(() => {
|
||||||
|
return latestCommits?.sort((a, b) => {
|
||||||
|
let one = 0;
|
||||||
|
let two = 0;
|
||||||
|
switch (sortedBy) {
|
||||||
|
case -1:
|
||||||
|
one = Number(b.lastUpdated ?? 0n);
|
||||||
|
two = Number(a.lastUpdated ?? 0n);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
one = Number(a.lastUpdated ?? 0n);
|
||||||
|
two = Number(b.lastUpdated ?? 0n);
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
one = Number(b.lastStoredBlock ?? 0n);
|
||||||
|
two = Number(a.lastStoredBlock ?? 0n);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
one = Number(a.lastStoredBlock ?? 0n);
|
||||||
|
two = Number(b.lastStoredBlock ?? 0n);
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
one = Number(b.lastStoredBlock ?? 0n);
|
||||||
|
two = Number(a.lastStoredBlock ?? 0n);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
one = Number(a.lastStoredBlock ?? 0n);
|
||||||
|
two = Number(b.lastStoredBlock ?? 0n);
|
||||||
|
break;
|
||||||
|
case -4:
|
||||||
|
one = b.disabled ? 1 : 0;
|
||||||
|
two = a.disabled ? 1 : 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
one = a.disabled ? 1 : 0;
|
||||||
|
two = b.disabled ? 1 : 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return one - two;
|
||||||
|
}) ?? [];
|
||||||
|
}, [latestCommits, sortedBy]);
|
||||||
|
|
||||||
|
const changeSort = (prevValue, newValue) => {
|
||||||
|
if (prevValue === undefined) {
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevValueAbs = Math.abs(prevValue);
|
||||||
|
const newValueAbs = Math.abs(newValue);
|
||||||
|
|
||||||
|
if (prevValueAbs === newValueAbs) {
|
||||||
|
return prevValue * -1;
|
||||||
|
} else {
|
||||||
|
return newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box width="100%" height="320px" display="flex" flexDirection="column" justifyContent="space-between">
|
<Box width="100%" height="340px" display="flex" flexDirection="column" justifyContent="space-between" gap="10px">
|
||||||
{!providerDetail && <Box sx={{ borderRadius: "15px", background: theme.colors.paper.background, paddingTop: "40px" }} width="100%" height="100%" display="flex" justifyContent="center">
|
{!providerDetail && <Box sx={{ borderRadius: "15px", background: theme.colors.paper.background }} width="100%" height="100%" display="flex" justifyContent="center">
|
||||||
<Box padding="20px 30px" display="flex" flexDirection="column" justifyContent="space-around" alignItems="center">
|
<Box padding="20px 30px" display="flex" flexDirection="column" justifyContent="space-around" alignItems="center">
|
||||||
<Typography sx={{ textAlign: "center" }} variant="h6">GHOST Wallet is not detected on your browser!</Typography>
|
<Typography sx={{ textAlign: "center" }} variant="h6">GHOST Wallet is not detected on your browser!</Typography>
|
||||||
<Typography sx={{ textAlign: "center" }}>Download GHOST Wallet Extension to see real-time validator stats for bridging transaction.</Typography>
|
<Typography sx={{ textAlign: "center" }} variant="body2">Download GHOST Wallet Extension for real-time visibility into validator status and related transaction risks.</Typography>
|
||||||
|
<Typography sx={{ textAlign: "center" }} variant="body2"><b>Important:</b> The GHOST Wallet Extension is optional, but be aware that your bridge transaction will succeed or fail irreversibly based on the condition of the validators.</Typography>
|
||||||
<PrimaryButton onClick={() => window.open('https://git.ghostchain.io/ghostchain/ghost-extension-wallet/releases', '_blank', 'noopener,noreferrer')}>
|
<PrimaryButton onClick={() => window.open('https://git.ghostchain.io/ghostchain/ghost-extension-wallet/releases', '_blank', 'noopener,noreferrer')}>
|
||||||
Get GHOST Extension
|
Get GHOST Extension
|
||||||
</PrimaryButton>
|
</PrimaryButton>
|
||||||
@ -53,7 +117,7 @@ export const ValidatorTable = ({
|
|||||||
component={Paper}
|
component={Paper}
|
||||||
className="custom-scrollbar"
|
className="custom-scrollbar"
|
||||||
sx={{
|
sx={{
|
||||||
height: "320px",
|
height: "310px",
|
||||||
overflowY: 'scroll',
|
overflowY: 'scroll',
|
||||||
msOverflowStyle: "thin !important",
|
msOverflowStyle: "thin !important",
|
||||||
scrollbarWidth: "thin !important",
|
scrollbarWidth: "thin !important",
|
||||||
@ -62,11 +126,11 @@ export const ValidatorTable = ({
|
|||||||
<Table sx={{ marginTop: "0px" }} stickyHeader aria-label="sticky available validators">
|
<Table sx={{ marginTop: "0px" }} stickyHeader aria-label="sticky available validators">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow sx={{ height: "40px" }}>
|
<TableRow sx={{ height: "40px" }}>
|
||||||
<BridgeHeaderTableCell value="Validator" background={theme.colors.paper.cardHover} borderTopLeftRadius="3px" />
|
<BridgeHeaderTableCell index={0} changeSort={() => setsortedBy(undefined)} value="Validator" background={theme.colors.paper.cardHover} borderTopLeftRadius="3px" />
|
||||||
<BridgeHeaderTableCell value="Last Acitve" background={theme.colors.paper.cardHover} tooltip="GHOST Validators must submit block commitments every 10 minutes to remain active." />
|
<BridgeHeaderTableCell index={1} sortedBy={sortedBy} changeSort={() => setsortedBy(prev => changeSort(prev, 1))} value="Last Acitve" background={theme.colors.paper.cardHover} tooltip="GHOST Validators must submit block commitments every 10 minutes to remain active." />
|
||||||
<BridgeHeaderTableCell value="Block Height" background={theme.colors.paper.cardHover} tooltip="The latest EVM block height reported by the Validator." />
|
<BridgeHeaderTableCell index={2} sortedBy={sortedBy} changeSort={() => setsortedBy(prev => changeSort(prev, 2))} value="Block Height" background={theme.colors.paper.cardHover} tooltip="The latest EVM block height reported by the Validator." />
|
||||||
<BridgeHeaderTableCell value="Block Delayed" background={theme.colors.paper.cardHover} tooltip="Block delays under 4 hours are safe. Block delays over 4 hours risk bridge transaction failure." />
|
<BridgeHeaderTableCell index={3} sortedBy={sortedBy} changeSort={() => setsortedBy(prev => changeSort(prev, 3))} value="Block Delayed" background={theme.colors.paper.cardHover} tooltip="Block delays under 4 hours are safe. Block delays over 4 hours risk bridge transaction failure." />
|
||||||
<BridgeHeaderTableCell value="Status" background={theme.colors.paper.cardHover} borderTopRightRadius="3px" tooltip="Active and disabled validators fore the current GHOST Epoch." />
|
<BridgeHeaderTableCell index={4} sortedBy={sortedBy} changeSort={() => setsortedBy(prev => changeSort(prev, 4))} value="Status" background={theme.colors.paper.cardHover} borderTopRightRadius="3px" tooltip="Active and disabled validators fore the current GHOST Epoch." />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
|
||||||
@ -86,11 +150,26 @@ export const ValidatorTable = ({
|
|||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>}
|
</TableContainer>}
|
||||||
|
<Box marginTop="5px" display="flex" flexDirection="row" justifyContent="center" alignItems="center">
|
||||||
|
<Link
|
||||||
|
underline="always"
|
||||||
|
fontSize="12px"
|
||||||
|
lineHeight="15px"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href="https://telemetry.ghostchain.io"
|
||||||
|
>
|
||||||
|
See Validator Telemetry
|
||||||
|
</Link>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const BridgeHeaderTableCell = ({
|
const BridgeHeaderTableCell = ({
|
||||||
|
index=0,
|
||||||
|
sortedBy=undefined,
|
||||||
|
changeSort,
|
||||||
align="center",
|
align="center",
|
||||||
borderTopRightRadius="0px",
|
borderTopRightRadius="0px",
|
||||||
borderTopLeftRadius="0px",
|
borderTopLeftRadius="0px",
|
||||||
@ -113,11 +192,21 @@ const BridgeHeaderTableCell = ({
|
|||||||
background,
|
background,
|
||||||
fontSize,
|
fontSize,
|
||||||
padding,
|
padding,
|
||||||
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box display="flex" justifyContent="center">
|
<Box onClick={changeSort} display="flex" justifyContent="center" alignItems="center">
|
||||||
{value}
|
{value}
|
||||||
{tooltip && <InfoTooltip message={tooltip} />}
|
{tooltip
|
||||||
|
? Math.abs(sortedBy) !== index
|
||||||
|
? <InfoTooltip message={tooltip} />
|
||||||
|
: <GhostStyledIcon
|
||||||
|
sx={{ width: "12px", height: "12px" }}
|
||||||
|
viewBox="0 0 25 25"
|
||||||
|
component={sortedBy > 0 ? KeyboardArrowDownIcon : KeyboardArrowUpIcon}
|
||||||
|
/>
|
||||||
|
: <></>
|
||||||
|
}
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Paper from "../../components/Paper/Paper";
|
|||||||
|
|
||||||
import GhostIcon from "../../assets/icons/ghost-nav-header.svg?react";
|
import GhostIcon from "../../assets/icons/ghost-nav-header.svg?react";
|
||||||
import EthIcon from "../../assets/tokens/ETH.svg?react";
|
import EthIcon from "../../assets/tokens/ETH.svg?react";
|
||||||
|
import { parseKnownToken } from "../../components/Token/Token"
|
||||||
|
|
||||||
import { useSwitchChain } from 'wagmi';
|
import { useSwitchChain } from 'wagmi';
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
@ -92,7 +93,7 @@ export default function NotFound({
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
gap="15px"
|
gap="15px"
|
||||||
>
|
>
|
||||||
<SvgIcon component={EthIcon} viewBox="0 0 32 32" />
|
<SvgIcon component={parseKnownToken(chain.nativeCurrency.symbol)} inheritViewBox style={{ height: "25px" }} />
|
||||||
<Typography fontSize="1.2em">{chain.name}</Typography>
|
<Typography fontSize="1.2em">{chain.name}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -42,9 +42,13 @@ export const sortBondsByDiscount = (bonds) => {
|
|||||||
return Array.from(bonds).filter((bond) => !bond.isSoldOut).sort((a, b) => (a.discount.gt(b.discount) ? -1 : 1));
|
return Array.from(bonds).filter((bond) => !bond.isSoldOut).sort((a, b) => (a.discount.gt(b.discount) ? -1 : 1));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const timeConverter = (time) => {
|
export const timeConverter = (time, max = 7200, maxText = "long ago") => {
|
||||||
const seconds = Number(time);
|
const seconds = Number(time);
|
||||||
const mins = Math.floor(seconds / 60);
|
const mins = Math.floor(seconds / 60);
|
||||||
const secs = seconds % 60;
|
const secs = seconds % 60;
|
||||||
|
if (mins > max) {
|
||||||
|
return maxText;
|
||||||
|
} else {
|
||||||
return `${mins}m ${secs < 10 ? '0' : ''}${secs}s`;
|
return `${mins}m ${secs < 10 ? '0' : ''}${secs}s`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -137,12 +137,11 @@ export const getTokenAddress = (chainId, name) => {
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TBD: should be extended on new tokens
|
|
||||||
export const getTokenIcons = (chainId, address) => {
|
export const getTokenIcons = (chainId, address) => {
|
||||||
let icons = [""];
|
let icons = [""];
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case RESERVE_ADDRESSES[chainId]:
|
case RESERVE_ADDRESSES[chainId]:
|
||||||
icons = ["RESERVE"];
|
icons = [chainId === 11155111 ? "GDAI" : "WETH"];
|
||||||
break;
|
break;
|
||||||
case FTSO_ADDRESSES[chainId]:
|
case FTSO_ADDRESSES[chainId]:
|
||||||
icons = ["FTSO"];
|
icons = ["FTSO"];
|
||||||
@ -154,7 +153,7 @@ export const getTokenIcons = (chainId, address) => {
|
|||||||
icons = ["GHST"];
|
icons = ["GHST"];
|
||||||
break;
|
break;
|
||||||
case FTSO_DAI_LP_ADDRESSES[chainId]:
|
case FTSO_DAI_LP_ADDRESSES[chainId]:
|
||||||
icons = ["FTSO", "RESERVE"];
|
icons = ["FTSO", chainId === 11155111 ? "GDAI" : "WETH"];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return icons;
|
return icons;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user