import './App.css'; import { getChainState } from './get-status'; import moment from 'moment' import { Card, CardActions, CardContent, CircularProgress, Container, createStyles, FormControl, Grid, makeStyles, MenuItem, Select, Tab, TextField, Theme, Typography } from '@material-ui/core'; import Dialog from '@material-ui/core/Dialog'; import DialogTitle from '@material-ui/core/DialogTitle'; import Button from '@material-ui/core/Button'; import Edit from '@material-ui/icons/Edit'; import { BootstrapButton } from './BootstrapButton'; import Autocomplete, { AutocompleteChangeDetails } from '@material-ui/lab/Autocomplete'; import { ChangeEvent, FocusEvent, useEffect, useState } from 'react'; import axios from 'axios' import { config } from "dotenv"; import { Report, Reports } from './Types'; import { ColDef, DataGrid, PageChangeParams, ValueFormatterParams } from '@material-ui/data-grid'; import Alert from '@material-ui/lab/Alert'; import Tabs from '@material-ui/core/Tabs'; import Backdrop from '@material-ui/core/Backdrop'; import { AutocompleteChangeReason } from '@material-ui/lab'; config(); const useStyles = makeStyles((theme: Theme) => createStyles({ root: { flexGrow: 1, }, backdrop: { zIndex: theme.zIndex.drawer + 1, color: '#fff', position: 'absolute', width: '100%' }, }), ); const ValidatorReport = () => { const dateFormat = 'yyyy-MM-DD'; const [backendUrl, setBackendUrl] = useState(process.env.REACT_APP_BACKEND_URL || "http://localhost:3500"); const [activeValidators, setActiveValidators] = useState([]); const [lastBlock, setLastBlock] = useState(0); const [stash, setStash] = useState('5EhDdcWm4TdqKp1ew1PqtSpoAELmjbZZLm5E34aFoVYkXdRW'); const [dateFrom, setDateFrom] = useState(moment().subtract(14, 'd').format(dateFormat)); const [dateTo, setDateTo] = useState(moment().format(dateFormat)); const [startBlock, setStartBlock] = useState('' as unknown as number); const [endBlock, setEndBlock] = useState('' as unknown as number); const [isLoading, setIsLoading] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); const [error, setError] = useState(undefined); const [currentPage, setCurrentPage] = useState(1); const [filterTab, setFilterTab] = useState(0 as number); const [columns] = useState( [ { field: 'id', headerName: 'Era', width: 150, sortable: true }, { field: 'stakeTotal', headerName: 'Total Stake', width: 150, sortable: true }, { field: 'stakeOwn', headerName: 'Own Stake', width: 150, sortable: true }, { field: 'points', headerName: 'Points', width: 150, sortable: true }, { field: 'rewards', headerName: 'Rewards', width: 150, sortable: true }, { field: 'commission', headerName: 'Commission', width: 150, sortable: true, valueFormatter: (params: ValueFormatterParams) => { if (isNaN(params.value as unknown as number)) { return `${params.value}%` } return `${Number(params.value).toFixed(0)}%` }}, { field: 'blocksCount', headerName: 'Blocks Produced', width: 150, sortable: true }, ] ); const [report, setReport] = useState({ pageSize: 0, totalCount: 0, totalBlocks: 0, startEra: -1, endEra: -1, startBlock: -1, endBlock: -1, startTime: -1, endTime: -1, report: [] as unknown as Report[] } as unknown as Reports ); const isDateRange = filterTab === 0; const isBlockRange = filterTab === 1; useEffect(() => { updateChainState() const interval = setInterval(() => { updateChainState() }, 10000); return () => clearInterval(interval); }, []); const updateChainState = () => { getChainState().then((chainState) => { setLastBlock(chainState.finalizedBlockHeight) setActiveValidators(chainState.validators.validators) }) } const handlePageChange = (params: PageChangeParams) => { if (report.totalCount > 0) { loadReport(params.page) } } const loadReport = (page: number) => { setCurrentPage(page) setIsLoading(true) const blockParam = isBlockRange && startBlock && endBlock ? `&start_block=${startBlock}&end_block=${endBlock}` : '' const dateParam = isDateRange && dateFrom && dateTo ? `&start_time=${moment(dateFrom, dateFormat).format(dateFormat)}&end_time=${moment(dateTo, dateFormat).format(dateFormat)}` : '' const apiUrl = `${backendUrl}/validator-report?addr=${stash}&page=${page}${blockParam}${dateParam}` axios.get(apiUrl).then((response) => { if (response.data.report !== undefined) { setReport(response.data); } setIsLoading(false) setError(undefined) }).catch((err) => { setIsLoading(false) setError(err) }) } const stopLoadingReport = () => { setIsLoading(false) } const canLoadReport = () => stash && ((isBlockRange && startBlock && endBlock) || (isDateRange && dateFrom && dateTo)) const startOrStopLoading = () => isLoading ? stopLoadingReport() : loadReport(1) const updateStartBlock = (e: { target: { value: unknown; }; }) => setStartBlock((e.target.value as unknown as number)); const updateEndBlock = (e: { target: { value: unknown; }; }) => setEndBlock((e.target.value as unknown as number)); const updateDateFrom = (e: { target: { value: unknown; }; }) => setDateFrom((e.target.value as unknown as string)) const updateDateTo = (e: { target: { value: unknown; }; }) => setDateTo((e.target.value as unknown as string)); const setCurrentPeriodStartBlock = () => { const blocksToEndOfDay = moment().endOf('d').diff(moment(), "seconds") / 6 const twoWeeksBlocks = (600 * 24 * 14); return setStartBlock(lastBlock - twoWeeksBlocks - Number(blocksToEndOfDay.toFixed(0))) } const setCurrentPeriodEndBlock = () => setEndBlock(lastBlock) const getButtonTitle = (isLoading: boolean) => { if (isLoading) { return (