import {
Box,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Typography,
Container,
FormControlLabel,
FormControl,
Checkbox,
Link,
useMediaQuery,
useTheme,
} from "@mui/material";
import { useLocation } from "react-router-dom";
import { useEffect, useState, useMemo, useCallback } from "react";
import useSWR from 'swr';
import ReactGA from "react-ga4";
import SettingsIcon from '@mui/icons-material/Settings';
import Modal from "../../components/Modal/Modal";
import Paper from "../../components/Paper/Paper";
import PageTitle from "../../components/PageTitle/PageTitle";
import TokenStack from "../../components/TokenStack/TokenStack";
import GhostStyledIcon from "../../components/Icon/GhostIcon";
import Chip from "../../components/Chip/Chip";
import { PrimaryButton, TertiaryButton } from "../../components/Button";
import { Tab, Tabs } from "../../components/Tabs/Tabs";
import { useTokenSymbol } from "../../hooks/tokens";
import { useLocalStorage } from "../../hooks/localstorage";
import { useUnstableProvider } from "../../hooks/ghost";
import { shorten } from "../../helpers";
import { networkAvgBlockSpeed } from "../../constants";
import EraseModal from "./EraseModal";
import SettingsModal from "./SettingsModal";
import DexViewModal from "./DexViewModal";
import StakingViewModal from "./StakingViewModal";
import BridgeInModal from "./BridgeInModal";
const HistoryItem = ({ item, chainId, config, currentTime, eraseRecord, setViewModalOpen, isSmallScreen, finalityDelay }) => {
const theme = useTheme();
const isVerySmallScreen = useMediaQuery("(max-width: 450px)");
const localString = new Date(item.submitted).toLocaleString();
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO")
const chainInfo = useMemo(() => {
const client = config?.getClient();
return {
url: client?.chain?.blockExplorers?.default?.url,
symbol: client?.chain?.nativeCurrency?.symbol,
};
}, [config]);
const chipStatus = useMemo(() => {
const delay = Number(finalityDelay * networkAvgBlockSpeed(chainId)) * 1000;
const width = isVerySmallScreen ? "21px" : "100px";
if (item.submitted + delay > currentTime) {
return
}
return
}, [item, currentTime, isVerySmallScreen, finalityDelay])
if (isSmallScreen || isVerySmallScreen) {
return (
<>
{localString}
{shorten(item.txHash)}
{item?.name ?? "Unknown"}
{chipStatus}
Erase
View
>
)
}
return (
{item?.name ?? "Unknown"}
{shorten(item.txHash, 7, -5)}
{chipStatus}
{localString}
Erase
View
)
}
const HistoryList = ({ chainId, storedTransactions, historyType, config, eraseRecord }) => {
const isSmallScreen = useMediaQuery("(max-width: 900px)");
const [currentTime, setCurrentTime] = useState(Date.now());
const [viewModalOpen, setViewModalOpen] = useState(null);
const { CONSTANTS } = useLocalStorage();
const { casperApi } = useUnstableProvider();
const { data: networkData, error, isLoading } = useSWR(
casperApi ? ['networkData', casperApi, chainId] : null,
async () => {
const key = BigInt(chainId);
const res = await casperApi.query.GhostNetworks.Networks.getValue(key);
return res;
},
{
revalidateOnFocus: true
}
);
const finalityDelay = useMemo(() => {
return networkData ? networkData.finality_delay : 420n;
}, [networkData]);
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentTime(Date.now());
}, 1000);
return () => clearInterval(intervalId);
}, []);
const historyContainer = useMemo(() => {
if (isSmallScreen) {
return (
{storedTransactions?.map((item, i) => {
return (
eraseRecord(i)}
setViewModalOpen={() => setViewModalOpen(i)}
isSmallScreen={isSmallScreen}
/>
)
})}
)
} else {
return (
Transaction
Status
Submitted
{storedTransactions?.map((item, i) => {
return (
eraseRecord(i)}
setViewModalOpen={() => setViewModalOpen(i)}
isSmallScreen={isSmallScreen}
/>
)
})}
)
}
}, [isSmallScreen, storedTransactions, config]);
return (
<>
{viewModalOpen !== null && historyType === CONSTANTS.dex.key && (
setViewModalOpen(null)}
isOpen={true}
historyRecord={storedTransactions.at(viewModalOpen)}
/>
)}
{viewModalOpen !== null && historyType === CONSTANTS.stake.key && (
setViewModalOpen(null)}
isOpen={true}
historyRecord={storedTransactions.at(viewModalOpen)}
/>
)}
{viewModalOpen !== null && historyType === CONSTANTS.bridgeIn.key && (
setViewModalOpen(null)}
isOpen={true}
historyRecord={storedTransactions.at(viewModalOpen)}
/>
)}
{historyContainer}
>
)
}
const History = ({ chainId, config, tryConnectInjected, address }) => {
const isSmallScreen = useMediaQuery("(max-width: 650px)");
const isSemiSmallScreen = useMediaQuery("(max-width: 745px)");
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
const [historyTypeIndex, setHistoryTypeIndex] = useState(0);
const [erasingIndex, setErasingIndex] = useState(null);
const [settingsOpen, setSettingsOpen] = useState(false);
const [erasingOpen, setErasingOpen] = useState(false);
const location = useLocation();
useEffect(() => {
ReactGA.send({ hitType: "pageview", page: location.pathname });
}, [location]);
const {
CONSTANTS,
useStorageValue,
setStorageValue,
clearPendingHistory
} = useLocalStorage();
const { data: storedHistoryTypes } = useStorageValue(chainId, address, CONSTANTS.historyPrefix, CONSTANTS.defaultHistoryTypes);
const { data: storedTransactions } = useStorageValue(chainId, address, storedHistoryTypes[historyTypeIndex], []);
const { data: pendingHistory } = useStorageValue(chainId, address, CONSTANTS.pendingHistoryPrefix, {});
const handleHistoryTypesChange = useCallback((values) => {
setStorageValue(chainId, address, CONSTANTS.historyPrefix, values);
}, [chainId, address]);
const handleConfirmErase = useCallback(() => {
if (erasingIndex !== null) {
const updated = storedTransactions.filter((_, index) => index !== erasingIndex);
setStorageValue(chainId, address, storedHistoryTypes[historyTypeIndex], updated);
} else {
setStorageValue(chainId, address, storedHistoryTypes[historyTypeIndex], []);
}
setErasingOpen(false);
setErasingIndex(null);
}, [storedTransactions, erasingIndex, chainId, address, historyTypeIndex]);
useEffect(() => {
clearPendingHistory(chainId, address, storedHistoryTypes.at(historyTypeIndex));
}, [storedHistoryTypes, historyTypeIndex])
return (
{
setErasingOpen(false);
setErasingIndex(null);
}}
submit={handleConfirmErase}
isAll={erasingIndex === null}
/>
setSettingsOpen(false)}
onChange={handleHistoryTypesChange}
selectedValues={storedHistoryTypes}
possibleValues={CONSTANTS.possibleHistoryTypes}
/>
setSettingsOpen(true)}
/>
}
headerContent={
{
const index = storedHistoryTypes.indexOf(selectedValue);
if (index !== -1) setHistoryTypeIndex(index);
}}
TabIndicatorProps={{ style: { display: "none" } }}
>
{storedHistoryTypes.map((type, i) => {
return (
{type}
{pendingHistory && pendingHistory[type] > 0 && (
)}
}
/>
)
})}
setErasingOpen(true)}
sx={{ maxWidth: isSemiSmallScreen ? "100%" : "350px" }}
>
Erase All Records
}
>
{
setErasingIndex(index);
setErasingOpen(true);
}}
historyType={storedHistoryTypes[historyTypeIndex]}
storedTransactions={storedTransactions}
/>
);
}
export default History;