Commit 0cbc1fdc authored by isstuev's avatar isstuev

add signers mobile view

parent ddb5c42e
...@@ -32,4 +32,7 @@ export const ARBITRUM_L2_TXN_BATCH: ArbitrumL2TxnBatch = { ...@@ -32,4 +32,7 @@ export const ARBITRUM_L2_TXN_BATCH: ArbitrumL2TxnBatch = {
before_acc: '0x2ed7c4985eb778d76ec400a43805e7feecc8c2afcdb492dbe5caf227de6d37bc', before_acc: '0x2ed7c4985eb778d76ec400a43805e7feecc8c2afcdb492dbe5caf227de6d37bc',
start_block: 1245209, start_block: 1245209,
end_block: 1245490, end_block: 1245490,
data_availability: {
batch_data_container: 'in_blob4844',
},
}; };
...@@ -51,7 +51,7 @@ export type ArbitrumL2TxnBatchesResponse = { ...@@ -51,7 +51,7 @@ export type ArbitrumL2TxnBatchesResponse = {
} | null; } | null;
} }
type BatchDataAvailability = { export type ArbitrumL2TxnBatchDAAnytrust = {
batch_data_container: 'in_anytrust'; batch_data_container: 'in_anytrust';
bls_signature: string; bls_signature: string;
data_hash: string; data_hash: string;
...@@ -61,7 +61,9 @@ type BatchDataAvailability = { ...@@ -61,7 +61,9 @@ type BatchDataAvailability = {
trusted: boolean; trusted: boolean;
proof?: string; proof?: string;
}>; }>;
} | { }
export type ArbitrumL2TxnBatchDataAvailability = ArbitrumL2TxnBatchDAAnytrust | {
batch_data_container: Exclude<BatchDataContainer, 'in_anytrust'>; batch_data_container: Exclude<BatchDataContainer, 'in_anytrust'>;
} }
...@@ -73,7 +75,7 @@ export type ArbitrumL2TxnBatch = { ...@@ -73,7 +75,7 @@ export type ArbitrumL2TxnBatch = {
start_block: number; start_block: number;
number: number; number: number;
transactions_count: number; transactions_count: number;
data_availability: BatchDataAvailability; data_availability: ArbitrumL2TxnBatchDataAvailability;
} }
export type ArbitrumL2BatchTxs = { export type ArbitrumL2BatchTxs = {
......
...@@ -24,6 +24,13 @@ test('base view', async({ render, mockApiResponse }) => { ...@@ -24,6 +24,13 @@ test('base view', async({ render, mockApiResponse }) => {
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
test('with anytrust DA', async({ render, mockApiResponse }) => {
await mockApiResponse('arbitrum_l2_txn_batch', batchDataAnytrust, { pathParams: { number: batchNumber } });
const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig });
await component.getByText('Show data availability info').click();
await expect(component).toHaveScreenshot();
});
test.describe('mobile', () => { test.describe('mobile', () => {
test.use({ viewport: devices['iPhone 13 Pro'].viewport }); test.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ render, mockApiResponse }) => { test('base view', async({ render, mockApiResponse }) => {
...@@ -31,11 +38,11 @@ test.describe('mobile', () => { ...@@ -31,11 +38,11 @@ test.describe('mobile', () => {
const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig }); const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig });
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
});
test('with anytrust DA', async({ render, mockApiResponse }) => { test('with anytrust DA', async({ render, mockApiResponse }) => {
await mockApiResponse('arbitrum_l2_txn_batch', batchDataAnytrust, { pathParams: { number: batchNumber } }); await mockApiResponse('arbitrum_l2_txn_batch', batchDataAnytrust, { pathParams: { number: batchNumber } });
const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig }); const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig });
await component.getByText('Show data availability info').click(); await component.getByText('Show data availability info').click();
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
});
}); });
import { Grid, GridItem, Link, Text, Flex, Box, Skeleton, useColorModeValue } from '@chakra-ui/react'; import { Grid, GridItem, Link, Skeleton } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; 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';
...@@ -9,7 +9,6 @@ import type { ArbitrumL2TxnBatch } from 'types/api/arbitrumL2'; ...@@ -9,7 +9,6 @@ import type { ArbitrumL2TxnBatch } from 'types/api/arbitrumL2';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import dayjs from 'lib/date/dayjs';
import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError'; import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError'; import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import ArbitrumL2TxnBatchDA from 'ui/shared/batch/ArbitrumL2TxnBatchDA'; import ArbitrumL2TxnBatchDA from 'ui/shared/batch/ArbitrumL2TxnBatchDA';
...@@ -19,12 +18,11 @@ import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem'; ...@@ -19,12 +18,11 @@ import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsTimestamp from 'ui/shared/DetailsTimestamp'; import DetailsTimestamp from 'ui/shared/DetailsTimestamp';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1'; import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1'; import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShorten from 'ui/shared/HashStringShorten';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/links/LinkInternal'; import LinkInternal from 'ui/shared/links/LinkInternal';
import PrevNext from 'ui/shared/PrevNext'; import PrevNext from 'ui/shared/PrevNext';
import TextSeparator from 'ui/shared/TextSeparator';
import ArbitrumL2TxnBatchDetailsDA from './ArbitrumL2TxnBatchDetailsDA';
interface Props { interface Props {
query: UseQueryResult<ArbitrumL2TxnBatch, ResourceError>; query: UseQueryResult<ArbitrumL2TxnBatch, ResourceError>;
} }
...@@ -54,8 +52,6 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => { ...@@ -54,8 +52,6 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => {
router.push({ pathname: '/batches/[number]', query: { number: nextId } }, undefined); router.push({ pathname: '/batches/[number]', query: { number: nextId } }, undefined);
}, [ data, router ]); }, [ data, router ]);
const signersBg = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');
if (isError) { if (isError) {
if (isCustomAppError(error)) { if (isCustomAppError(error)) {
throwOnResourceLoadError({ isError, error }); throwOnResourceLoadError({ isError, error });
...@@ -227,83 +223,7 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => { ...@@ -227,83 +223,7 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => {
<> <>
<GridItem colSpan={{ base: undefined, lg: 2 }} mt={{ base: 1, lg: 4 }}/> <GridItem colSpan={{ base: undefined, lg: 2 }} mt={{ base: 1, lg: 4 }}/>
<DetailsInfoItem.Label <ArbitrumL2TxnBatchDetailsDA dataAvailability={ data.data_availability }/>
isLoading={ isPlaceholderData }
hint="Aggregated BLS signature of AnyTrust committee members"
>
Signature
</DetailsInfoItem.Label>
<DetailsInfoItem.Value wordBreak="break-all" whiteSpace="break-spaces">
{ data.data_availability.bls_signature }
</DetailsInfoItem.Value>
<DetailsInfoItem.Label
isLoading={ isPlaceholderData }
hint="The hash of the data blob stored by the AnyTrust committee"
>
Data hash
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
{ data.data_availability.data_hash }
<CopyToClipboard text={ data.data_availability.data_hash } ml={ 2 }/>
</DetailsInfoItem.Value>
<DetailsInfoItem.Label
isLoading={ isPlaceholderData }
hint="Expiration timeout for the data blob"
>
Timeout
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
{ dayjs(data.data_availability.timeout) < dayjs() ?
<DetailsTimestamp timestamp={ data.data_availability.timeout }/> :
(
<>
<Text>{ dayjs(data.data_availability.timeout).format('llll') }</Text>
<TextSeparator color="gray.500"/>
<Text color="red.500">{ dayjs(data.data_availability.timeout).diff(dayjs(), 'day') } days left</Text>
</>
)
}
</DetailsInfoItem.Value>
<DetailsInfoItem.Label
isLoading={ isPlaceholderData }
hint="Members of AnyTrust committee"
>
Signers
</DetailsInfoItem.Label>
<DetailsInfoItem.Value overflowX="scroll">
<Grid
templateColumns="1fr auto auto"
gap={ 5 }
backgroundColor={ signersBg }
padding={ 4 }
borderRadius="md"
minW="600px"
>
<Text fontWeight={ 600 }>Key</Text>
<Text fontWeight={ 600 }>Trusted</Text>
<Text fontWeight={ 600 }>Proof</Text>
{ data.data_availability.signers.map(signer => (
<>
<Flex justifyContent="space-between">
<Text wordBreak="break-all" whiteSpace="break-spaces">{ signer.key }</Text>
<CopyToClipboard text={ signer.key } ml={ 2 }/>
</Flex>
<Box justifySelf="center">
{ signer.trusted ? <IconSvg name="check" boxSize={ 6 }/> : <IconSvg name="cross" boxSize={ 6 }/> }
</Box>
{ signer.proof ? (
<Flex>
<HashStringShorten hash={ signer.proof }/>
<CopyToClipboard text={ signer.proof } ml={ 2 }/>
</Flex>
) : '-' }
</>
)) }
</Grid>
</DetailsInfoItem.Value>
</> </>
) } ) }
</> </>
......
import { Grid, Text, Flex, Box, useColorModeValue, Show, Hide, VStack } from '@chakra-ui/react';
import React from 'react';
import type { ArbitrumL2TxnBatchDAAnytrust } from 'types/api/arbitrumL2';
import dayjs from 'lib/date/dayjs';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsTimestamp from 'ui/shared/DetailsTimestamp';
import HashStringShorten from 'ui/shared/HashStringShorten';
import IconSvg from 'ui/shared/IconSvg';
import TextSeparator from 'ui/shared/TextSeparator';
type Props = {
dataAvailability: ArbitrumL2TxnBatchDAAnytrust;
}
const ArbitrumL2TxnBatchDetailsDA = ({ dataAvailability }: Props) => {
const signersBg = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');
return (
<>
<DetailsInfoItem.Label
hint="Aggregated BLS signature of AnyTrust committee members"
>
Signature
</DetailsInfoItem.Label><DetailsInfoItem.Value wordBreak="break-all" whiteSpace="break-spaces">
{ dataAvailability.bls_signature }
</DetailsInfoItem.Value><DetailsInfoItem.Label
hint="The hash of the data blob stored by the AnyTrust committee"
>
Data hash
</DetailsInfoItem.Label><DetailsInfoItem.Value>
{ dataAvailability.data_hash }
<CopyToClipboard text={ dataAvailability.data_hash } ml={ 2 }/>
</DetailsInfoItem.Value><DetailsInfoItem.Label
hint="Expiration timeout for the data blob"
>
Timeout
</DetailsInfoItem.Label><DetailsInfoItem.Value>
{ dayjs(dataAvailability.timeout) < dayjs() ?
<DetailsTimestamp timestamp={ dataAvailability.timeout }/> :
(
<>
<Text>{ dayjs(dataAvailability.timeout).format('llll') }</Text>
<TextSeparator color="gray.500"/>
<Text color="red.500">{ dayjs(dataAvailability.timeout).diff(dayjs(), 'day') } days left</Text>
</>
) }
</DetailsInfoItem.Value>
<DetailsInfoItem.Label
hint="Members of AnyTrust committee"
>
Signers
</DetailsInfoItem.Label>
<DetailsInfoItem.Value overflowX="scroll" fontSize="sm">
<Show above="lg" ssr={ false }>
<Grid
templateColumns="1fr auto auto"
gap={ 5 }
backgroundColor={ signersBg }
padding={ 4 }
borderRadius="md"
minW="600px"
>
<Text fontWeight={ 600 }>Key</Text>
<Text fontWeight={ 600 }>Trusted</Text>
<Text fontWeight={ 600 }>Proof</Text>
{ dataAvailability.signers.map(signer => (
<>
<Flex justifyContent="space-between">
<Text wordBreak="break-all" whiteSpace="break-spaces">{ signer.key }</Text>
<CopyToClipboard text={ signer.key } ml={ 2 }/>
</Flex>
<Box justifySelf="center">
{ signer.trusted ? <IconSvg name="check" boxSize={ 6 }/> : <IconSvg name="cross" boxSize={ 6 }/> }
</Box>
{ signer.proof ? (
<Flex>
<HashStringShorten hash={ signer.proof }/>
<CopyToClipboard text={ signer.proof } ml={ 2 }/>
</Flex>
) : '-' }
</>
)) }
</Grid>
</Show>
<Hide above="lg" ssr={ false }>
<Box backgroundColor={ signersBg } borderRadius="md">
{ dataAvailability.signers.map(signer => (
<VStack padding={ 4 } key={ signer.key } gap={ 2 }>
<Flex w="100%" justifyContent="space-between">
<Text fontWeight={ 600 }>Key</Text>
<CopyToClipboard text={ signer.key }/>
</Flex>
<Text wordBreak="break-all" whiteSpace="break-spaces">{ signer.key }</Text>
<Flex w="100%" alignItems="center">
<Flex alignItems="center" w="50%">
<Text fontWeight={ 600 } mr={ 2 }>Trusted</Text>
{ signer.trusted ? <IconSvg name="check" boxSize={ 6 }/> : <IconSvg name="cross" boxSize={ 6 }/> }
</Flex>
<Flex alignItems="center" w="50%">
<Text fontWeight={ 600 } mr={ 2 }>Proof</Text>
{ signer.proof ? (
<Flex>
<HashStringShorten hash={ signer.proof }/>
<CopyToClipboard text={ signer.proof } ml={ 2 }/>
</Flex>
) : '-' }
</Flex>
</Flex>
</VStack>
)) }
</Box>
</Hide>
</DetailsInfoItem.Value>
</>
);
};
export default ArbitrumL2TxnBatchDetailsDA;
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