Commit 97fd4a12 authored by isstuev's avatar isstuev Committed by isstuev

batches fixes

parent 6805ed8c
...@@ -68,10 +68,12 @@ export type Transaction = { ...@@ -68,10 +68,12 @@ export type Transaction = {
// zkEvm fields // zkEvm fields
zkevm_verify_hash?: string; zkevm_verify_hash?: string;
zkevm_batch_number?: number; zkevm_batch_number?: number;
zkevm_status?: 'Confirmed by Sequencer' | 'L1 Confirmed'; zkevm_status?: typeof ZKEVM_L2_TX_STATUSES[number];
zkevm_sequence_hash?: string; zkevm_sequence_hash?: string;
} }
export const ZKEVM_L2_TX_STATUSES = [ 'Confirmed by Sequencer', 'L1 Confirmed' ];
export type TransactionsResponse = TransactionsResponseValidated | TransactionsResponsePending; export type TransactionsResponse = TransactionsResponseValidated | TransactionsResponsePending;
export interface TransactionsResponseValidated { export interface TransactionsResponseValidated {
......
...@@ -15,13 +15,15 @@ export type ZkEvmL2TxnBatchesResponse = { ...@@ -15,13 +15,15 @@ export type ZkEvmL2TxnBatchesResponse = {
} | null; } | null;
} }
export const ZKEVM_L2_TX_BATCH_STATUSES = [ 'Unfinalized', 'L1 Sequence Confirmed', 'Finalized' ];
export type ZkEvmL2TxnBatch = { export type ZkEvmL2TxnBatch = {
acc_input_hash: string; acc_input_hash: string;
global_exit_root: string; global_exit_root: string;
number: number; number: number;
sequence_tx_hash: string; sequence_tx_hash: string;
state_root: string; state_root: string;
status: string; status: typeof ZKEVM_L2_TX_BATCH_STATUSES[number];
timestamp: string; timestamp: string;
transactions: Array<string>; transactions: Array<string>;
verify_tx_hash: string; verify_tx_hash: string;
......
import { Text, Icon, HStack } from '@chakra-ui/react';
import React from 'react';
import arrowIcon from 'icons/arrows/east.svg';
import finalizedIcon from 'icons/finalized.svg';
type Props = {
step: string;
isLast: boolean;
isPassed: boolean;
}
const VerificationStep = ({ step, isLast, isPassed }: Props) => {
const stepColor = isPassed ? 'green.500' : 'text_secondary';
return (
<HStack gap={ 2 } color={ stepColor }>
<Icon as={ finalizedIcon } boxSize={ 5 }/>
<Text color={ stepColor }>{ step }</Text>
{ !isLast && <Icon as={ arrowIcon } boxSize={ 5 }/> }
</HStack>
);
};
export default VerificationStep;
...@@ -2,16 +2,18 @@ import { Box } from '@chakra-ui/react'; ...@@ -2,16 +2,18 @@ import { Box } from '@chakra-ui/react';
import { test, expect } from '@playwright/experimental-ct-react'; import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react'; import React from 'react';
import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction';
import TestApp from 'playwright/TestApp'; import TestApp from 'playwright/TestApp';
import TxZkEvmStatus from './TxZkEvmStatus'; import VerificationSteps from './VerificationSteps';
test('first status +@mobile +@dark-mode', async({ mount }) => { test('first step +@mobile +@dark-mode', async({ mount }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<Box p={ 10 }> <Box p={ 10 }>
<TxZkEvmStatus status="Confirmed by Sequencer"/> <VerificationSteps step={ ZKEVM_L2_TX_STATUSES[0] } steps={ ZKEVM_L2_TX_STATUSES }/>
</Box> </Box>
</TestApp>, </TestApp>,
); );
...@@ -23,7 +25,7 @@ test('second status', async({ mount }) => { ...@@ -23,7 +25,7 @@ test('second status', async({ mount }) => {
const component = await mount( const component = await mount(
<TestApp> <TestApp>
<TxZkEvmStatus status="L1 Confirmed"/> <VerificationSteps step={ ZKEVM_L2_TX_STATUSES[1] } steps={ ZKEVM_L2_TX_STATUSES }/>
</TestApp>, </TestApp>,
); );
......
import { Skeleton } from '@chakra-ui/react';
import React from 'react';
import VerificationStep from './VerificationStep';
export interface Props<T extends string> {
step: T;
steps: Array<T>;
isLoading?: boolean;
}
const VerificationSteps = <T extends string>({ step, steps, isLoading }: Props<T>) => {
const currentStepIndex = steps.indexOf(step);
return (
<Skeleton
isLoaded={ !isLoading }
display="flex"
gap={ 2 }
alignItems="center"
flexWrap="wrap"
>
{ steps.map((step, index) => (
<VerificationStep step={ step } isLast={ index === steps.length - 1 } isPassed={ index <= currentStepIndex } key={ step }/>
)) }
</Skeleton>
);
};
export default VerificationSteps;
...@@ -17,6 +17,8 @@ import BigNumber from 'bignumber.js'; ...@@ -17,6 +17,8 @@ import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import { scroller, Element } from 'react-scroll'; import { scroller, Element } from 'react-scroll';
import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
...@@ -56,7 +58,7 @@ import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers'; ...@@ -56,7 +58,7 @@ import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers';
import TxSocketAlert from 'ui/tx/TxSocketAlert'; import TxSocketAlert from 'ui/tx/TxSocketAlert';
import useFetchTxInfo from 'ui/tx/useFetchTxInfo'; import useFetchTxInfo from 'ui/tx/useFetchTxInfo';
import TxZkEvmStatus from './TxZkEvmStatus'; import VerificationSteps from './VerificationSteps';
const TxDetails = () => { const TxDetails = () => {
const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo(); const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo();
...@@ -160,7 +162,7 @@ const TxDetails = () => { ...@@ -160,7 +162,7 @@ const TxDetails = () => {
title="Confirmation status" title="Confirmation status"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<TxZkEvmStatus status={ data.zkevm_status } isLoading={ isPlaceholderData }/> <VerificationSteps step={ data.zkevm_status } steps={ ZKEVM_L2_TX_STATUSES } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
{ data.revert_reason && ( { data.revert_reason && (
......
import { Text, Icon, Skeleton, HStack } from '@chakra-ui/react';
import React from 'react';
import type { Transaction } from 'types/api/transaction';
import arrowIcon from 'icons/arrows/east.svg';
import finalizedIcon from 'icons/finalized.svg';
export interface Props {
status: Transaction['zkevm_status'];
isLoading?: boolean;
}
const TxZkEvmStatus = ({ status, isLoading }: Props) => {
const secondStepColor = status === 'L1 Confirmed' ? 'green.500' : 'text_secondary';
return (
<Skeleton
isLoaded={ !isLoading }
display="flex"
gap={ 2 }
alignItems="center"
flexWrap="wrap"
>
<HStack gap={ 2 }>
<Icon as={ finalizedIcon } boxSize={ 5 } color="green.500"/>
<Text color="green.500">Confirmed by Sequencer</Text>
<Icon as={ arrowIcon } boxSize={ 5 } color="green.500"/>
</HStack>
<HStack gap={ 2 }>
<Icon as={ finalizedIcon } boxSize={ 5 } color={ secondStepColor }/>
<Text color={ secondStepColor }>L1 Confirmed</Text>
</HStack>
</Skeleton>
);
};
export default TxZkEvmStatus;
...@@ -3,17 +3,21 @@ import type { UseQueryResult } from '@tanstack/react-query'; ...@@ -3,17 +3,21 @@ import type { UseQueryResult } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import { ZKEVM_L2_TX_BATCH_STATUSES } from 'types/api/zkEvml2TxnBatches';
import type { ZkEvmL2TxnBatch } from 'types/api/zkEvml2TxnBatches'; import type { ZkEvmL2TxnBatch } from 'types/api/zkEvml2TxnBatches';
import clockIcon from 'icons/clock.svg'; import clockIcon from 'icons/clock.svg';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon'; import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1'; import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import PrevNext from 'ui/shared/PrevNext'; import PrevNext from 'ui/shared/PrevNext';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
import VerificationSteps from 'ui/shared/verificationSteps/VerificationSteps';
interface Props { interface Props {
query: UseQueryResult<ZkEvmL2TxnBatch, ResourceError>; query: UseQueryResult<ZkEvmL2TxnBatch, ResourceError>;
...@@ -70,7 +74,6 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -70,7 +74,6 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
> >
<DetailsInfoItem <DetailsInfoItem
title="Tx batch number" title="Tx batch number"
// hint="The block height of a particular block is defined as the number of blocks preceding it in the blockchain"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData }>
...@@ -87,16 +90,12 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -87,16 +90,12 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Status" title="Status"
// hint="Size of the block in bytes"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Skeleton isLoaded={ !isPlaceholderData }> <VerificationSteps steps={ ZKEVM_L2_TX_BATCH_STATUSES } step={ data.status } isLoading={ isPlaceholderData }/>
{ data.status }
</Skeleton>
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Verify timestamp" title="Timestamp"
// hint="Date & time at which block was produced."
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/> <Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
...@@ -110,7 +109,6 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -110,7 +109,6 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Verify tx hash" title="Verify tx hash"
// hint="Date & time at which block was produced."
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
{ data.verify_tx_hash ? ( { data.verify_tx_hash ? (
...@@ -137,25 +135,24 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -137,25 +135,24 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
<DetailsInfoItem <DetailsInfoItem
title="Global exit root" title="Global exit root"
// hint=''
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
{ data.global_exit_root } <HashStringShortenDynamic hash={ data.global_exit_root }/>
</Skeleton> </Skeleton>
<CopyToClipboard text={ data.global_exit_root } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Acc input hash" title="Acc input hash"
// hint=''
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
{ data.acc_input_hash } <HashStringShortenDynamic hash={ data.acc_input_hash }/>
</Skeleton> </Skeleton>
<CopyToClipboard text={ data.acc_input_hash } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Sequence tx hash" title="Sequence tx hash"
// hint=''
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
{ data.sequence_tx_hash ? ( { data.sequence_tx_hash ? (
...@@ -164,17 +161,16 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => { ...@@ -164,17 +161,16 @@ const ZkEvmL2TxnBatchDetails = ({ query }: Props) => {
hash={ data.sequence_tx_hash } hash={ data.sequence_tx_hash }
maxW="100%" maxW="100%"
/> />
) : <Text>pending</Text> } ) : <Text>Pending</Text> }
{ /* Not sertain how to display pending state */ }
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="State root" title="State root"
// hint=''
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<Skeleton isLoaded={ !isPlaceholderData }> <Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
{ data.state_root } <HashStringShortenDynamic hash={ data.state_root }/>
</Skeleton> </Skeleton>
<CopyToClipboard text={ data.state_root } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
</Grid> </Grid>
); );
......
...@@ -54,9 +54,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => { ...@@ -54,9 +54,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>Txn count</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Txn count</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<LinkInternal <LinkInternal
// fix after implementing batch page href={ route({ pathname: '/zkevm-l2-txn-batch/[number]', query: { number: item.number.toString(), tab: 'txs' } }) }
href="#"
// href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString(), tab: 'txs' } }) }
isLoading={ isLoading } isLoading={ isLoading }
fontWeight={ 600 } fontWeight={ 600 }
> >
...@@ -76,8 +74,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => { ...@@ -76,8 +74,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => {
lineHeight={ 5 } lineHeight={ 5 }
maxW="100%" maxW="100%"
/> />
) : <Text>pending</Text> } ) : <Text>Pending</Text> }
{ /* Not sertain how to display pending state */ }
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Sequence hash</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Sequence hash</ListItemMobileGrid.Label>
...@@ -90,8 +87,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => { ...@@ -90,8 +87,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => {
lineHeight={ 5 } lineHeight={ 5 }
maxW="100%" maxW="100%"
/> />
) : <Text>pending</Text> } ) : <Text>Pending</Text> }
{ /* Not sertain how to display pending state */ }
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
</ListItemMobileGrid.Container> </ListItemMobileGrid.Container>
......
...@@ -46,8 +46,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => { ...@@ -46,8 +46,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
</Td> </Td>
<Td> <Td>
<LinkInternal <LinkInternal
// href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString(), tab: 'txs' } }) } href={ route({ pathname: '/zkevm-l2-txn-batch/[number]', query: { number: item.number.toString(), tab: 'txs' } }) }
href="#"
isLoading={ isLoading } isLoading={ isLoading }
> >
<Skeleton isLoaded={ !isLoading } minW="40px" my={ 1 }> <Skeleton isLoaded={ !isLoading } minW="40px" my={ 1 }>
...@@ -64,7 +63,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => { ...@@ -64,7 +63,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
lineHeight={ 5 } lineHeight={ 5 }
maxW="100%" maxW="100%"
/> />
) : <Text>pending</Text> } ) : <Text>Pending</Text> }
</Td> </Td>
<Td pr={ 12 }> <Td pr={ 12 }>
{ item.sequence_tx_hash ? ( { item.sequence_tx_hash ? (
...@@ -75,7 +74,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => { ...@@ -75,7 +74,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
lineHeight={ 5 } lineHeight={ 5 }
maxW="100%" maxW="100%"
/> />
) : <Text>pending</Text> } ) : <Text>Pending</Text> }
</Td> </Td>
</Tr> </Tr>
); );
......
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