Skip to content

Commit

Permalink
Merge pull request #184 from migalabs/dev
Browse files Browse the repository at this point in the history
v2.4.2 Release
  • Loading branch information
santi1234567 authored Dec 26, 2024
2 parents 3eccf79 + 5bcfec3 commit f0fdbee
Show file tree
Hide file tree
Showing 21 changed files with 1,836 additions and 781 deletions.
277 changes: 244 additions & 33 deletions packages/client/components/layouts/Epochs.tsx

Large diffs are not rendered by default.

232 changes: 232 additions & 0 deletions packages/client/components/layouts/SlashedVals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
import React from 'react';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';

import axiosClient from '../../config/axios';

// Hooks
import useLargeView from '../../hooks/useLargeView';

// Components
import LinkValidator from '../ui/LinkValidator';
import LinkSlot from '../ui/LinkSlot';
import LinkEntity from '../ui/LinkEntity';
import LinkEpoch from '../ui/LinkEpoch';
import { LargeTable, LargeTableHeader, LargeTableRow, SmallTable, SmallTableCard } from '../ui/Table';
import TooltipContainer from '../ui/TooltipContainer';
import TooltipResponsive from '../ui/TooltipResponsive';

// Types
import { SlashedVal } from '../../types';

// Props
type Props = {
slashedVals: SlashedVal[];
};

const Age = (timestampDay: any): string => {
const slashedDate: any = new Date(timestampDay);
const todaysDate:any = new Date();
const difference = todaysDate - slashedDate;
const seconds = Math.floor(difference / 1000);
const minutes = Math.floor(difference / (1000 * 60));
const hours = Math.floor(difference / (1000 * 60 * 60));
const days = Math.floor(hours / 24);

const remainingHours = hours % 24;
const remainingMinutes = minutes % 60;
const remainingSeconds = seconds % 60;

let age: string = `${days} days ${remainingHours} hours ago`;
if (days > 0) {
age = `${days} days ${remainingHours} hours ago`;
} else if (hours > 0) {
age = `${hours} hours ${remainingMinutes} min ago`;
} else {
age = `${remainingMinutes} min ${remainingSeconds} seconds ago`; }
return age;
}

const SlashedVals = ({slashedVals}: Props) => {
// Large View Hook
const router = useRouter();
const { network } = router.query;

const isLargeView = useLargeView();
const [blockGenesis, setBlockGenesis] = useState(0);

useEffect(() => {
if (network && blockGenesis === 0) {
getBlockGenesis(network as string);
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [network]);

const getBlockGenesis = async (network: string) => {
try {
const genesisBlock = await axiosClient.get('/api/networks/block/genesis', {
params: {
network,
},
});
setBlockGenesis(genesisBlock.data.block_genesis);
} catch (error) {
console.log(error);
}
};
// SLashed Validators Large View
const getContentSlashedValsLargeView = () => (
<LargeTable
minWidth={1150}
noRowsText='No Slashed Validators'
fetchingRows={false}
showRowsWhileFetching={false}>
<LargeTableHeader text='Slashed Validators' width='20%' />
<LargeTableHeader text='Slashed by' width='20%' />
<LargeTableHeader text='Time' width='12%' />
<LargeTableHeader text='Reason' width='15%' />
<LargeTableHeader text='Slot' width='15%' />
<LargeTableHeader text='Epoch' width='15%' />

{slashedVals.map(slashedVals => (
<LargeTableRow key={slashedVals.f_slashed_validator_index}>

<div className='w-[20%] flex justify-center items-center gap-3'>
<div className=' md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkValidator validator={slashedVals.f_slashed_validator_index} mxAuto />
</div>
<div className='flex gap-1'>
<span>(</span>
<div className=' md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkEntity entity={slashedVals.f_slashed_validator_pool_name} mxAuto />
</div>
<span>)</span>
</div>
</div>

<div className='w-[20%] flex justify-center items-center gap-3'>
<div className=' md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkValidator validator={slashedVals.f_slashed_by_validator_index} mxAuto />
</div>
<div className='flex gap-1'>
<span>(</span>
<div className=' md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkEntity entity={slashedVals.f_slashed_by_validator_pool_name} mxAuto />
</div>
<span>)</span>
</div>
</div>

<div className='w-[12%] flex flex-col pt-2.5 pb-2.5'>
<TooltipContainer>
<div>
<p>{Age(blockGenesis + slashedVals.f_slot * 12000)}</p>
</div>
<TooltipResponsive
width={120}
content={
<>
<p>{new Date(blockGenesis + slashedVals.f_slot * 12000).toLocaleDateString('ja-JP')}</p>
<p>{new Date(blockGenesis + slashedVals.f_slot * 12000).toLocaleTimeString('ja-JP')}</p>
</>
}
top='34px'
/>
</TooltipContainer>
</div>

<p className='w-[15%] text-center'>{slashedVals.f_slashing_reason.split(/(?=[A-Z])/).join(" ")}</p>

<div className='w-[15%] md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkSlot slot={slashedVals.f_slot} mxAuto />
</div>

<div className='w-[15%] md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkEpoch epoch={slashedVals.f_epoch} mxAuto />
</div>

</LargeTableRow>
))}
</LargeTable>
);

// SlashedVals Small View
const getSlashedValsSmallView = () => (
<SmallTable noRowsText='No Slashed Validators' fetchingRows={false}>
{slashedVals.map(slashedVals => (
<SmallTableCard key={slashedVals.f_slashed_validator_index}>
<div className='flex flex-col'>
<div className='flex items-center justify-between py-1 gap-2 flex-wrap'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>Slashed Validators: </p>
<LinkValidator validator={slashedVals.f_slashed_validator_index} mxAuto />
<div className='flex'>
<span>(</span>
<LinkEntity entity={slashedVals.f_slashed_validator_pool_name} mxAuto />
<p>)</p>
</div>
</div>
</div>

<div className='flex flex-col'>
<div className='flex items-center justify-between py-1 gap-2 flex-wrap'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>Slashed By: </p>
<LinkValidator validator={slashedVals.f_slashed_by_validator_index} mxAuto />
<div className='flex justify-center'>
<span>(</span>
<LinkEntity entity={slashedVals.f_slashed_by_validator_pool_name} mxAuto />
<p>)</p>
</div>
</div>
</div>

<div className='flex items-center justify-between py-1 gap-2'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>Time:</p>
<div className='flex flex-col text-end'>
<TooltipContainer>
<div>
<p>{Age(blockGenesis + slashedVals.f_slot * 12000)}</p>
</div>
<TooltipResponsive
width={120}
content={
<>
<p>{new Date(blockGenesis + slashedVals.f_slot * 12000).toLocaleDateString('ja-JP')}</p>
<p>{new Date(blockGenesis + slashedVals.f_slot * 12000).toLocaleTimeString('ja-JP')}</p>
</>
}
top='34px'
/>
</TooltipContainer>
</div>
</div>

<div className='flex flex-col'>
<div className='flex items-center justify-between py-1 gap-2'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>Reason: </p>
<p>{slashedVals.f_slashing_reason.split(/(?=[A-Z])/).join(" ")}</p>
</div>
</div>

<div className='flex flex-col'>
<div className='flex items-center justify-between py-1 gap-2'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>Slot: </p>
<LinkSlot slot={slashedVals.f_slot} />
</div>
</div>

<div className='flex flex-col'>
<div className='flex items-center justify-between py-1 gap-2'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>Epoch: </p>
<LinkEpoch epoch={slashedVals.f_epoch} mxAuto />
</div>
</div>
</SmallTableCard>
))}
</SmallTable>
);

return <>{isLargeView ? getContentSlashedValsLargeView() : getSlashedValsSmallView()}</>;
};

export default SlashedVals;
104 changes: 94 additions & 10 deletions packages/client/components/layouts/Slots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import LinkSlot from '../../components/ui/LinkSlot';
import LinkEntity from '../../components/ui/LinkEntity';
import BlockState from '../ui/BlockState';
import { LargeTable, LargeTableHeader, LargeTableRow, SmallTable, SmallTableCard } from '../ui/Table';
import TooltipResponsive from '../ui/TooltipResponsive';


// Types
import { Slot } from '../../types';
import { getShortAddress } from '../../helpers/addressHelper';

// Props
type Props = {
Expand Down Expand Up @@ -59,16 +62,52 @@ const Slots = ({ slots, fetchingSlots }: Props) => {
// Slots Large View
const getContentSlotsLargeView = () => (
<LargeTable minWidth={850} noRowsText='No Slots' fetchingRows={fetchingSlots}>
<LargeTableHeader text='Block' width='17%' />
<LargeTableHeader text='Entity' width='28%' />
<LargeTableHeader text='Proposer' width='15%' />
<LargeTableHeader text='Slot' width='15%' />
<LargeTableHeader text='Block' width='11%' />
<LargeTableHeader text='Entity' width='25%' />
<LargeTableHeader text='Proposer' width='12%' />
<LargeTableHeader text='Slot' width='12%' />
<LargeTableHeader text='Time' width='10%' />
<LargeTableHeader text='Att' width='10%' tooltipContent={
<TooltipResponsive
width={220}
content={
<>
<span>Attestations included in slot</span>
</>
}
top='34px'
/>
}/>
<LargeTableHeader text='Sync Agg %' width='15%' tooltipContent={
<TooltipResponsive
width={220}
content={
<>
<span>Sync Aggregate Participation</span>
</>
}
top='34px'
/>
}/>

<LargeTableHeader text='Deposits' width='10%' />
<LargeTableHeader text='S- P / A' width='10%' tooltipContent={
<TooltipResponsive
width={220}
content={
<>
<span>Slashings Proposer / Attester</span>
</>
}
top='34px'
/>
}/>
<LargeTableHeader text='Exits' width='10%' />
<LargeTableHeader text='Withdrawals' width='15%' />

{slots.map(slot => (
<LargeTableRow key={slot.f_proposer_slot}>
<div className='w-[17%] flex items-center justify-center'>
<div className='w-[11%] flex items-center justify-center'>
<BlockState
poolName={slot.f_pool_name}
proposed={slot.f_proposed}
Expand All @@ -78,15 +117,15 @@ const Slots = ({ slots, fetchingSlots }: Props) => {
/>
</div>

<div className='w-[28%] uppercase md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<div className='w-[25%] uppercase md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkEntity entity={slot.f_pool_name} mxAuto />
</div>

<div className='w-[15%] md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<div className='w-[12%] md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkValidator validator={slot.f_val_idx} mxAuto />
</div>

<div className='w-[15%] md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<div className='w-[12%] md:hover:underline underline-offset-4 decoration-2 text-[var(--darkPurple)] dark:text-[var(--purple)]'>
<LinkSlot slot={slot.f_proposer_slot} mxAuto />
</div>

Expand All @@ -99,7 +138,17 @@ const Slots = ({ slots, fetchingSlots }: Props) => {
</span>
</div>

<p className='w-[15%] text-center'>{(slot.withdrawals / 10 ** 9).toLocaleString()} ETH</p>
<p className='w-[10%] text-center'>{(slot.f_proposed === false) ? "-" : slot.f_attestations}</p>

<p className='w-[15%] text-center'>{(slot.f_proposed === false) ? '-' : `${(slot.f_sync_bits * 100 / 512).toFixed(2)}%`}</p>

<p className='w-[10%] text-center'>{(slot.f_proposed === false) ? '-' : slot.f_deposits}</p>

<p className='w-[10%] text-center'>{(slot.f_proposed === false) ? '-' : `${slot.f_proposer_slashings}/${slot.f_attester_slashings}`}</p>

<p className='w-[10%] text-center'>{(slot.f_proposed === false) ? '-' : slot.f_voluntary_exits}</p>

<p className='w-[15%] text-center'>{(slot.f_proposed === false) ? '-' : `${slot.num_withdrawals} (${(slot.withdrawals / 10 ** 9).toLocaleString()}) ETH`}</p>
</LargeTableRow>
))}
</LargeTable>
Expand Down Expand Up @@ -148,11 +197,46 @@ const Slots = ({ slots, fetchingSlots }: Props) => {
</div>
</div>

<div className='flex items-center justify-between'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>
Attestations:
</p>
<p>{(slot.f_proposed === false) ? "-" : slot.f_attestations}</p>
</div>

<div className='flex items-center justify-between'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>
Sync Agg %:
</p>
<p>{(slot.f_proposed === false) ? '-' : (slot.f_sync_bits * 100 / 512).toFixed(2)}%</p>
</div>

<div className='flex items-center justify-between'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>
Deposits:
</p>
<p>{(slot.f_proposed === false) ? "-" : slot.f_deposits}</p>
</div>

<div className='flex items-center justify-between'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>
Slashing P / A:
</p>
<p>{(slot.f_proposed === false) ? '-' : `${slot.f_proposer_slashings}/${slot.f_attester_slashings}`}</p>
</div>

<div className='flex items-center justify-between'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>
Exits:
</p>
<p>{(slot.f_proposed === false) ? '-' : slot.f_voluntary_exits}</p>
</div>

<div className='flex items-center justify-between'>
<p className='font-semibold text-[var(--darkGray)] dark:text-[var(--white)]'>
Withdrawals:
</p>
<p>{(slot.withdrawals / 10 ** 9).toLocaleString()} ETH</p>
<p>{(slot.f_proposed === false) ? '-' : slot.num_withdrawals}({(slot.withdrawals / 10 ** 9).toLocaleString()} ETH)</p>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit f0fdbee

Please sign in to comment.