Skip to content

Commit

Permalink
add signers mobile view
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed Aug 8, 2024
1 parent ddb5c42 commit 0cbc1fd
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 93 deletions.
3 changes: 3 additions & 0 deletions stubs/arbitrumL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,7 @@ export const ARBITRUM_L2_TXN_BATCH: ArbitrumL2TxnBatch = {
before_acc: '0x2ed7c4985eb778d76ec400a43805e7feecc8c2afcdb492dbe5caf227de6d37bc',
start_block: 1245209,
end_block: 1245490,
data_availability: {
batch_data_container: 'in_blob4844',
},
};
8 changes: 5 additions & 3 deletions types/api/arbitrumL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export type ArbitrumL2TxnBatchesResponse = {
} | null;
}

type BatchDataAvailability = {
export type ArbitrumL2TxnBatchDAAnytrust = {
batch_data_container: 'in_anytrust';
bls_signature: string;
data_hash: string;
Expand All @@ -61,7 +61,9 @@ type BatchDataAvailability = {
trusted: boolean;
proof?: string;
}>;
} | {
}

export type ArbitrumL2TxnBatchDataAvailability = ArbitrumL2TxnBatchDAAnytrust | {
batch_data_container: Exclude<BatchDataContainer, 'in_anytrust'>;
}

Expand All @@ -73,7 +75,7 @@ export type ArbitrumL2TxnBatch = {
start_block: number;
number: number;
transactions_count: number;
data_availability: BatchDataAvailability;
data_availability: ArbitrumL2TxnBatchDataAvailability;
}

export type ArbitrumL2BatchTxs = {
Expand Down
19 changes: 13 additions & 6 deletions ui/pages/ArbitrumL2TxnBatch.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,25 @@ test('base view', async({ render, mockApiResponse }) => {
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.use({ viewport: devices['iPhone 13 Pro'].viewport });
test('base view', async({ render, mockApiResponse }) => {
await mockApiResponse('arbitrum_l2_txn_batch', batchData, { pathParams: { number: batchNumber } });
const component = await render(<ArbitrumL2TxnBatch/>, { hooksConfig });
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('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();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 4 additions & 84 deletions ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
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 { useRouter } from 'next/router';
import React from 'react';
Expand All @@ -9,7 +9,6 @@ import type { ArbitrumL2TxnBatch } from 'types/api/arbitrumL2';
import { route } from 'nextjs-routes';

import type { ResourceError } from 'lib/api/resources';
import dayjs from 'lib/date/dayjs';
import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import isCustomAppError from 'ui/shared/AppError/isCustomAppError';
import ArbitrumL2TxnBatchDA from 'ui/shared/batch/ArbitrumL2TxnBatchDA';
Expand All @@ -19,12 +18,11 @@ import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsTimestamp from 'ui/shared/DetailsTimestamp';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShorten from 'ui/shared/HashStringShorten';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import IconSvg from 'ui/shared/IconSvg';
import LinkInternal from 'ui/shared/links/LinkInternal';
import PrevNext from 'ui/shared/PrevNext';
import TextSeparator from 'ui/shared/TextSeparator';

import ArbitrumL2TxnBatchDetailsDA from './ArbitrumL2TxnBatchDetailsDA';
interface Props {
query: UseQueryResult<ArbitrumL2TxnBatch, ResourceError>;
}
Expand Down Expand Up @@ -54,8 +52,6 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => {
router.push({ pathname: '/batches/[number]', query: { number: nextId } }, undefined);
}, [ data, router ]);

const signersBg = useColorModeValue('blackAlpha.50', 'whiteAlpha.50');

if (isError) {
if (isCustomAppError(error)) {
throwOnResourceLoadError({ isError, error });
Expand Down Expand Up @@ -227,83 +223,7 @@ const ArbitrumL2TxnBatchDetails = ({ query }: Props) => {
<>
<GridItem colSpan={{ base: undefined, lg: 2 }} mt={{ base: 1, lg: 4 }}/>

<DetailsInfoItem.Label
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>
<ArbitrumL2TxnBatchDetailsDA dataAvailability={ data.data_availability }/>
</>
) }
</>
Expand Down
122 changes: 122 additions & 0 deletions ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchDetailsDA.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
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;

0 comments on commit 0cbc1fd

Please sign in to comment.