Commit a0c383ef authored by tom's avatar tom

validators page

parent 6290429c
...@@ -362,6 +362,7 @@ ...@@ -362,6 +362,7 @@
"arbitrum", "arbitrum",
"arbitrum_sepolia", "arbitrum_sepolia",
"base", "base",
"blackfort_testnet",
"celo_alfajores", "celo_alfajores",
"garnet", "garnet",
"gnosis", "gnosis",
......
...@@ -8,26 +8,26 @@ import config from 'configs/app'; ...@@ -8,26 +8,26 @@ import config from 'configs/app';
const validatorsFeature = config.features.validators; const validatorsFeature = config.features.validators;
// const Validators = dynamic(() => { const Validators = dynamic(() => {
// if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'stability') { if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'stability') {
// return import('ui/pages/ValidatorsStability'); return import('ui/pages/ValidatorsStability');
// } }
// if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'blackfort') { if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'blackfort') {
// return import('ui/pages/ValidatorsBlackfort'); return import('ui/pages/ValidatorsBlackfort');
// } }
// if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'zilliqa') { if (validatorsFeature.isEnabled && validatorsFeature.chainType === 'zilliqa') {
// return import('ui/pages/ValidatorsZilliqa'); return import('ui/pages/ValidatorsZilliqa');
// } }
// throw new Error('Validators feature is not enabled.'); throw new Error('Validators feature is not enabled.');
// }, { ssr: false }); }, { ssr: false });
const Page: NextPage = () => { const Page: NextPage = () => {
return ( return (
<PageNextJs pathname="/validators"> <PageNextJs pathname="/validators">
{ /* <Validators/> */ } <Validators/>
</PageNextJs> </PageNextJs>
); );
}; };
......
...@@ -36,10 +36,11 @@ export interface TableColumnHeaderSortableProps<F extends string> extends TableC ...@@ -36,10 +36,11 @@ export interface TableColumnHeaderSortableProps<F extends string> extends TableC
sortValue: string; sortValue: string;
onSortToggle: (sortField: F) => void; onSortToggle: (sortField: F) => void;
disabled?: boolean; disabled?: boolean;
indicatorPosition?: 'left' | 'right';
} }
export const TableColumnHeaderSortable = <F extends string>(props: TableColumnHeaderSortableProps<F>) => { export const TableColumnHeaderSortable = <F extends string>(props: TableColumnHeaderSortableProps<F>) => {
const { sortField, sortValue, onSortToggle, children, disabled, ...rest } = props; const { sortField, sortValue, onSortToggle, children, disabled, indicatorPosition = 'left', ...rest } = props;
const handleSortToggle = React.useCallback(() => { const handleSortToggle = React.useCallback(() => {
onSortToggle(sortField); onSortToggle(sortField);
...@@ -55,7 +56,8 @@ export const TableColumnHeaderSortable = <F extends string>(props: TableColumnHe ...@@ -55,7 +56,8 @@ export const TableColumnHeaderSortable = <F extends string>(props: TableColumnHe
h="100%" h="100%"
transform={ sortValue.toLowerCase().includes('asc') ? 'rotate(-90deg)' : 'rotate(90deg)' } transform={ sortValue.toLowerCase().includes('asc') ? 'rotate(-90deg)' : 'rotate(90deg)' }
position="absolute" position="absolute"
left={ -5 } left={ indicatorPosition === 'left' ? -5 : undefined }
right={ indicatorPosition === 'right' ? -5 : undefined }
top={ 0 } top={ 0 }
/> />
) } ) }
......
...@@ -37,7 +37,7 @@ export interface ValidatorsStabilitySorting { ...@@ -37,7 +37,7 @@ export interface ValidatorsStabilitySorting {
export type ValidatorsStabilitySortingField = ValidatorsStabilitySorting['sort']; export type ValidatorsStabilitySortingField = ValidatorsStabilitySorting['sort'];
export type ValidatorsStabilitySortingValue = `${ ValidatorsStabilitySortingField }-${ ValidatorsStabilitySorting['order'] }`; export type ValidatorsStabilitySortingValue = `${ ValidatorsStabilitySortingField }-${ ValidatorsStabilitySorting['order'] }` | 'default';
// Blackfort // Blackfort
...@@ -68,7 +68,7 @@ export interface ValidatorsBlackfortSorting { ...@@ -68,7 +68,7 @@ export interface ValidatorsBlackfortSorting {
export type ValidatorsBlackfortSortingField = ValidatorsBlackfortSorting['sort']; export type ValidatorsBlackfortSortingField = ValidatorsBlackfortSorting['sort'];
export type ValidatorsBlackfortSortingValue = `${ ValidatorsBlackfortSortingField }-${ ValidatorsBlackfortSorting['order'] }`; export type ValidatorsBlackfortSortingValue = `${ ValidatorsBlackfortSortingField }-${ ValidatorsBlackfortSorting['order'] }` | 'default';
// Zilliqa // Zilliqa
export interface ValidatorsZilliqaItem { export interface ValidatorsZilliqaItem {
......
import { Box, Hide, HStack, Show } from '@chakra-ui/react'; import { Box, createListCollection, HStack } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -24,11 +24,15 @@ import ValidatorsCounters from 'ui/validators/blackfort/ValidatorsCounters'; ...@@ -24,11 +24,15 @@ import ValidatorsCounters from 'ui/validators/blackfort/ValidatorsCounters';
import ValidatorsList from 'ui/validators/blackfort/ValidatorsList'; import ValidatorsList from 'ui/validators/blackfort/ValidatorsList';
import ValidatorsTable from 'ui/validators/blackfort/ValidatorsTable'; import ValidatorsTable from 'ui/validators/blackfort/ValidatorsTable';
const sortCollection = createListCollection({
items: VALIDATORS_BLACKFORT_SORT_OPTIONS,
});
const ValidatorsBlackfort = () => { const ValidatorsBlackfort = () => {
const router = useRouter(); const router = useRouter();
const [ sort, setSort ] = const [ sort, setSort ] =
React.useState<ValidatorsBlackfortSortingValue | undefined>( React.useState<ValidatorsBlackfortSortingValue>(
getSortValueFromQuery<ValidatorsBlackfortSortingValue>(router.query, VALIDATORS_BLACKFORT_SORT_OPTIONS), getSortValueFromQuery<ValidatorsBlackfortSortingValue>(router.query, VALIDATORS_BLACKFORT_SORT_OPTIONS) ?? 'default',
); );
const { isError, isPlaceholderData, data, pagination, onSortingChange } = useQueryWithPages({ const { isError, isPlaceholderData, data, pagination, onSortingChange } = useQueryWithPages({
...@@ -44,23 +48,24 @@ const ValidatorsBlackfort = () => { ...@@ -44,23 +48,24 @@ const ValidatorsBlackfort = () => {
}, },
}); });
const handleSortChange = React.useCallback((value?: ValidatorsBlackfortSortingValue) => { const handleSortChange = React.useCallback(({ value }: { value: Array<string> }) => {
setSort(value); const sortValue = value[0] as ValidatorsBlackfortSortingValue;
onSortingChange(getSortParamsFromValue(value)); setSort(sortValue);
onSortingChange(sortValue === 'default' ? undefined : getSortParamsFromValue(sortValue));
}, [ onSortingChange ]); }, [ onSortingChange ]);
const sortButton = ( const sortButton = (
<Sort <Sort
name="validators_sorting" name="validators_sorting"
defaultValue={ sort } defaultValue={ [ sort ] }
options={ VALIDATORS_BLACKFORT_SORT_OPTIONS } collection={ sortCollection }
onChange={ handleSortChange } onValueChange={ handleSortChange }
/> />
); );
const actionBar = ( const actionBar = (
<> <>
<HStack spacing={ 3 } mb={ 6 } display={{ base: 'flex', lg: 'none' }}> <HStack gap={ 3 } mb={ 6 } display={{ base: 'flex', lg: 'none' }}>
{ sortButton } { sortButton }
</HStack> </HStack>
{ pagination.isVisible && ( { pagination.isVisible && (
...@@ -73,10 +78,10 @@ const ValidatorsBlackfort = () => { ...@@ -73,10 +78,10 @@ const ValidatorsBlackfort = () => {
const content = data?.items ? ( const content = data?.items ? (
<> <>
<Show below="lg" ssr={ false }> <Box hideFrom="lg">
<ValidatorsList data={ data.items } isLoading={ isPlaceholderData }/> <ValidatorsList data={ data.items } isLoading={ isPlaceholderData }/>
</Show> </Box>
<Hide below="lg" ssr={ false }> <Box hideBelow="lg">
<ValidatorsTable <ValidatorsTable
data={ data.items } data={ data.items }
sort={ sort } sort={ sort }
...@@ -84,7 +89,7 @@ const ValidatorsBlackfort = () => { ...@@ -84,7 +89,7 @@ const ValidatorsBlackfort = () => {
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
top={ pagination.isVisible ? ACTION_BAR_HEIGHT_DESKTOP : 0 } top={ pagination.isVisible ? ACTION_BAR_HEIGHT_DESKTOP : 0 }
/> />
</Hide> </Box>
</> </>
) : null; ) : null;
...@@ -94,11 +99,12 @@ const ValidatorsBlackfort = () => { ...@@ -94,11 +99,12 @@ const ValidatorsBlackfort = () => {
<ValidatorsCounters/> <ValidatorsCounters/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } itemsNum={ data?.items.length }
emptyText="There are no validators." emptyText="There are no validators."
content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> >
{ content }
</DataListDisplay>
</Box> </Box>
); );
}; };
......
import { Box, Hide, HStack, Show } from '@chakra-ui/react'; import { Box, createListCollection, HStack } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -31,13 +31,17 @@ import ValidatorsFilter from 'ui/validators/stability/ValidatorsFilter'; ...@@ -31,13 +31,17 @@ import ValidatorsFilter from 'ui/validators/stability/ValidatorsFilter';
import ValidatorsList from 'ui/validators/stability/ValidatorsList'; import ValidatorsList from 'ui/validators/stability/ValidatorsList';
import ValidatorsTable from 'ui/validators/stability/ValidatorsTable'; import ValidatorsTable from 'ui/validators/stability/ValidatorsTable';
const sortCollection = createListCollection({
items: VALIDATORS_STABILITY_SORT_OPTIONS,
});
const ValidatorsStability = () => { const ValidatorsStability = () => {
const router = useRouter(); const router = useRouter();
// const [ searchTerm, setSearchTerm ] = React.useState(getQueryParamString(router.query.address_hash) || undefined); // const [ searchTerm, setSearchTerm ] = React.useState(getQueryParamString(router.query.address_hash) || undefined);
const [ statusFilter, setStatusFilter ] = const [ statusFilter, setStatusFilter ] =
React.useState(getQueryParamString(router.query.state_filter) as ValidatorsStabilityFilters['state_filter'] || undefined); React.useState(getQueryParamString(router.query.state_filter) as ValidatorsStabilityFilters['state_filter'] || undefined);
const [ sort, setSort ] = React.useState<ValidatorsStabilitySortingValue | undefined>( const [ sort, setSort ] = React.useState<ValidatorsStabilitySortingValue>(
getSortValueFromQuery<ValidatorsStabilitySortingValue>(router.query, VALIDATORS_STABILITY_SORT_OPTIONS), getSortValueFromQuery<ValidatorsStabilitySortingValue>(router.query, VALIDATORS_STABILITY_SORT_OPTIONS) ?? 'default',
); );
// const debouncedSearchTerm = useDebounce(searchTerm || '', 300); // const debouncedSearchTerm = useDebounce(searchTerm || '', 300);
...@@ -83,9 +87,10 @@ const ValidatorsStability = () => { ...@@ -83,9 +87,10 @@ const ValidatorsStability = () => {
setStatusFilter(state); setStatusFilter(state);
}, [ onFilterChange ]); }, [ onFilterChange ]);
const handleSortChange = React.useCallback((value?: ValidatorsStabilitySortingValue) => { const handleSortChange = React.useCallback(({ value }: { value: Array<string> }) => {
setSort(value); const sortValue = value[0] as ValidatorsStabilitySortingValue;
onSortingChange(getSortParamsFromValue(value)); setSort(sortValue);
onSortingChange(sortValue === 'default' ? undefined : getSortParamsFromValue(sortValue));
}, [ onSortingChange ]); }, [ onSortingChange ]);
const filterMenu = const filterMenu =
...@@ -104,22 +109,22 @@ const ValidatorsStability = () => { ...@@ -104,22 +109,22 @@ const ValidatorsStability = () => {
const sortButton = ( const sortButton = (
<Sort <Sort
name="validators_sorting" name="validators_sorting"
defaultValue={ sort } defaultValue={ [ sort ] }
options={ VALIDATORS_STABILITY_SORT_OPTIONS } collection={ sortCollection }
onChange={ handleSortChange } onValueChange={ handleSortChange }
/> />
); );
const actionBar = ( const actionBar = (
<> <>
<HStack spacing={ 3 } mb={ 6 } display={{ base: 'flex', lg: 'none' }}> <HStack gap={ 3 } mb={ 6 } display={{ base: 'flex', lg: 'none' }}>
{ filterMenu } { filterMenu }
{ sortButton } { sortButton }
{ /* { filterInput } */ } { /* { filterInput } */ }
</HStack> </HStack>
{ (!isMobile || pagination.isVisible) && ( { (!isMobile || pagination.isVisible) && (
<ActionBar mt={ -6 }> <ActionBar mt={ -6 }>
<HStack spacing={ 3 } display={{ base: 'none', lg: 'flex' }}> <HStack gap={ 3 } display={{ base: 'none', lg: 'flex' }}>
{ filterMenu } { filterMenu }
{ /* { filterInput } */ } { /* { filterInput } */ }
</HStack> </HStack>
...@@ -131,12 +136,12 @@ const ValidatorsStability = () => { ...@@ -131,12 +136,12 @@ const ValidatorsStability = () => {
const content = data?.items ? ( const content = data?.items ? (
<> <>
<Show below="lg" ssr={ false }> <Box hideFrom="lg">
<ValidatorsList data={ data.items } isLoading={ isPlaceholderData }/> <ValidatorsList data={ data.items } isLoading={ isPlaceholderData }/>
</Show> </Box>
<Hide below="lg" ssr={ false }> <Box hideBelow="lg">
<ValidatorsTable data={ data.items } sort={ sort } setSorting={ handleSortChange } isLoading={ isPlaceholderData }/> <ValidatorsTable data={ data.items } sort={ sort } setSorting={ handleSortChange } isLoading={ isPlaceholderData }/>
</Hide> </Box>
</> </>
) : null; ) : null;
...@@ -146,7 +151,7 @@ const ValidatorsStability = () => { ...@@ -146,7 +151,7 @@ const ValidatorsStability = () => {
<ValidatorsCounters/> <ValidatorsCounters/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } itemsNum={ data?.items.length }
emptyText="There are no validators." emptyText="There are no validators."
filterProps={{ filterProps={{
emptyFilteredText: `Couldn${ apos }t find any validator that matches your query.`, emptyFilteredText: `Couldn${ apos }t find any validator that matches your query.`,
...@@ -155,9 +160,10 @@ const ValidatorsStability = () => { ...@@ -155,9 +160,10 @@ const ValidatorsStability = () => {
statusFilter, statusFilter,
), ),
}} }}
content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> >
{ content }
</DataListDisplay>
</Box> </Box>
); );
}; };
......
import { Box, Hide, Show } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
...@@ -37,12 +37,12 @@ const ValidatorsZilliqa = () => { ...@@ -37,12 +37,12 @@ const ValidatorsZilliqa = () => {
const content = data?.items ? ( const content = data?.items ? (
<> <>
<Show below="lg" ssr={ false }> <Box hideFrom="lg">
<ValidatorsList data={ data.items } isLoading={ isPlaceholderData }/> <ValidatorsList data={ data.items } isLoading={ isPlaceholderData }/>
</Show> </Box>
<Hide below="lg" ssr={ false }> <Box hideBelow="lg">
<ValidatorsTable data={ data.items } isLoading={ isPlaceholderData }/> <ValidatorsTable data={ data.items } isLoading={ isPlaceholderData }/>
</Hide> </Box>
</> </>
) : null; ) : null;
...@@ -51,11 +51,12 @@ const ValidatorsZilliqa = () => { ...@@ -51,11 +51,12 @@ const ValidatorsZilliqa = () => {
<PageTitle title="Validators" withTextAd/> <PageTitle title="Validators" withTextAd/>
<DataListDisplay <DataListDisplay
isError={ isError } isError={ isError }
items={ data?.items } itemsNum={ data?.items.length }
emptyText="There are no validators." emptyText="There are no validators."
content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> >
{ content }
</DataListDisplay>
</Box> </Box>
); );
}; };
......
import { Alert, AlertIcon, AlertTitle } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
...@@ -12,7 +11,8 @@ import * as cookies from 'lib/cookies'; ...@@ -12,7 +11,8 @@ import * as cookies from 'lib/cookies';
import { nbsp, ndash } from 'lib/html-entities'; import { nbsp, ndash } from 'lib/html-entities';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Alert } from 'toolkit/chakra/alert';
import { Skeleton } from 'toolkit/chakra/skeleton';
const IndexingBlocksAlert = () => { const IndexingBlocksAlert = () => {
const appProps = useAppContext(); const appProps = useAppContext();
...@@ -64,7 +64,7 @@ const IndexingBlocksAlert = () => { ...@@ -64,7 +64,7 @@ const IndexingBlocksAlert = () => {
} }
if (isPending) { if (isPending) {
return hasAlertCookie ? <Skeleton h={{ base: '96px', lg: '48px' }} w="100%"/> : null; return hasAlertCookie ? <Skeleton loading h={{ base: '96px', lg: '48px' }} w="100%"/> : null;
} }
if (data.finished_indexing_blocks !== false) { if (data.finished_indexing_blocks !== false) {
...@@ -73,11 +73,8 @@ const IndexingBlocksAlert = () => { ...@@ -73,11 +73,8 @@ const IndexingBlocksAlert = () => {
return ( return (
<Alert status="info" colorScheme="gray" py={ 3 } borderRadius="md"> <Alert status="info" colorScheme="gray" py={ 3 } borderRadius="md">
<AlertIcon display={{ base: 'none', lg: 'flex' }}/>
<AlertTitle>
{ `${ data.indexed_blocks_ratio && `${ Math.floor(Number(data.indexed_blocks_ratio) * 100) }% Blocks Indexed${ nbsp }${ ndash } ` } { `${ data.indexed_blocks_ratio && `${ Math.floor(Number(data.indexed_blocks_ratio) * 100) }% Blocks Indexed${ nbsp }${ ndash } ` }
We're indexing this chain right now. Some of the counts may be inaccurate.` } We're indexing this chain right now. Some of the counts may be inaccurate.` }
</AlertTitle>
</Alert> </Alert>
); );
}; };
......
...@@ -6,7 +6,7 @@ import type { ValidatorBlackfort } from 'types/api/validators'; ...@@ -6,7 +6,7 @@ import type { ValidatorBlackfort } from 'types/api/validators';
import config from 'configs/app'; import config from 'configs/app';
import { currencyUnits } from 'lib/units'; import { currencyUnits } from 'lib/units';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid'; import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
...@@ -30,28 +30,32 @@ const ValidatorsListItem = ({ data, isLoading }: Props) => { ...@@ -30,28 +30,32 @@ const ValidatorsListItem = ({ data, isLoading }: Props) => {
/> />
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
{ data.name && (
<>
<ListItemMobileGrid.Label isLoading={ isLoading }>Name</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Name</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Flex><TruncatedValue value={ data.name } isLoading={ isLoading }/></Flex> <Flex><TruncatedValue value={ data.name } isLoading={ isLoading }/></Flex>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
</>
) }
<ListItemMobileGrid.Label isLoading={ isLoading }>Commission</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Commission</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ `${ data.commission / 100 }%` } { `${ data.commission / 100 }%` }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Self bonded</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Self bonded</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ `${ BigNumber(data.self_bonded_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } ${ currencyUnits.ether }` } { `${ BigNumber(data.self_bonded_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } ${ currencyUnits.ether }` }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Delegated amount</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Delegated amount</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ `${ BigNumber(data.delegated_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } ${ currencyUnits.ether }` } { `${ BigNumber(data.delegated_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } ${ currencyUnits.ether }` }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
......
import { Table, Tbody, Tr, Th, Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { import type {
ValidatorBlackfort, ValidatorBlackfort,
ValidatorsBlackfortSorting,
ValidatorsBlackfortSortingField, ValidatorsBlackfortSortingField,
ValidatorsBlackfortSortingValue, ValidatorsBlackfortSortingValue,
} from 'types/api/validators'; } from 'types/api/validators';
import { currencyUnits } from 'lib/units'; import { currencyUnits } from 'lib/units';
import IconSvg from 'ui/shared/IconSvg'; import { TableBody, TableColumnHeader, TableColumnHeaderSortable, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import getNextSortValue from 'ui/shared/sort/getNextSortValue'; import getNextSortValue from 'ui/shared/sort/getNextSortValue';
import { default as Thead } from 'ui/shared/TheadSticky';
import { VALIDATORS_BLACKFORT_SORT_SEQUENCE } from './utils'; import { VALIDATORS_BLACKFORT_SORT_SEQUENCE } from './utils';
import ValidatorsTableItem from './ValidatorsTableItem'; import ValidatorsTableItem from './ValidatorsTableItem';
interface Props { interface Props {
data: Array<ValidatorBlackfort>; data: Array<ValidatorBlackfort>;
sort: ValidatorsBlackfortSortingValue | undefined; sort: ValidatorsBlackfortSortingValue;
setSorting: (val: ValidatorsBlackfortSortingValue | undefined) => void; setSorting: ({ value }: { value: Array<string> }) => void;
isLoading?: boolean; isLoading?: boolean;
top: number; top: number;
} }
const ValidatorsTable = ({ data, sort, setSorting, isLoading, top }: Props) => { const ValidatorsTable = ({ data, sort, setSorting, isLoading, top }: Props) => {
const sortIconTransform = sort?.includes('asc' as ValidatorsBlackfortSorting['order']) ? 'rotate(-90deg)' : 'rotate(90deg)';
const onSortToggle = React.useCallback((field: ValidatorsBlackfortSortingField) => () => { const onSortToggle = React.useCallback((field: ValidatorsBlackfortSortingField) => {
const value = getNextSortValue<ValidatorsBlackfortSortingField, ValidatorsBlackfortSortingValue>(VALIDATORS_BLACKFORT_SORT_SEQUENCE, field)(sort); const value = getNextSortValue<ValidatorsBlackfortSortingField, ValidatorsBlackfortSortingValue>(VALIDATORS_BLACKFORT_SORT_SEQUENCE, field)(sort);
setSorting(value); setSorting({ value: [ value ] });
}, [ sort, setSorting ]); }, [ sort, setSorting ]);
return ( return (
<Table> <TableRoot>
<Thead top={ top }> <TableHeaderSticky top={ top }>
<Tr> <TableRow>
<Th> <TableColumnHeaderSortable
<Link sortField="address_hash"
display="flex" sortValue={ sort }
alignItems="center" onSortToggle={ onSortToggle }
onClick={ isLoading ? undefined : onSortToggle('address_hash') } indicatorPosition="right"
columnGap={ 1 }
> >
{ sort?.includes('address') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Validator’s address Validator’s address
</Link> </TableColumnHeaderSortable>
</Th> <TableColumnHeader>Name</TableColumnHeader>
<Th>Name</Th> <TableColumnHeader isNumeric>Commission</TableColumnHeader>
<Th isNumeric>Commission</Th> <TableColumnHeader isNumeric>{ `Self bonded ${ currencyUnits.ether }` }</TableColumnHeader>
<Th isNumeric>{ `Self bonded ${ currencyUnits.ether }` }</Th> <TableColumnHeader isNumeric>{ `Delegated amount ${ currencyUnits.ether }` }</TableColumnHeader>
<Th isNumeric>{ `Delegated amount ${ currencyUnits.ether }` }</Th> </TableRow>
</Tr> </TableHeaderSticky>
</Thead> <TableBody>
<Tbody>
{ data.map((item, index) => ( { data.map((item, index) => (
<ValidatorsTableItem <ValidatorsTableItem
key={ item.address.hash + (isLoading ? index : '') } key={ item.address.hash + (isLoading ? index : '') }
data={ item } data={ item }
isLoading={ isLoading }/> isLoading={ isLoading }/>
)) } )) }
</Tbody> </TableBody>
</Table> </TableRoot>
); );
}; };
......
import { Tr, Td, Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { ValidatorBlackfort } from 'types/api/validators'; import type { ValidatorBlackfort } from 'types/api/validators';
import config from 'configs/app'; import config from 'configs/app';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableCell, TableRow } from 'toolkit/chakra/table';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
...@@ -16,35 +17,35 @@ interface Props { ...@@ -16,35 +17,35 @@ interface Props {
const ValidatorsTableItem = ({ data, isLoading }: Props) => { const ValidatorsTableItem = ({ data, isLoading }: Props) => {
return ( return (
<Tr> <TableRow>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<AddressEntity <AddressEntity
address={ data.address } address={ data.address }
isLoading={ isLoading } isLoading={ isLoading }
truncation="constant" truncation="constant"
/> />
</Td> </TableCell>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<Flex> <Flex>
<TruncatedValue value={ data.name } isLoading={ isLoading }/> <TruncatedValue value={ data.name } isLoading={ isLoading }/>
</Flex> </Flex>
</Td> </TableCell>
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ `${ data.commission / 100 }%` } { `${ data.commission / 100 }%` }
</Skeleton> </Skeleton>
</Td> </TableCell>
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ BigNumber(data.self_bonded_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { BigNumber(data.self_bonded_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() }
</Skeleton> </Skeleton>
</Td> </TableCell>
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ BigNumber(data.delegated_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { BigNumber(data.delegated_amount).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() }
</Skeleton> </Skeleton>
</Td> </TableCell>
</Tr> </TableRow>
); );
}; };
......
...@@ -2,14 +2,15 @@ import type { ...@@ -2,14 +2,15 @@ import type {
ValidatorsBlackfortSortingValue, ValidatorsBlackfortSortingValue,
ValidatorsBlackfortSortingField, ValidatorsBlackfortSortingField,
} from 'types/api/validators'; } from 'types/api/validators';
import type { SelectOption } from 'toolkit/chakra/select'; import type { SelectOption } from 'toolkit/chakra/select';
export const VALIDATORS_BLACKFORT_SORT_OPTIONS: Array<SelectOption<ValidatorsBlackfortSortingValue>> = [ export const VALIDATORS_BLACKFORT_SORT_OPTIONS: Array<SelectOption<ValidatorsBlackfortSortingValue>> = [
{ label: 'Default', value: undefined }, { label: 'Default', value: 'default' },
{ label: 'Address descending', value: 'address_hash-desc' }, { label: 'Address descending', value: 'address_hash-desc' },
{ label: 'Address ascending', value: 'address_hash-asc' }, { label: 'Address ascending', value: 'address_hash-asc' },
]; ];
export const VALIDATORS_BLACKFORT_SORT_SEQUENCE: Record<ValidatorsBlackfortSortingField, Array<ValidatorsBlackfortSortingValue | undefined>> = { export const VALIDATORS_BLACKFORT_SORT_SEQUENCE: Record<ValidatorsBlackfortSortingField, Array<ValidatorsBlackfortSortingValue>> = {
address_hash: [ 'address_hash-desc', 'address_hash-asc', undefined ], address_hash: [ 'address_hash-desc', 'address_hash-asc', 'default' ],
}; };
import { createListCollection } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { ValidatorsStabilityFilters } from 'types/api/validators'; import type { ValidatorsStabilityFilters } from 'types/api/validators';
...@@ -11,6 +12,10 @@ const OPTIONS = [ ...@@ -11,6 +12,10 @@ const OPTIONS = [
{ value: 'inactive', label: 'Inactive' }, { value: 'inactive', label: 'Inactive' },
]; ];
const collection = createListCollection({
items: OPTIONS,
});
interface Props { interface Props {
hasActiveFilter: boolean; hasActiveFilter: boolean;
defaultValue: ValidatorsStabilityFilters['state_filter'] | undefined; defaultValue: ValidatorsStabilityFilters['state_filter'] | undefined;
...@@ -21,10 +26,10 @@ const ValidatorsFilter = ({ onChange, defaultValue, hasActiveFilter }: Props) => ...@@ -21,10 +26,10 @@ const ValidatorsFilter = ({ onChange, defaultValue, hasActiveFilter }: Props) =>
return ( return (
<PopoverFilterRadio <PopoverFilterRadio
name="validators_filter" name="validators_filter"
options={ OPTIONS } collection={ collection }
onChange={ onChange } onChange={ onChange }
hasActiveFilter={ hasActiveFilter } hasActiveFilter={ hasActiveFilter }
defaultValue={ defaultValue || OPTIONS[0].value } initialValue={ defaultValue || OPTIONS[0].value }
/> />
); );
}; };
......
...@@ -2,7 +2,7 @@ import React from 'react'; ...@@ -2,7 +2,7 @@ import React from 'react';
import type { ValidatorStability } from 'types/api/validators'; import type { ValidatorStability } from 'types/api/validators';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid'; import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
import ValidatorStatus from 'ui/shared/statusTag/ValidatorStabilityStatus'; import ValidatorStatus from 'ui/shared/statusTag/ValidatorStabilityStatus';
...@@ -33,7 +33,7 @@ const ValidatorsListItem = ({ data, isLoading }: Props) => { ...@@ -33,7 +33,7 @@ const ValidatorsListItem = ({ data, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>Blocks</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Blocks</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ data.blocks_validated_count.toLocaleString() } { data.blocks_validated_count.toLocaleString() }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
......
import { Table, Tbody, Tr, Th, Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { import type {
ValidatorStability, ValidatorStability,
ValidatorsStabilitySorting,
ValidatorsStabilitySortingField, ValidatorsStabilitySortingField,
ValidatorsStabilitySortingValue, ValidatorsStabilitySortingValue,
} from 'types/api/validators'; } from 'types/api/validators';
import { TableBody, TableColumnHeader, TableColumnHeaderSortable, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar'; import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
import IconSvg from 'ui/shared/IconSvg';
import getNextSortValue from 'ui/shared/sort/getNextSortValue'; import getNextSortValue from 'ui/shared/sort/getNextSortValue';
import { default as Thead } from 'ui/shared/TheadSticky';
import { VALIDATORS_STABILITY_SORT_SEQUENCE } from './utils'; import { VALIDATORS_STABILITY_SORT_SEQUENCE } from './utils';
import ValidatorsTableItem from './ValidatorsTableItem'; import ValidatorsTableItem from './ValidatorsTableItem';
interface Props { interface Props {
data: Array<ValidatorStability>; data: Array<ValidatorStability>;
sort: ValidatorsStabilitySortingValue | undefined; sort: ValidatorsStabilitySortingValue;
setSorting: (val: ValidatorsStabilitySortingValue | undefined) => void; setSorting: ({ value }: { value: Array<ValidatorsStabilitySortingValue> }) => void;
isLoading?: boolean; isLoading?: boolean;
} }
const ValidatorsTable = ({ data, sort, setSorting, isLoading }: Props) => { const ValidatorsTable = ({ data, sort, setSorting, isLoading }: Props) => {
const sortIconTransform = sort?.includes('asc' as ValidatorsStabilitySorting['order']) ? 'rotate(-90deg)' : 'rotate(90deg)';
const onSortToggle = React.useCallback((field: ValidatorsStabilitySortingField) => () => { const onSortToggle = React.useCallback((field: ValidatorsStabilitySortingField) => {
const value = getNextSortValue<ValidatorsStabilitySortingField, ValidatorsStabilitySortingValue>(VALIDATORS_STABILITY_SORT_SEQUENCE, field)(sort); const value = getNextSortValue<ValidatorsStabilitySortingField, ValidatorsStabilitySortingValue>(VALIDATORS_STABILITY_SORT_SEQUENCE, field)(sort);
setSorting(value); setSorting({ value: [ value ] });
}, [ sort, setSorting ]); }, [ sort, setSorting ]);
return ( return (
<Table> <TableRoot>
<Thead top={ ACTION_BAR_HEIGHT_DESKTOP }> <TableHeaderSticky top={ ACTION_BAR_HEIGHT_DESKTOP }>
<Tr> <TableRow>
<Th width="50%">Validator’s address</Th> <TableColumnHeader width="50%">Validator’s address</TableColumnHeader>
<Th width="25%"> <TableColumnHeaderSortable
<Link width="25%"
display="flex" sortField="state"
alignItems="center" sortValue={ sort }
onClick={ isLoading ? undefined : onSortToggle('state') } onSortToggle={ onSortToggle }
columnGap={ 1 }
> >
{ sort?.includes('state') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Status Status
</Link> </TableColumnHeaderSortable>
</Th> <TableColumnHeaderSortable
<Th width="25%" isNumeric> width="25%"
<Link sortField="blocks_validated"
display="flex" sortValue={ sort }
alignItems="center" onSortToggle={ onSortToggle }
justifyContent="flex-end" isNumeric
onClick={ isLoading ? undefined : onSortToggle('blocks_validated') }
columnGap={ 1 }
> >
{ sort?.includes('blocks_validated') && <IconSvg name="arrows/east" boxSize={ 4 } transform={ sortIconTransform }/> }
Blocks Blocks
</Link> </TableColumnHeaderSortable>
</Th> </TableRow>
</Tr> </TableHeaderSticky>
</Thead> <TableBody>
<Tbody>
{ data.map((item, index) => ( { data.map((item, index) => (
<ValidatorsTableItem <ValidatorsTableItem
key={ item.address.hash + (isLoading ? index : '') } key={ item.address.hash + (isLoading ? index : '') }
data={ item } data={ item }
isLoading={ isLoading }/> isLoading={ isLoading }/>
)) } )) }
</Tbody> </TableBody>
</Table> </TableRoot>
); );
}; };
......
import { Tr, Td } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { ValidatorStability } from 'types/api/validators'; import type { ValidatorStability } from 'types/api/validators';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableCell, TableRow } from 'toolkit/chakra/table';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ValidatorStatus from 'ui/shared/statusTag/ValidatorStabilityStatus'; import ValidatorStatus from 'ui/shared/statusTag/ValidatorStabilityStatus';
...@@ -14,23 +14,23 @@ interface Props { ...@@ -14,23 +14,23 @@ interface Props {
const ValidatorsTableItem = ({ data, isLoading }: Props) => { const ValidatorsTableItem = ({ data, isLoading }: Props) => {
return ( return (
<Tr> <TableRow>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<AddressEntity <AddressEntity
address={ data.address } address={ data.address }
isLoading={ isLoading } isLoading={ isLoading }
truncation="constant" truncation="constant"
/> />
</Td> </TableCell>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<ValidatorStatus state={ data.state } isLoading={ isLoading }/> <ValidatorStatus state={ data.state } isLoading={ isLoading }/>
</Td> </TableCell>
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading }>
{ data.blocks_validated_count.toLocaleString() } { data.blocks_validated_count.toLocaleString() }
</Skeleton> </Skeleton>
</Td> </TableCell>
</Tr> </TableRow>
); );
}; };
......
...@@ -2,17 +2,18 @@ import type { ...@@ -2,17 +2,18 @@ import type {
ValidatorsStabilitySortingValue, ValidatorsStabilitySortingValue,
ValidatorsStabilitySortingField, ValidatorsStabilitySortingField,
} from 'types/api/validators'; } from 'types/api/validators';
import type { SelectOption } from 'toolkit/chakra/select'; import type { SelectOption } from 'toolkit/chakra/select';
export const VALIDATORS_STABILITY_SORT_OPTIONS: Array<SelectOption<ValidatorsStabilitySortingValue>> = [ export const VALIDATORS_STABILITY_SORT_OPTIONS: Array<SelectOption<ValidatorsStabilitySortingValue>> = [
{ label: 'Default', value: undefined }, { label: 'Default', value: 'default' },
{ label: 'Status descending', value: 'state-desc' }, { label: 'Status descending', value: 'state-desc' },
{ label: 'Status ascending', value: 'state-asc' }, { label: 'Status ascending', value: 'state-asc' },
{ label: 'Blocks validated descending', value: 'blocks_validated-desc' }, { label: 'Blocks validated descending', value: 'blocks_validated-desc' },
{ label: 'Blocks validated ascending', value: 'blocks_validated-asc' }, { label: 'Blocks validated ascending', value: 'blocks_validated-asc' },
]; ];
export const VALIDATORS_STABILITY_SORT_SEQUENCE: Record<ValidatorsStabilitySortingField, Array<ValidatorsStabilitySortingValue | undefined>> = { export const VALIDATORS_STABILITY_SORT_SEQUENCE: Record<ValidatorsStabilitySortingField, Array<ValidatorsStabilitySortingValue>> = {
state: [ 'state-desc', 'state-asc', undefined ], state: [ 'state-desc', 'state-asc', 'default' ],
blocks_validated: [ 'blocks_validated-desc', 'blocks_validated-asc', undefined ], blocks_validated: [ 'blocks_validated-desc', 'blocks_validated-asc', 'default' ],
}; };
...@@ -5,10 +5,10 @@ import React from 'react'; ...@@ -5,10 +5,10 @@ import React from 'react';
import type { ValidatorZilliqa } from 'types/api/validators'; import type { ValidatorZilliqa } from 'types/api/validators';
import config from 'configs/app'; import config from 'configs/app';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem'; import DetailedInfoSponsoredItem from 'ui/shared/DetailedInfo/DetailedInfoSponsoredItem';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
...@@ -22,97 +22,97 @@ interface Props { ...@@ -22,97 +22,97 @@ interface Props {
const ValidatorDetails = ({ data, isLoading }: Props) => { const ValidatorDetails = ({ data, isLoading }: Props) => {
return ( return (
<Grid columnGap={ 8 } rowGap={ 3 } templateColumns={{ base: 'minmax(0, 1fr)', lg: 'max-content minmax(728px, auto)' }}> <Grid columnGap={ 8 } rowGap={ 3 } templateColumns={{ base: 'minmax(0, 1fr)', lg: 'max-content minmax(728px, auto)' }}>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="Index of the staker in the committee" hint="Index of the staker in the committee"
isLoading={ isLoading } isLoading={ isLoading }
> >
Index Index
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !isLoading } display="inline"> <Skeleton loading={ isLoading } display="inline">
{ data.index } { data.index }
</Skeleton> </Skeleton>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="Staker's balance" hint="Staker's balance"
isLoading={ isLoading } isLoading={ isLoading }
> >
Staked Staked
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<NativeTokenIcon isLoading={ isLoading } boxSize={ 5 } mr={ 2 }/> <NativeTokenIcon isLoading={ isLoading } boxSize={ 5 } mr={ 2 }/>
<Skeleton isLoaded={ !isLoading } display="inline"> <Skeleton loading={ isLoading } display="inline">
{ BigNumber(data.balance).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { config.chain.currency.symbol } { BigNumber(data.balance).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { config.chain.currency.symbol }
</Skeleton> </Skeleton>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="libp2p peer ID, corresponding to the staker's BLS public key" hint="libp2p peer ID, corresponding to the staker's BLS public key"
isLoading={ isLoading } isLoading={ isLoading }
> >
Peer ID Peer ID
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<Flex alignItems="center" w="100%" minWidth={ 0 }> <Flex alignItems="center" w="100%" minWidth={ 0 }>
<Skeleton isLoaded={ !isLoading } maxW="calc(100% - 28px)" overflow="hidden"> <Skeleton loading={ isLoading } maxW="calc(100% - 28px)" overflow="hidden">
<HashStringShortenDynamic hash={ data.peer_id }/> <HashStringShortenDynamic hash={ data.peer_id }/>
</Skeleton> </Skeleton>
<CopyToClipboard text={ data.peer_id } isLoading={ isLoading }/> <CopyToClipboard text={ data.peer_id } isLoading={ isLoading }/>
</Flex> </Flex>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="The address used for authenticating requests from this staker to the deposit contract" hint="The address used for authenticating requests from this staker to the deposit contract"
isLoading={ isLoading } isLoading={ isLoading }
> >
Control address Control address
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<AddressEntity address={ data.control_address } isLoading={ isLoading }/> <AddressEntity address={ data.control_address } isLoading={ isLoading }/>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="The address which rewards for this staker will be sent to" hint="The address which rewards for this staker will be sent to"
isLoading={ isLoading } isLoading={ isLoading }
> >
Reward address Reward address
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<AddressEntity address={ data.reward_address } isLoading={ isLoading }/> <AddressEntity address={ data.reward_address } isLoading={ isLoading }/>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="The address whose key the validator uses to sign cross-chain events" hint="The address whose key the validator uses to sign cross-chain events"
isLoading={ isLoading } isLoading={ isLoading }
> >
Signing address Signing address
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<AddressEntity address={ data.signing_address } isLoading={ isLoading }/> <AddressEntity address={ data.signing_address } isLoading={ isLoading }/>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="Block number at which the staker was added" hint="Block number at which the staker was added"
isLoading={ isLoading } isLoading={ isLoading }
> >
Added at block Added at block
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<BlockEntity number={ data.added_at_block_number } isLoading={ isLoading }/> <BlockEntity number={ data.added_at_block_number } isLoading={ isLoading }/>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsInfoItem.Label <DetailedInfo.ItemLabel
hint="Block number at which the staker's stake was last updated" hint="Block number at which the staker's stake was last updated"
isLoading={ isLoading } isLoading={ isLoading }
> >
Stake updated Stake updated
</DetailsInfoItem.Label> </DetailedInfo.ItemLabel>
<DetailsInfoItem.Value> <DetailedInfo.ItemValue>
<BlockEntity number={ data.stake_updated_at_block_number } isLoading={ isLoading }/> <BlockEntity number={ data.stake_updated_at_block_number } isLoading={ isLoading }/>
</DetailsInfoItem.Value> </DetailedInfo.ItemValue>
<DetailsSponsoredItem isLoading={ isLoading }/> <DetailedInfoSponsoredItem isLoading={ isLoading }/>
</Grid> </Grid>
); );
}; };
......
...@@ -4,7 +4,7 @@ import React from 'react'; ...@@ -4,7 +4,7 @@ import React from 'react';
import type { ValidatorsZilliqaItem } from 'types/api/validators'; import type { ValidatorsZilliqaItem } from 'types/api/validators';
import config from 'configs/app'; import config from 'configs/app';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import ValidatorEntity from 'ui/shared/entities/validator/ValidatorEntity'; import ValidatorEntity from 'ui/shared/entities/validator/ValidatorEntity';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid'; import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
...@@ -28,14 +28,14 @@ const ValidatorsListItem = ({ data, isLoading }: Props) => { ...@@ -28,14 +28,14 @@ const ValidatorsListItem = ({ data, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>Index</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Index</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ data.index } { data.index }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Balance</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Balance</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ BigNumber(data.balance).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { config.chain.currency.symbol } { BigNumber(data.balance).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { config.chain.currency.symbol }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
......
import { Table, Tbody, Tr, Th } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { ValidatorsZilliqaItem } from 'types/api/validators'; import type { ValidatorsZilliqaItem } from 'types/api/validators';
import config from 'configs/app'; import config from 'configs/app';
import { TableBody, TableColumnHeader, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar'; import { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar';
import { default as Thead } from 'ui/shared/TheadSticky';
import ValidatorsTableItem from './ValidatorsTableItem'; import ValidatorsTableItem from './ValidatorsTableItem';
...@@ -16,25 +15,25 @@ interface Props { ...@@ -16,25 +15,25 @@ interface Props {
const ValidatorsTable = ({ data, isLoading }: Props) => { const ValidatorsTable = ({ data, isLoading }: Props) => {
return ( return (
<Table> <TableRoot>
<Thead top={ ACTION_BAR_HEIGHT_DESKTOP }> <TableHeaderSticky top={ ACTION_BAR_HEIGHT_DESKTOP }>
<Tr> <TableRow>
<Th width="50%">BLS public key</Th> <TableColumnHeader width="50%">BLS public key</TableColumnHeader>
<Th width="25%">Index</Th> <TableColumnHeader width="25%">Index</TableColumnHeader>
<Th width="25%" isNumeric> <TableColumnHeader width="25%" isNumeric>
Staked { config.chain.currency.symbol } Staked { config.chain.currency.symbol }
</Th> </TableColumnHeader>
</Tr> </TableRow>
</Thead> </TableHeaderSticky>
<Tbody> <TableBody>
{ data.map((item, index) => ( { data.map((item, index) => (
<ValidatorsTableItem <ValidatorsTableItem
key={ item.bls_public_key + (isLoading ? index : '') } key={ item.bls_public_key + (isLoading ? index : '') }
data={ item } data={ item }
isLoading={ isLoading }/> isLoading={ isLoading }/>
)) } )) }
</Tbody> </TableBody>
</Table> </TableRoot>
); );
}; };
......
import { Tr, Td } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { ValidatorsZilliqaItem } from 'types/api/validators'; import type { ValidatorsZilliqaItem } from 'types/api/validators';
import config from 'configs/app'; import config from 'configs/app';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableCell, TableRow } from 'toolkit/chakra/table';
import ValidatorEntity from 'ui/shared/entities/validator/ValidatorEntity'; import ValidatorEntity from 'ui/shared/entities/validator/ValidatorEntity';
interface Props { interface Props {
...@@ -15,21 +15,21 @@ interface Props { ...@@ -15,21 +15,21 @@ interface Props {
const ValidatorsTableItem = ({ data, isLoading }: Props) => { const ValidatorsTableItem = ({ data, isLoading }: Props) => {
return ( return (
<Tr> <TableRow>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<ValidatorEntity id={ data.bls_public_key } isLoading={ isLoading } fontWeight="700"/> <ValidatorEntity id={ data.bls_public_key } isLoading={ isLoading } fontWeight="700"/>
</Td> </TableCell>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ data.index } { data.index }
</Skeleton> </Skeleton>
</Td> </TableCell>
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ BigNumber(data.balance).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() } { BigNumber(data.balance).div(BigNumber(10 ** config.chain.currency.decimals)).toFormat() }
</Skeleton> </Skeleton>
</Td> </TableCell>
</Tr> </TableRow>
); );
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment