Commit 6805ed8c authored by isstuev's avatar isstuev Committed by isstuev

tx details

parent 7ad5a392
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path fill="currentColor" d="M7.79 11.839a1 1 0 0 0 1.42 0l5.285-5.33a.71.71 0 1 1 1.009 1L9.21 13.854a1 1 0 0 1-1.42 0l-3.294-3.322a.71.71 0 1 1 1.008-1L7.79 11.84Z"/>
<rect width="18.4" height="18.4" x=".8" y=".8" stroke="currentColor" stroke-width="1.6" rx="3.2"/>
</svg>
...@@ -59,7 +59,7 @@ import type { TTxsFilters } from 'types/api/txsFilters'; ...@@ -59,7 +59,7 @@ import type { TTxsFilters } from 'types/api/txsFilters';
import type { TxStateChanges } from 'types/api/txStateChanges'; import type { TxStateChanges } from 'types/api/txStateChanges';
import type { VisualizedContract } from 'types/api/visualization'; import type { VisualizedContract } from 'types/api/visualization';
import type { WithdrawalsResponse, WithdrawalsCounters } from 'types/api/withdrawals'; import type { WithdrawalsResponse, WithdrawalsCounters } from 'types/api/withdrawals';
import type { ZkEvmL2TxnBatch, ZkEvmL2TxnBatchesResponse } from 'types/api/zkEvml2TxnBatches'; import type { ZkEvmL2TxnBatch, ZkEvmL2TxnBatchesItem, ZkEvmL2TxnBatchesResponse } from 'types/api/zkEvml2TxnBatches';
import type { ArrayElement } from 'types/utils'; import type { ArrayElement } from 'types/utils';
import config from 'configs/app'; import config from 'configs/app';
...@@ -427,6 +427,9 @@ export const RESOURCES = { ...@@ -427,6 +427,9 @@ export const RESOURCES = {
homepage_txs: { homepage_txs: {
path: '/api/v2/main-page/transactions', path: '/api/v2/main-page/transactions',
}, },
homepage_zkevm_l2_batches: {
path: '/api/v2/main-page/zkevm/batches/confirmed',
},
homepage_txs_watchlist: { homepage_txs_watchlist: {
path: '/api/v2/main-page/transactions/watchlist', path: '/api/v2/main-page/transactions/watchlist',
}, },
...@@ -500,6 +503,10 @@ export const RESOURCES = { ...@@ -500,6 +503,10 @@ export const RESOURCES = {
path: '/api/v2/zkevm/batches/:number', path: '/api/v2/zkevm/batches/:number',
pathParams: [ 'number' as const ], pathParams: [ 'number' as const ],
}, },
zkevm_l2_txn_batch_txs: {
path: 'api/v2/transactions/zkevm-batch/:number',
pathParams: [ 'number' as const ],
},
// CONFIGS // CONFIGS
config_backend_version: { config_backend_version: {
...@@ -570,7 +577,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' | ...@@ -570,7 +577,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'token_instance_transfers' | 'token_instance_holders' | 'token_instance_transfers' | 'token_instance_holders' |
'verified_contracts' | 'verified_contracts' |
'l2_output_roots' | 'l2_withdrawals' | 'l2_txn_batches' | 'l2_deposits' | 'l2_output_roots' | 'l2_withdrawals' | 'l2_txn_batches' | 'l2_deposits' |
'zkevm_l2_txn_batches' | 'zkevm_l2_txn_batch_txs' | // 'zkevm_l2_txn_batches' | 'zkevm_l2_txn_batch_txs' |
'zkevm_l2_txn_batches' |
'withdrawals' | 'address_withdrawals' | 'block_withdrawals'; 'withdrawals' | 'address_withdrawals' | 'block_withdrawals';
export type PaginatedResponse<Q extends PaginatedResources> = ResourcePayload<Q>; export type PaginatedResponse<Q extends PaginatedResources> = ResourcePayload<Q>;
...@@ -594,6 +602,7 @@ Q extends 'homepage_blocks' ? Array<Block> : ...@@ -594,6 +602,7 @@ Q extends 'homepage_blocks' ? Array<Block> :
Q extends 'homepage_txs' ? Array<Transaction> : Q extends 'homepage_txs' ? Array<Transaction> :
Q extends 'homepage_txs_watchlist' ? Array<Transaction> : Q extends 'homepage_txs_watchlist' ? Array<Transaction> :
Q extends 'homepage_deposits' ? Array<L2DepositsItem> : Q extends 'homepage_deposits' ? Array<L2DepositsItem> :
Q extends 'homepage_zkevm_l2_batches' ? { items: Array<ZkEvmL2TxnBatchesItem> } :
Q extends 'homepage_indexing_status' ? IndexingStatus : Q extends 'homepage_indexing_status' ? IndexingStatus :
Q extends 'homepage_zkevm_latest_batch' ? number : Q extends 'homepage_zkevm_latest_batch' ? number :
Q extends 'stats_counters' ? Counters : Q extends 'stats_counters' ? Counters :
...@@ -663,6 +672,7 @@ Q extends 'l2_txn_batches_count' ? number : ...@@ -663,6 +672,7 @@ Q extends 'l2_txn_batches_count' ? number :
Q extends 'zkevm_l2_txn_batches' ? ZkEvmL2TxnBatchesResponse : Q extends 'zkevm_l2_txn_batches' ? ZkEvmL2TxnBatchesResponse :
Q extends 'zkevm_l2_txn_batches_count' ? number : Q extends 'zkevm_l2_txn_batches_count' ? number :
Q extends 'zkevm_l2_txn_batch' ? ZkEvmL2TxnBatch : Q extends 'zkevm_l2_txn_batch' ? ZkEvmL2TxnBatch :
Q extends 'zkevm_l2_txn_batch_txs' ? Array<Transaction> :
Q extends 'config_backend_version' ? BackendVersionConfig : Q extends 'config_backend_version' ? BackendVersionConfig :
never; never;
/* eslint-enable @typescript-eslint/indent */ /* eslint-enable @typescript-eslint/indent */
......
...@@ -50,4 +50,12 @@ export const TX: Transaction = { ...@@ -50,4 +50,12 @@ export const TX: Transaction = {
tx_tag: null, tx_tag: null,
}; };
export const TX_ZKEVM_L2: Transaction = {
...TX,
zkevm_batch_number: 12345,
zkevm_sequence_hash: '0x2b824349b320cfa72f292ab26bf525adb00083ba9fa097141896c3c8c74567cc',
zkevm_status: 'Confirmed by Sequencer',
zkevm_verify_hash: '0x2b824349b320cfa72f292ab26bf525adb00083ba9fa097141896c3c8c74567cc',
};
export const TX_RAW_TRACE: RawTracesResponse = []; export const TX_RAW_TRACE: RawTracesResponse = [];
...@@ -68,7 +68,7 @@ export type Transaction = { ...@@ -68,7 +68,7 @@ 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?: string; zkevm_status?: 'Confirmed by Sequencer' | 'L1 Confirmed';
zkevm_sequence_hash?: string; zkevm_sequence_hash?: string;
} }
......
import { Box, Heading, Flex, Text, VStack } from '@chakra-ui/react';
// import { AnimatePresence } from 'framer-motion';
import React from 'react';
import { route } from 'nextjs-routes';
import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import { ZKEVM_L2_TXN_BATCHES_ITEM } from 'stubs/zkEvmL2';
import LinkInternal from 'ui/shared/LinkInternal';
import LatestZkevmL2BatchItem from './LatestZkevmL2BatchItem';
const LatestZkEvmL2Batches = () => {
const isMobile = useIsMobile();
const batchesMaxCount = isMobile ? 2 : 3;
const { data, isPlaceholderData, isError } = useApiQuery('homepage_zkevm_l2_batches', {
queryOptions: {
placeholderData: { items: Array(batchesMaxCount).fill(ZKEVM_L2_TXN_BATCHES_ITEM) },
},
});
let content;
if (isError) {
content = <Text>No data. Please reload page.</Text>;
}
if (data) {
const dataToShow = data.items.slice(0, batchesMaxCount);
content = (
<>
<VStack spacing={ 3 } mb={ 4 } overflow="hidden" alignItems="stretch">
{ /* <AnimatePresence initial={ false } > */ }
{ dataToShow.map(((batch, index) => (
<LatestZkevmL2BatchItem
key={ batch.number + (isPlaceholderData ? String(index) : '') }
batch={ batch }
isLoading={ isPlaceholderData }
/>
))) }
{ /* </AnimatePresence> */ }
</VStack>
<Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ route({ pathname: '/zkevm-l2-txn-batches' }) }>View all batches</LinkInternal>
</Flex>
</>
);
}
return (
<Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }>
<Heading as="h4" size="sm" mb={ 4 }>Latest batches</Heading>
{ content }
</Box>
);
};
export default LatestZkEvmL2Batches;
import { Box, Heading, Flex, Text, VStack, Skeleton } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import { AnimatePresence } from 'framer-motion';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import type { Block } from 'types/api/block';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import { nbsp } from 'lib/html-entities';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import { BLOCK } from 'stubs/block';
import { HOMEPAGE_STATS } from 'stubs/stats';
import LinkInternal from 'ui/shared/LinkInternal';
import LatestBlocksItem from './LatestBlocksItem';
const LatestBlocks = () => {
const isMobile = useIsMobile();
// const blocksMaxCount = isMobile ? 2 : 3;
let blocksMaxCount: number;
if (config.features.rollup.isEnabled || config.UI.views.block.hiddenFields?.total_reward) {
blocksMaxCount = isMobile ? 4 : 5;
} else {
blocksMaxCount = isMobile ? 2 : 3;
}
const { data, isPlaceholderData, isError } = useApiQuery('homepage_blocks', {
queryOptions: {
placeholderData: Array(blocksMaxCount).fill(BLOCK),
},
});
const queryClient = useQueryClient();
const statsQueryResult = useApiQuery('homepage_stats', {
queryOptions: {
placeholderData: HOMEPAGE_STATS,
},
});
const handleNewBlockMessage: SocketMessage.NewBlock['handler'] = React.useCallback((payload) => {
queryClient.setQueryData(getResourceKey('homepage_blocks'), (prevData: Array<Block> | undefined) => {
const newData = prevData ? [ ...prevData ] : [];
if (newData.some((block => block.height === payload.block.height))) {
return newData;
}
return [ payload.block, ...newData ].sort((b1, b2) => b2.height - b1.height).slice(0, blocksMaxCount);
});
}, [ queryClient, blocksMaxCount ]);
const channel = useSocketChannel({
topic: 'blocks:new_block',
isDisabled: isPlaceholderData || isError,
});
useSocketMessage({
channel,
event: 'new_block',
handler: handleNewBlockMessage,
});
let content;
if (isError) {
content = <Text>No data. Please reload page.</Text>;
}
if (data) {
const dataToShow = data.slice(0, blocksMaxCount);
content = (
<>
{ statsQueryResult.data?.network_utilization_percentage !== undefined && (
<Skeleton isLoaded={ !statsQueryResult.isPlaceholderData } mb={{ base: 6, lg: 3 }} display="inline-block">
<Text as="span" fontSize="sm">
Network utilization:{ nbsp }
</Text>
<Text as="span" fontSize="sm" color="blue.400" fontWeight={ 700 }>
{ statsQueryResult.data?.network_utilization_percentage.toFixed(2) }%
</Text>
</Skeleton>
) }
<VStack spacing={ 3 } mb={ 4 } overflow="hidden" alignItems="stretch">
<AnimatePresence initial={ false } >
{ dataToShow.map(((block, index) => (
<LatestBlocksItem
key={ block.height + (isPlaceholderData ? String(index) : '') }
block={ block }
isLoading={ isPlaceholderData }
/>
))) }
</AnimatePresence>
</VStack>
<Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ route({ pathname: '/blocks' }) }>View all blocks</LinkInternal>
</Flex>
</>
);
}
return (
<Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }>
<Heading as="h4" size="sm" mb={ 4 }>Latest blocks</Heading>
{ content }
</Box>
);
};
export default LatestBlocks;
import {
Box,
Flex,
Grid,
Skeleton,
} from '@chakra-ui/react';
import { motion } from 'framer-motion';
import React from 'react';
import type { ZkEvmL2TxnBatchesItem } from 'types/api/zkEvml2TxnBatches';
import { route } from 'nextjs-routes';
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
type Props = {
batch: ZkEvmL2TxnBatchesItem;
isLoading?: boolean;
}
const LatestZkevmL2BatchItem = ({ batch, isLoading }: Props) => {
return (
<Box
as={ motion.div }
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ display: 'none' }}
transitionDuration="normal"
transitionTimingFunction="linear"
borderRadius="md"
border="1px solid"
borderColor="divider"
p={ 6 }
>
<Flex alignItems="center" overflow="hidden" w="100%" mb={ 3 }>
<BlockEntityL2
isLoading={ isLoading }
number={ batch.number }
tailLength={ 2 }
fontSize="xl"
lineHeight={ 7 }
fontWeight={ 500 }
mr="auto"
href={ route({ pathname: '/zkevm-l2-txn-batch/[number]', query: { number: batch.number.toString() } }) }
/>
<BlockTimestamp
ts={ batch.timestamp }
isEnabled={ !isLoading }
isLoading={ isLoading }
fontSize="sm"
flexShrink={ 0 }
ml={ 2 }
/>
</Flex>
<Grid gridGap={ 2 } templateColumns="auto minmax(0, 1fr)" fontSize="sm">
<Skeleton isLoaded={ !isLoading }>Txn</Skeleton>
<Skeleton isLoaded={ !isLoading } color="text_secondary"><span>{ batch.tx_count }</span></Skeleton>
<Skeleton isLoaded={ !isLoading }>Status</Skeleton>
<Skeleton isLoaded={ !isLoading } color="text_secondary"><span>{ batch.status }</span></Skeleton>
</Grid>
</Box>
);
};
export default LatestZkevmL2BatchItem;
...@@ -4,6 +4,7 @@ import React from 'react'; ...@@ -4,6 +4,7 @@ import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
import ChainIndicators from 'ui/home/indicators/ChainIndicators'; import ChainIndicators from 'ui/home/indicators/ChainIndicators';
import LatestBlocks from 'ui/home/LatestBlocks'; import LatestBlocks from 'ui/home/LatestBlocks';
import LatestZkEvmL2Batches from 'ui/home/LatestZkEvmL2Batches';
import Stats from 'ui/home/Stats'; import Stats from 'ui/home/Stats';
import Transactions from 'ui/home/Transactions'; import Transactions from 'ui/home/Transactions';
import AdBanner from 'ui/shared/ad/AdBanner'; import AdBanner from 'ui/shared/ad/AdBanner';
...@@ -43,7 +44,7 @@ const Home = () => { ...@@ -43,7 +44,7 @@ const Home = () => {
<ChainIndicators/> <ChainIndicators/>
<AdBanner mt={{ base: 6, lg: 8 }} mx="auto" display="flex" justifyContent="center"/> <AdBanner mt={{ base: 6, lg: 8 }} mx="auto" display="flex" justifyContent="center"/>
<Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 8 }> <Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 8 }>
<LatestBlocks/> { config.features.zkEvmRollup.isEnabled ? <LatestZkEvmL2Batches/> : <LatestBlocks/> }
<Box flexGrow={ 1 }> <Box flexGrow={ 1 }>
<Transactions/> <Transactions/>
</Box> </Box>
......
...@@ -42,19 +42,27 @@ const ZkEvmL2TxnBatch = () => { ...@@ -42,19 +42,27 @@ const ZkEvmL2TxnBatch = () => {
}, },
}); });
// const blockTxsQuery = useQueryWithPages({ // const batchTxsQuery = useQueryWithPages({
// resourceName: 'batch_txs', // resourceName: 'zkevm_l2_txn_batch_txs',
// pathParams: { height_or_hash: heightOrHash }, // pathParams: { number },
// options: { // options: {
// enabled: Boolean(!blockQuery.isPlaceholderData && blockQuery.data?.height && tab === 'txs'), // enabled: Boolean(!batchQuery.isPlaceholderData && batchQuery.data?.number && tab === 'txs'),
// placeholderData: generateListStub<'block_txs'>(TX, 50, { next_page_params: { // placeholderData: generateListStub<'block_txs'>(TX_ZKEVM_L2, 50, { next_page_params: {
// block_number: 9004925, // number: 9004925,
// index: 49, // index: 49,
// items_count: 50, // items_count: 50,
// } }), // } }),
// }, // },
// }); // });
// const batchTxsQuery = useApiQuery('zkevm_l2_txn_batch_txs', {
// pathParams: { number },
// queryOptions: {
// enabled: Boolean(!batchQuery.isPlaceholderData && batchQuery.data?.number && tab === 'txs'),
// placeholderData: Array(50).fill(TX),
// },
// });
if (!number) { if (!number) {
throw new Error('Tx batch not found', { cause: { status: 404 } }); throw new Error('Tx batch not found', { cause: { status: 404 } });
} }
...@@ -64,8 +72,8 @@ const ZkEvmL2TxnBatch = () => { ...@@ -64,8 +72,8 @@ const ZkEvmL2TxnBatch = () => {
} }
// const tabs: Array<RoutedTab> = React.useMemo(() => ([ // const tabs: Array<RoutedTab> = React.useMemo(() => ([
// { id: 'index', title: 'Details', component: <BlockDetails query={ blockQuery }/> }, // { id: 'index', title: 'Details', component: <ZkEvmL2TxnBatchDetails query={ batchQuery }/> },
// { id: 'txs', title: 'Transactions', component: <TxsContent query={ blockTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> }, // { id: 'txs', title: 'Transactions', component: <TxsContent query={ batchTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> },
// ].filter(Boolean)), [ blockQuery, blockTxsQuery, blockWithdrawalsQuery ]); // ].filter(Boolean)), [ blockQuery, blockTxsQuery, blockWithdrawalsQuery ]);
// const hasPagination = !isMobile && ( // const hasPagination = !isMobile && (
......
...@@ -56,6 +56,8 @@ import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers'; ...@@ -56,6 +56,8 @@ 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';
const TxDetails = () => { const TxDetails = () => {
const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo(); const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo();
...@@ -142,7 +144,7 @@ const TxDetails = () => { ...@@ -142,7 +144,7 @@ const TxDetails = () => {
<CopyToClipboard text={ data.hash } isLoading={ isPlaceholderData }/> <CopyToClipboard text={ data.hash } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title="Status and method" title={ config.features.zkEvmRollup.isEnabled ? 'L2 status and method' : 'Status and method' }
hint="Current transaction state: Success, Failed (Error), or Pending (In Process)" hint="Current transaction state: Success, Failed (Error), or Pending (In Process)"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
...@@ -153,13 +155,12 @@ const TxDetails = () => { ...@@ -153,13 +155,12 @@ const TxDetails = () => {
</Tag> </Tag>
) } ) }
</DetailsInfoItem> </DetailsInfoItem>
{ data.zkevm_status && ( { config.features.zkEvmRollup.isEnabled && (
<DetailsInfoItem <DetailsInfoItem
title="ZkEVM status" title="Confirmation status"
// hint="Current transaction state: Success, Failed (Error), or Pending (In Process)"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
{ data.zkevm_status } <TxZkEvmStatus status={ data.zkevm_status } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
{ data.revert_reason && ( { data.revert_reason && (
...@@ -195,7 +196,6 @@ const TxDetails = () => { ...@@ -195,7 +196,6 @@ const TxDetails = () => {
{ data.zkevm_batch_number && ( { data.zkevm_batch_number && (
<DetailsInfoItem <DetailsInfoItem
title="Tx batch" title="Tx batch"
// hint="Block number containing the transaction"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
<BlockEntityL2 <BlockEntityL2
...@@ -309,22 +309,31 @@ const TxDetails = () => { ...@@ -309,22 +309,31 @@ const TxDetails = () => {
<DetailsInfoItemDivider/> <DetailsInfoItemDivider/>
{ data.zkevm_batch_number && ( { data.zkevm_sequence_hash && (
<DetailsInfoItem <DetailsInfoItem
title="Sequence tx hash" title="Sequence tx hash"
// hint="Value sent in the native token (and USD) if applicable" flexWrap="nowrap"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
{ data.zkevm_sequence_hash } <Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
<HashStringShortenDynamic hash={ data.zkevm_sequence_hash }/>
</Skeleton>
<CopyToClipboard text={ data.zkevm_sequence_hash } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
{ data.zkevm_verify_hash && ( { data.zkevm_verify_hash && (
<DetailsInfoItem <DetailsInfoItem
title="Verify tx hash" title="Verify tx hash"
// hint="Value sent in the native token (and USD) if applicable" flexWrap="nowrap"
isLoading={ isPlaceholderData } isLoading={ isPlaceholderData }
> >
{ data.zkevm_verify_hash } <Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
<HashStringShortenDynamic hash={ data.zkevm_verify_hash }/>
</Skeleton>
<CopyToClipboard text={ data.zkevm_verify_hash } isLoading={ isPlaceholderData }/>
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
......
import { Box } from '@chakra-ui/react';
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import TestApp from 'playwright/TestApp';
import TxZkEvmStatus from './TxZkEvmStatus';
test('first status +@mobile +@dark-mode', async({ mount }) => {
const component = await mount(
<TestApp>
<Box p={ 10 }>
<TxZkEvmStatus status="Confirmed by Sequencer"/>
</Box>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
test('second status', async({ mount }) => {
const component = await mount(
<TestApp>
<TxZkEvmStatus status="L1 Confirmed"/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
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;
...@@ -6,13 +6,14 @@ import React from 'react'; ...@@ -6,13 +6,14 @@ import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import config from 'configs/app';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import delay from 'lib/delay'; import delay from 'lib/delay';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
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 { TX } from 'stubs/tx'; import { TX, TX_ZKEVM_L2 } from 'stubs/tx';
interface Params { interface Params {
onTxStatusUpdate?: () => void; onTxStatusUpdate?: () => void;
...@@ -34,7 +35,7 @@ export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params ...@@ -34,7 +35,7 @@ export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params
queryOptions: { queryOptions: {
enabled: Boolean(hash), enabled: Boolean(hash),
refetchOnMount: false, refetchOnMount: false,
placeholderData: TX, placeholderData: config.features.zkEvmRollup.isEnabled ? TX_ZKEVM_L2 : TX,
}, },
}); });
const { data, isError, isLoading } = queryResult; const { data, isError, isLoading } = queryResult;
......
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