components for Block and Tx entities (#1108)
* base implementation of entity * refactor other components to make use of BlockEntity * tests * migrate entities w/o icon + L2 blocks * base implementation of tx entity * delet TransactionSnippet * remove type="transaction" from AddressLink * tests for TxEntity * make EntityBase components * common styles for icon color and spacing to text * update icon color in tests * update icons to slime format * Address entity
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.83 0 1 5.03v10.267l6.825 3.976-.034-1.67-5.421-3.175V6.8l6.757 3.818V19.6L9.84 20l.736-.401v-8.98L17.323 6.8v7.628l-5.388 3.108v1.67l6.858-3.834V5.029L9.829 0Zm0 9.415L3.238 5.531l6.59-3.877 6.75 3.877-6.75 3.884Zm-5.082 3.767 1.32-.752-.112-.196-1.32.752.112.196ZM7.06 11.86l1.32-.752-.113-.196-1.32.752.113.196Zm2.868-3.527V6.821h-.226v1.512h.226Zm0-2.636v-1.52h-.226v1.52h.226Zm0-2.534v-1.52h-.226v1.52h.226Zm2.854 8.51-1.31-.76-.114.195 1.311.76.114-.196Zm2.287 1.322-1.32-.76-.113.195 1.32.76.113-.195Zm-12.654 1.52 1.311-.751-.112-.196-1.311.751.112.196Zm14.979-.198-1.311-.76-.114.195 1.311.76.114-.195Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 728 B |
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.392 1.45c.252-.288.592-.45.948-.45h8.038a.63.63 0 0 1 .474.225L17.54 6.61a.83.83 0 0 1 .196.544v12.308c0 .408-.141.799-.393 1.087-.25.289-.592.451-.947.451H4.34c-.356 0-.696-.162-.948-.45A1.661 1.661 0 0 1 3 19.461V2.538c0-.408.141-.799.392-1.087Zm.948 1.088h6.87v4.497c0 .388.315.702.702.702h4.485v11.725H4.34V2.538Zm8.274.59 2.791 3.205h-2.791V3.128ZM6.5 11a.5.5 0 0 0 0 1h7.2a.5.5 0 0 0 0-1H6.5ZM6 13.9a.5.5 0 0 1 .5-.5h7.2a.5.5 0 1 1 0 1H6.5a.5.5 0 0 1-.5-.5Zm4.5 2.1a.5.5 0 0 0 0 1h3.2a.5.5 0 0 0 0-1h-3.2Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.28 1.352A1.408 1.408 0 0 1 4.34.85h8.038a.78.78 0 0 1 .587.276l4.689 5.385a.98.98 0 0 1 .233.642v12.308c0 .442-.153.869-.43 1.187a1.408 1.408 0 0 1-1.06.502H4.34c-.403 0-.783-.184-1.06-.502a1.811 1.811 0 0 1-.43-1.187V2.538c0-.442.153-.869.43-1.186Zm1.06-.202c-.308 0-.61.14-.834.399-.226.259-.356.615-.356.99V19.46c0 .375.13.73.356.99.225.258.526.399.834.399h12.057c.309 0 .61-.14.834-.4.226-.259.356-.614.356-.989V7.153a.68.68 0 0 0-.16-.445L12.74 1.323a.48.48 0 0 0-.36-.173h-8.04Zm7.02 1.238v4.647c0 .304.248.551.552.551h4.635v12.025H4.19V2.388h7.17Zm-6.87.3v16.623h11.757V7.886h-4.335a.852.852 0 0 1-.852-.851V2.688H4.49Zm7.974.039 3.27 3.756h-3.27V2.727Zm.3.801v2.655h2.312l-2.312-2.655ZM6.5 11.15a.35.35 0 1 0 0 .7h7.2a.35.35 0 1 0 0-.7H6.5Zm-.65.35a.65.65 0 0 1 .65-.65h7.2a.65.65 0 1 1 0 1.3H6.5a.65.65 0 0 1-.65-.65Zm0 2.4a.65.65 0 0 1 .65-.65h7.2a.65.65 0 1 1 0 1.3H6.5a.65.65 0 0 1-.65-.65Zm.65-.35a.35.35 0 1 0 0 .7h7.2a.35.35 0 1 0 0-.7H6.5Zm4 2.6a.35.35 0 1 0 0 .7h3.2a.35.35 0 1 0 0-.7h-3.2Zm-.65.35a.65.65 0 0 1 .65-.65h3.2a.65.65 0 1 1 0 1.3h-3.2a.65.65 0 0 1-.65-.65Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.392.45C3.644.163 3.984 0 4.34 0h8.038a.63.63 0 0 1 .474.225L17.54 5.61a.83.83 0 0 1 .196.544v12.308c0 .408-.141.799-.393 1.087-.25.289-.592.451-.947.451H4.34c-.356 0-.696-.162-.948-.45A1.661 1.661 0 0 1 3 18.461V1.538c0-.408.141-.799.392-1.087Zm8.709 1.088H4.34v16.924h12.057V6.472l-4.296-4.934Z" fill="currentColor"/>
|
||||
<path d="m7.3 13.357 2.2 2.357L13.9 11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.912.42c.388 0 .702.315.702.703v4.21h4.21a.702.702 0 1 1 0 1.404h-4.912a.702.702 0 0 1-.702-.702V1.123c0-.388.315-.702.702-.702Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 791 B |
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.77 7.794H.987a.97.97 0 0 1-.549-.17 1.009 1.009 0 0 1-.364-.453 1.041 1.041 0 0 1 .218-1.106l3.722-3.827a.97.97 0 0 1 1.333.06 1.033 1.033 0 0 1 .058 1.37L3.371 5.764H17.77c.262 0 .513.107.698.297.185.19.29.449.29.718 0 .269-.105.527-.29.717a.973.973 0 0 1-.698.297ZM2.23 12.066h16.783c.195 0 .386.059.549.17.162.11.289.269.364.454a1.042 1.042 0 0 1-.218 1.106l-3.737 3.842-.006.007a.99.99 0 0 1-.711.354.963.963 0 0 1-.736-.296 1.017 1.017 0 0 1-.289-.757 1.04 1.04 0 0 1 .345-.731l.007-.007 2.047-2.112H2.23a.973.973 0 0 1-.698-.298 1.03 1.03 0 0 1-.29-.717c0-.27.105-.527.29-.718a.974.974 0 0 1 .698-.297Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 767 B |
|
Before Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.013 21H2.035a.626.626 0 0 1-.625-.625V4.749c0-.345.28-.625.625-.625h2.85V1.625c0-.345.279-.625.624-.625h7.853c.008 0 .014.002.021.004l.018.004a.6.6 0 0 1 .186.04.616.616 0 0 1 .208.126l4.603 4.414-.002.002a.622.622 0 0 1 .194.45v9.733c0 1.16-.943 2.103-2.102 2.103h-1.372v1.021c0 1.16-.944 2.103-2.103 2.103Zm3.764-15.586-2.79-2.69v1.838c0 .47.382.852.852.852h1.938Zm-3.673-3.531H5.767v15.11h11.089c.469 0 .851-.382.851-.852V6.297H14.84c-1.16 0-1.735-.575-1.735-1.735v-2.68Zm-8.22 3.124H2.293v15.11H13.38c.47 0 .852-.75.852-1.22v-1.02H5.509a.625.625 0 0 1-.625-.626V5.007Zm10.182 4.866a.418.418 0 1 0 0-.836H9.568l.54-.542a.418.418 0 0 0-.302-.69c-.105-.004-.226-.068-.306 0L8.172 9.103c-.06.058-.007.191-.024.272a.418.418 0 0 0 .178.43c.069.045.137.157.22.157l6.52-.088Zm-.013 1.377H8.545c-.11 0-.217.05-.295.129-.079.078-.123.265-.123.376a.418.418 0 0 0 .418.418h5.498l-.54.542a.417.417 0 0 0 .12.707.415.415 0 0 0 .47-.118l1.347-1.218c.059-.058.007-.169.023-.25a.417.417 0 0 0-.178-.43c-.068-.045-.15-.156-.232-.156Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.784 1.625c0-.4.325-.725.725-.725h7.853c.023 0 .042.006.048.008h.001a.705.705 0 0 1 .205.044h.002l.044.016a.72.72 0 0 1 .202.134l4.677 4.485-.007.007a.717.717 0 0 1 .156.446v9.733a2.205 2.205 0 0 1-2.202 2.203h-1.272v.921a2.205 2.205 0 0 1-2.203 2.203H2.035a.726.726 0 0 1-.725-.725V4.749c0-.4.325-.725.725-.725h2.75V1.625ZM18.255 5.59l-4.53-4.344a.518.518 0 0 0-.167-.103l-.026-.008a.492.492 0 0 0-.136-.027m4.86 4.482-.003.002.074.07c.1.097.163.23.163.378v9.733a2.005 2.005 0 0 1-2.002 2.003h-1.472v1.121a2.005 2.005 0 0 1-2.003 2.003H2.035a.526.526 0 0 1-.525-.525V4.749c0-.29.235-.525.525-.525h2.95V1.625c0-.29.234-.525.524-.525h7.846m-7.688.683h7.537v2.78c0 .564.14.968.403 1.231.264.263.668.403 1.232.403h2.968v9.944a.953.953 0 0 1-.951.952H5.667V1.783Zm.2.2v14.91h10.989a.753.753 0 0 0 .751-.752V6.397H14.84c-.595 0-1.059-.147-1.373-.462-.314-.314-.462-.778-.462-1.373v-2.58H5.867Zm8.02.505 3.138 3.026h-2.186a.953.953 0 0 1-.952-.952V2.488Zm.2.471v1.603c0 .415.337.752.752.752h1.69L14.087 2.96ZM2.193 4.907h2.791V17.25c0 .29.235.525.525.525h8.824v1.121c0 .257-.103.58-.265.84-.16.254-.399.48-.687.48H2.193V4.907Zm.2.2v14.91H13.38c.18 0 .368-.148.517-.387.146-.234.235-.52.235-.733v-.92H5.509a.725.725 0 0 1-.725-.726V5.107H2.393Zm7.193 2.872L8.334 9.231a.32.32 0 0 0-.07.347.318.318 0 0 0 .294.195h6.508a.318.318 0 0 0 0-.636H9.327l.707-.71a.319.319 0 0 0-.448-.448Zm-.133-.15a.518.518 0 0 1 .73.731l-.004.006-.37.37h5.257a.518.518 0 0 1 0 1.037H8.56m-.366-.884a.518.518 0 0 0 .366.884m.894-2.143-1.26 1.26 1.26-1.26Zm-.908 3.607a.318.318 0 1 0 0 .636h5.739l-.715.718a.319.319 0 0 0 .09.537.319.319 0 0 0 .358-.089l.005-.006 1.255-1.254a.318.318 0 0 0-.047-.489.318.318 0 0 0-.177-.053H8.545Zm-.366-.048a.518.518 0 0 1 .366-.152h6.508m.365.883a.518.518 0 0 0-.365-.883m.365.883-1.251 1.252a.518.518 0 1 1-.732-.73l.367-.369H8.545a.518.518 0 0 1-.366-.884" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -9,7 +9,7 @@ export const hash = '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859';
|
||||
export const withName: AddressParam = {
|
||||
hash: hash,
|
||||
implementation_name: null,
|
||||
is_contract: true,
|
||||
is_contract: false,
|
||||
is_verified: null,
|
||||
name: 'ArianeeStore',
|
||||
private_tags: [],
|
||||
@@ -20,7 +20,7 @@ export const withName: AddressParam = {
|
||||
export const withoutName: AddressParam = {
|
||||
hash: hash,
|
||||
implementation_name: null,
|
||||
is_contract: true,
|
||||
is_contract: false,
|
||||
is_verified: null,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Text, Grid, Skeleton } from '@chakra-ui/react';
|
||||
import { Box, Text, Grid } from '@chakra-ui/react';
|
||||
import type { UseQueryResult } from '@tanstack/react-query';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
@@ -7,7 +7,6 @@ import type { Address as TAddress } from 'types/api/address';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import type { ResourceError } from 'lib/api/resources';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
@@ -15,10 +14,11 @@ import { ADDRESS_COUNTERS } from 'stubs/address';
|
||||
import AddressCounterItem from 'ui/address/details/AddressCounterItem';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import AddressHeadingInfo from 'ui/shared/AddressHeadingInfo';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import DataFetchAlert from 'ui/shared/DataFetchAlert';
|
||||
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
|
||||
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
@@ -104,7 +104,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
|
||||
>
|
||||
<AddressLink type="address" hash={ data.creator_address_hash } truncation="constant"/>
|
||||
<Text whiteSpace="pre"> at txn </Text>
|
||||
<AddressLink hash={ data.creation_tx_hash } type="transaction" truncation="constant"/>
|
||||
<TxEntity hash={ data.creation_tx_hash } truncation="constant" noIcon/>
|
||||
</DetailsInfoItem>
|
||||
) }
|
||||
{ data.is_contract && data.implementation_address && (
|
||||
@@ -210,16 +210,10 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
|
||||
py={{ base: '2px', lg: 1 }}
|
||||
isLoading={ addressQuery.isPlaceholderData }
|
||||
>
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block_number_balance_updated_at) } }) }
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
>
|
||||
<Box mr={ 2 }>
|
||||
<Icon as={ blockIcon } boxSize={ 6 } isLoading={ addressQuery.isPlaceholderData }/>
|
||||
</Box>
|
||||
<Skeleton isLoaded={ !addressQuery.isPlaceholderData }>{ data.block_number_balance_updated_at }</Skeleton>
|
||||
</LinkInternal>
|
||||
<BlockEntity
|
||||
number={ data.block_number_balance_updated_at }
|
||||
isLoading={ addressQuery.isPlaceholderData }
|
||||
/>
|
||||
</DetailsInfoItem>
|
||||
) }
|
||||
<DetailsSponsoredItem isLoading={ addressQuery.isPlaceholderData }/>
|
||||
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 50 KiB |
@@ -4,12 +4,10 @@ import React from 'react';
|
||||
|
||||
import type { Block } from 'types/api/block';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
import Utilization from 'ui/shared/Utilization/Utilization';
|
||||
|
||||
@@ -19,16 +17,18 @@ type Props = Block & {
|
||||
};
|
||||
|
||||
const AddressBlocksValidatedListItem = (props: Props) => {
|
||||
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: props.height.toString() } });
|
||||
const timeAgo = useTimeAgoIncrement(props.timestamp, props.page === 1);
|
||||
const totalReward = getBlockTotalReward(props);
|
||||
|
||||
return (
|
||||
<ListItemMobile rowGap={ 2 } isAnimated>
|
||||
<Flex justifyContent="space-between" w="100%">
|
||||
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
|
||||
<LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ props.isLoading }
|
||||
number={ props.height }
|
||||
noIcon
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
|
||||
<span>{ timeAgo }</span>
|
||||
</Skeleton>
|
||||
|
||||
@@ -4,11 +4,9 @@ import React from 'react';
|
||||
|
||||
import type { Block } from 'types/api/block';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import Utilization from 'ui/shared/Utilization/Utilization';
|
||||
|
||||
type Props = Block & {
|
||||
@@ -17,16 +15,20 @@ type Props = Block & {
|
||||
};
|
||||
|
||||
const AddressBlocksValidatedTableItem = (props: Props) => {
|
||||
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(props.height) } });
|
||||
const timeAgo = useTimeAgoIncrement(props.timestamp, props.page === 1);
|
||||
const totalReward = getBlockTotalReward(props);
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Td>
|
||||
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
|
||||
<LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ props.isLoading }
|
||||
number={ props.height }
|
||||
noIcon
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
|
||||
|
||||
@@ -4,14 +4,11 @@ import React from 'react';
|
||||
|
||||
import type { AddressCoinBalanceHistoryItem } from 'types/api/address';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import { WEI, ZERO } from 'lib/consts';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
|
||||
type Props = AddressCoinBalanceHistoryItem & {
|
||||
@@ -20,7 +17,6 @@ type Props = AddressCoinBalanceHistoryItem & {
|
||||
};
|
||||
|
||||
const AddressCoinBalanceListItem = (props: Props) => {
|
||||
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(props.block_number) } });
|
||||
const deltaBn = BigNumber(props.delta).div(WEI);
|
||||
const isPositiveDelta = deltaBn.gte(ZERO);
|
||||
const timeAgo = useTimeAgoIncrement(props.block_timestamp, props.page === 1);
|
||||
@@ -44,16 +40,23 @@ const AddressCoinBalanceListItem = (props: Props) => {
|
||||
</Flex>
|
||||
<Flex columnGap={ 2 } w="100%">
|
||||
<Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Block</Skeleton>
|
||||
<Skeleton isLoaded={ !props.isLoading }>
|
||||
<LinkInternal href={ blockUrl } fontWeight="700">{ props.block_number }</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ props.isLoading }
|
||||
number={ props.block_number }
|
||||
noIcon
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</Flex>
|
||||
{ props.transaction_hash && (
|
||||
<Flex columnGap={ 2 } w="100%">
|
||||
<Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Txs</Skeleton>
|
||||
<Address maxW="150px" fontWeight="700">
|
||||
<AddressLink hash={ props.transaction_hash } type="transaction" isLoading={ props.isLoading }/>
|
||||
</Address>
|
||||
<TxEntity
|
||||
hash={ props.transaction_hash }
|
||||
isLoading={ props.isLoading }
|
||||
noIcon
|
||||
fontWeight={ 700 }
|
||||
maxW="150px"
|
||||
/>
|
||||
</Flex>
|
||||
) }
|
||||
<Flex columnGap={ 2 } w="100%">
|
||||
|
||||
@@ -4,13 +4,10 @@ import React from 'react';
|
||||
|
||||
import type { AddressCoinBalanceHistoryItem } from 'types/api/address';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import { WEI, ZERO } from 'lib/consts';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
|
||||
type Props = AddressCoinBalanceHistoryItem & {
|
||||
page: number;
|
||||
@@ -18,7 +15,6 @@ type Props = AddressCoinBalanceHistoryItem & {
|
||||
};
|
||||
|
||||
const AddressCoinBalanceTableItem = (props: Props) => {
|
||||
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(props.block_number) } });
|
||||
const deltaBn = BigNumber(props.delta).div(WEI);
|
||||
const isPositiveDelta = deltaBn.gte(ZERO);
|
||||
const timeAgo = useTimeAgoIncrement(props.block_timestamp, props.page === 1);
|
||||
@@ -26,18 +22,25 @@ const AddressCoinBalanceTableItem = (props: Props) => {
|
||||
return (
|
||||
<Tr>
|
||||
<Td>
|
||||
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
|
||||
<LinkInternal href={ blockUrl } fontWeight="700">{ props.block_number }</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ props.isLoading }
|
||||
number={ props.block_number }
|
||||
noIcon
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
{ props.transaction_hash &&
|
||||
(
|
||||
<Address w="150px" fontWeight="700">
|
||||
<AddressLink hash={ props.transaction_hash } type="transaction" isLoading={ props.isLoading }/>
|
||||
</Address>
|
||||
)
|
||||
}
|
||||
{ props.transaction_hash && (
|
||||
<TxEntity
|
||||
hash={ props.transaction_hash }
|
||||
isLoading={ props.isLoading }
|
||||
noIcon
|
||||
fontWeight={ 700 }
|
||||
maxW="150px"
|
||||
/>
|
||||
) }
|
||||
</Td>
|
||||
<Td>
|
||||
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
|
||||
@@ -51,7 +54,7 @@ const AddressCoinBalanceTableItem = (props: Props) => {
|
||||
</Td>
|
||||
<Td isNumeric display="flex" justifyContent="end">
|
||||
<Skeleton isLoaded={ !props.isLoading }>
|
||||
<Stat flexGrow="0">
|
||||
<Stat flexGrow="0" lineHeight={ 5 }>
|
||||
<StatHelpText display="flex" mb={ 0 } alignItems="center">
|
||||
<StatArrow type={ isPositiveDelta ? 'increase' : 'decrease' }/>
|
||||
<Text as="span" color={ isPositiveDelta ? 'green.500' : 'red.500' } fontWeight={ 600 }>
|
||||
|
||||
@@ -4,8 +4,6 @@ import React from 'react';
|
||||
|
||||
import type { InternalTransaction } from 'types/api/internalTransaction';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import eastArrowIcon from 'icons/arrows/east.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
@@ -15,8 +13,9 @@ import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import InOutTag from 'ui/shared/InOutTag';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
import TxStatus from 'ui/shared/TxStatus';
|
||||
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
|
||||
@@ -50,16 +49,25 @@ const TxInternalsListItem = ({
|
||||
<TxStatus status={ success ? 'ok' : 'error' } errorText={ error } isLoading={ isLoading }/>
|
||||
</Flex>
|
||||
<Flex justifyContent="space-between" width="100%">
|
||||
<AddressLink fontWeight="700" hash={ txnHash } truncation="constant" type="transaction" isLoading={ isLoading }/>
|
||||
<TxEntity
|
||||
hash={ txnHash }
|
||||
isLoading={ isLoading }
|
||||
fontWeight={ 700 }
|
||||
truncation="constant"
|
||||
/>
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
|
||||
<span>{ dayjs(timestamp).fromNow() }</span>
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
<HStack spacing={ 1 }>
|
||||
<Skeleton isLoaded={ !isLoading } fontSize="sm" fontWeight={ 500 }>Block</Skeleton>
|
||||
<Skeleton isLoaded={ !isLoading }>
|
||||
<LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: block.toString() } }) }>{ block }</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ isLoading }
|
||||
number={ block }
|
||||
noIcon
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</HStack>
|
||||
<Box w="100%" display="flex" columnGap={ 3 }>
|
||||
<Address width="calc((100% - 48px) / 2)">
|
||||
|
||||
@@ -4,8 +4,6 @@ import React from 'react';
|
||||
|
||||
import type { InternalTransaction } from 'types/api/internalTransaction';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
@@ -15,8 +13,9 @@ import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import InOutTag from 'ui/shared/InOutTag';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import TxStatus from 'ui/shared/TxStatus';
|
||||
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
|
||||
|
||||
@@ -48,7 +47,12 @@ const AddressIntTxsTableItem = ({
|
||||
<Tr alignItems="top">
|
||||
<Td verticalAlign="middle">
|
||||
<Flex rowGap={ 3 } flexWrap="wrap">
|
||||
<AddressLink fontWeight="700" hash={ txnHash } type="transaction" isLoading={ isLoading }/>
|
||||
<TxEntity
|
||||
hash={ txnHash }
|
||||
isLoading={ isLoading }
|
||||
fontWeight={ 700 }
|
||||
noIcon
|
||||
/>
|
||||
{ timestamp && (
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
|
||||
<span>{ timeAgo }</span>
|
||||
@@ -67,11 +71,14 @@ const AddressIntTxsTableItem = ({
|
||||
</Flex>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">
|
||||
<LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: block.toString() } }) }>
|
||||
{ block }
|
||||
</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ isLoading }
|
||||
number={ block }
|
||||
noIcon
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 500 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<Address display="inline-flex" maxW="100%">
|
||||
|
||||
@@ -458,7 +458,15 @@ const BlockDetails = ({ query }: Props) => {
|
||||
hint="The hash of the block from which this block was generated"
|
||||
flexWrap="nowrap"
|
||||
>
|
||||
<AddressLink hash={ data.parent_hash } type="block" blockHeight={ String(data.height - 1) }/>
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.height - 1) } }) }
|
||||
overflow="hidden"
|
||||
whiteSpace="nowrap"
|
||||
>
|
||||
<HashStringShortenDynamic
|
||||
hash={ data.parent_hash }
|
||||
/>
|
||||
</LinkInternal>
|
||||
<CopyToClipboard text={ data.parent_hash }/>
|
||||
</DetailsInfoItem>
|
||||
) }
|
||||
|
||||
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 92 KiB |
@@ -15,6 +15,7 @@ import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
|
||||
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
@@ -38,17 +39,13 @@ const BlocksListItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
|
||||
<ListItemMobile rowGap={ 3 } key={ String(data.height) } isAnimated>
|
||||
<Flex justifyContent="space-between" w="100%">
|
||||
<Flex columnGap={ 2 } alignItems="center">
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">
|
||||
<LinkInternal
|
||||
fontWeight={ 600 }
|
||||
href={ route({
|
||||
pathname: '/block/[height_or_hash]',
|
||||
query: { height_or_hash: data.type === 'reorg' ? String(data.hash) : String(data.height) },
|
||||
}) }
|
||||
>
|
||||
{ data.height }
|
||||
</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ isLoading }
|
||||
number={ data.height }
|
||||
hash={ data.type === 'reorg' ? data.hash : undefined }
|
||||
noIcon
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Flex>
|
||||
<BlockTimestamp ts={ data.timestamp } isEnabled={ enableTimeIncrement } isLoading={ isLoading }/>
|
||||
</Flex>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { WEI } from 'lib/consts';
|
||||
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import TextSeparator from 'ui/shared/TextSeparator';
|
||||
@@ -45,17 +46,15 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
|
||||
<Td fontSize="sm">
|
||||
<Flex columnGap={ 2 } alignItems="center" mb={ 2 }>
|
||||
<Tooltip isDisabled={ data.type !== 'reorg' } label="Chain reorganizations">
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">
|
||||
<LinkInternal
|
||||
fontWeight={ 600 }
|
||||
href={ route({
|
||||
pathname: '/block/[height_or_hash]',
|
||||
query: { height_or_hash: data.type === 'reorg' ? String(data.hash) : String(data.height) },
|
||||
}) }
|
||||
>
|
||||
{ data.height }
|
||||
</LinkInternal>
|
||||
</Skeleton>
|
||||
<BlockEntity
|
||||
isLoading={ isLoading }
|
||||
number={ data.height }
|
||||
hash={ data.type === 'reorg' ? data.hash : undefined }
|
||||
noIcon
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
<BlockTimestamp ts={ data.timestamp } isEnabled={ enableTimeIncrement } isLoading={ isLoading }/>
|
||||
|
||||
@@ -10,12 +10,11 @@ import React from 'react';
|
||||
import type { Block } from 'types/api/block';
|
||||
|
||||
import config from 'configs/app';
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
|
||||
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
|
||||
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
|
||||
type Props = {
|
||||
block: Block;
|
||||
@@ -41,17 +40,14 @@ const LatestBlocksItem = ({ block, h, isLoading }: Props) => {
|
||||
w="100%"
|
||||
>
|
||||
<Flex alignItems="center" overflow="hidden" w="100%" mb={ 3 }>
|
||||
<Icon as={ blockIcon } boxSize="30px" color="link" isLoading={ isLoading } borderRadius="base"/>
|
||||
<AddressLink
|
||||
<BlockEntity
|
||||
isLoading={ isLoading }
|
||||
type="block"
|
||||
hash={ String(block.height) }
|
||||
blockHeight={ String(block.height) }
|
||||
fontSize="xl"
|
||||
fontWeight="500"
|
||||
ml={ 2 }
|
||||
mr="auto"
|
||||
number={ block.height }
|
||||
tailLength={ 2 }
|
||||
fontSize="xl"
|
||||
lineHeight={ 7 }
|
||||
fontWeight={ 500 }
|
||||
mr="auto"
|
||||
/>
|
||||
<BlockTimestamp
|
||||
ts={ block.timestamp }
|
||||
|
||||
@@ -8,17 +8,12 @@ import React from 'react';
|
||||
|
||||
import type { L2DepositsItem } from 'types/api/l2Deposits';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
@@ -36,51 +31,31 @@ const LatestTxsItem = ({ item, isLoading }: Props) => {
|
||||
}
|
||||
|
||||
const l1BlockLink = (
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl +
|
||||
route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l1_block_number.toString() } })
|
||||
}
|
||||
fontWeight={ 700 }
|
||||
display="inline-flex"
|
||||
mr={ 2 }
|
||||
<BlockEntityL1
|
||||
number={ item.l1_block_number }
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ blockIcon } boxSize="30px" isLoading={ isLoading } borderRadius="base"/>
|
||||
<Skeleton isLoaded={ !isLoading } ml={ 1 }>{ item.l1_block_number }</Skeleton>
|
||||
</LinkExternal>
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
);
|
||||
|
||||
const l1TxLink = (
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
maxW="100%"
|
||||
display="inline-flex"
|
||||
alignItems="center"
|
||||
overflow="hidden"
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
my="3px"
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ item.l1_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
);
|
||||
|
||||
const l2TxLink = (
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
overflow="hidden"
|
||||
w="100%"
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l2_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
hash={ item.l2_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
);
|
||||
|
||||
const content = (() => {
|
||||
|
||||
@@ -12,13 +12,13 @@ import type { Transaction } from 'types/api/transaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import transactionIcon from 'icons/transactions.svg';
|
||||
import getValueWithUnit from 'lib/getValueWithUnit';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxStatus from 'ui/shared/TxStatus';
|
||||
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
|
||||
import TxType from 'ui/txs/TxType';
|
||||
@@ -54,24 +54,20 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
|
||||
mt={ 2 }
|
||||
alignItems="center"
|
||||
>
|
||||
<Icon
|
||||
as={ transactionIcon }
|
||||
boxSize="30px"
|
||||
color="link"
|
||||
display="inline"
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
borderRadius="base"
|
||||
hash={ tx.hash }
|
||||
fontWeight="700"
|
||||
/>
|
||||
<Address overflow="hidden" w="calc(100% - 130px)" maxW="calc(100% - 130px)" ml={ 2 } mr={ 2 }>
|
||||
<AddressLink
|
||||
hash={ tx.hash }
|
||||
type="transaction"
|
||||
fontWeight="700"
|
||||
isLoading={ isLoading }
|
||||
/>
|
||||
</Address>
|
||||
{ tx.timestamp && (
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
|
||||
<Skeleton
|
||||
isLoaded={ !isLoading }
|
||||
color="text_secondary"
|
||||
fontWeight="400"
|
||||
fontSize="sm"
|
||||
flexShrink={ 0 }
|
||||
ml={ 2 }
|
||||
>
|
||||
<span>{ timeAgo }</span>
|
||||
</Skeleton>
|
||||
) }
|
||||
|
||||
@@ -11,13 +11,13 @@ import type { Transaction } from 'types/api/transaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
import transactionIcon from 'icons/transactions.svg';
|
||||
import getValueWithUnit from 'lib/getValueWithUnit';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxStatus from 'ui/shared/TxStatus';
|
||||
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
|
||||
import TxType from 'ui/txs/TxType';
|
||||
@@ -54,26 +54,14 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
|
||||
justifyContent="space-between"
|
||||
mb={ 6 }
|
||||
>
|
||||
<Flex mr={ 3 }>
|
||||
<Icon
|
||||
as={ transactionIcon }
|
||||
boxSize="30px"
|
||||
mr={ 2 }
|
||||
color="link"
|
||||
isLoading={ isLoading }
|
||||
/>
|
||||
<Address width="100%">
|
||||
<AddressLink
|
||||
hash={ tx.hash }
|
||||
type="transaction"
|
||||
fontWeight="700"
|
||||
truncation="constant"
|
||||
isLoading={ isLoading }
|
||||
/>
|
||||
</Address>
|
||||
</Flex>
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ tx.hash }
|
||||
fontWeight="700"
|
||||
truncation="constant"
|
||||
/>
|
||||
{ tx.timestamp && (
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm" ml={ 3 }>
|
||||
<span>{ timeAgo }</span>
|
||||
</Skeleton>
|
||||
) }
|
||||
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 63 KiB |
@@ -7,14 +7,13 @@ import type { L2DepositsItem } from 'types/api/l2Deposits';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
@@ -33,33 +32,23 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 block No</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l1_block_number.toString() } }) }
|
||||
fontWeight={ 600 }
|
||||
display="flex"
|
||||
<BlockEntityL1
|
||||
number={ item.l1_block_number }
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ blockIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } ml={ 1 }>{ item.l1_block_number }</Skeleton>
|
||||
</LinkExternal>
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
overflow="hidden"
|
||||
w="100%"
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l2_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
hash={ item.l2_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>Age</ListItemMobileGrid.Label>
|
||||
@@ -69,18 +58,12 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
maxW="100%"
|
||||
display="flex"
|
||||
overflow="hidden"
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ item.l1_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn origin</ListItemMobileGrid.Label>
|
||||
|
||||
@@ -7,14 +7,13 @@ import type { L2DepositsItem } from 'types/api/l2Deposits';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import HashStringShorten from 'ui/shared/HashStringShorten';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
@@ -29,51 +28,35 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Td verticalAlign="middle" fontWeight={ 600 }>
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l1_block_number.toString() } }) }
|
||||
fontWeight={ 600 }
|
||||
display="inline-flex"
|
||||
<Td verticalAlign="middle">
|
||||
<BlockEntityL1
|
||||
number={ item.l1_block_number }
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ blockIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } ml={ 1 }>
|
||||
{ item.l1_block_number }
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
overflow="hidden"
|
||||
w="100%"
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" ml={ 1 } overflow="hidden" whiteSpace="nowrap">
|
||||
<HashStringShorten hash={ item.l2_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
hash={ item.l2_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant"
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle" pr={ 12 }>
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block"><span>{ timeAgo }</span></Skeleton>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
maxW="100%"
|
||||
display="inline-flex"
|
||||
overflow="hidden"
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShorten hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ item.l1_tx_hash }
|
||||
truncation="constant"
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<LinkExternal
|
||||
|
||||
@@ -3,16 +3,12 @@ import React from 'react';
|
||||
|
||||
import type { L2OutputRootsItem } from 'types/api/l2OutputRoots';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
@@ -43,31 +39,23 @@ const OutputRootsListItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block #</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<LinkInternal
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
|
||||
<BlockEntityL2
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">{ item.l2_block_number }</Skeleton>
|
||||
</LinkInternal>
|
||||
number={ item.l2_block_number }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
noIcon
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkExternal
|
||||
maxW="100%"
|
||||
display="flex"
|
||||
overflow="hidden"
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ item.l1_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>Output root</ListItemMobileGrid.Label>
|
||||
|
||||
@@ -3,17 +3,12 @@ import React from 'react';
|
||||
|
||||
import type { L2OutputRootsItem } from 'types/api/l2OutputRoots';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import txBatchIcon from 'icons/txBatch.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
@@ -35,34 +30,21 @@ const OutputRootsTableItem = ({ item, isLoading }: Props) => {
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block"><span>{ timeAgo }</span></Skeleton>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<LinkInternal
|
||||
fontWeight={ 600 }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
|
||||
<BlockEntityL2
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txBatchIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block" ml={ 1 }>
|
||||
{ item.l2_block_number }
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
number={ item.l2_block_number }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle" pr={ 12 }>
|
||||
<Flex>
|
||||
<LinkExternal
|
||||
maxW="100%"
|
||||
display="inline-flex"
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 } >
|
||||
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
</Flex>
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l1_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<Flex overflow="hidden" whiteSpace="nowrap" w="100%" alignItems="center">
|
||||
|
||||
@@ -6,12 +6,10 @@ import type { L2TxnBatchesItem } from 'types/api/l2TxnBatches';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import txBatchIcon from 'icons/txBatch.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
|
||||
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
|
||||
|
||||
@@ -31,19 +29,13 @@ const TxnBatchesListItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block #</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkInternal
|
||||
fontWeight={ 600 }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
|
||||
<BlockEntityL2
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txBatchIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } ml={ 1 }>
|
||||
{ item.l2_block_number }
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
number={ item.l2_block_number }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block txn count</ListItemMobileGrid.Label>
|
||||
@@ -60,34 +52,28 @@ const TxnBatchesListItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>Epoch number</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<LinkExternal
|
||||
fontWeight={ 600 }
|
||||
display="inline-flex"
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.epoch_number.toString() } }) }
|
||||
<BlockEntityL1
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Skeleton isLoaded={ !isLoading }>
|
||||
{ item.epoch_number }
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
number={ item.epoch_number }
|
||||
noIcon
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<VStack spacing={ 3 } w="100%" overflow="hidden" alignItems="flex-start">
|
||||
{ item.l1_tx_hashes.map(hash => (
|
||||
<LinkExternal
|
||||
maxW="100%"
|
||||
display="inline-flex"
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }
|
||||
<TxEntityL1
|
||||
key={ hash }
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
maxW="100%"
|
||||
/>
|
||||
)) }
|
||||
</VStack>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
@@ -6,12 +6,10 @@ import type { L2TxnBatchesItem } from 'types/api/l2TxnBatches';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import txBatchIcon from 'icons/txBatch.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
|
||||
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
@@ -28,19 +26,13 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
|
||||
return (
|
||||
<Tr>
|
||||
<Td>
|
||||
<LinkInternal
|
||||
fontWeight={ 600 }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
|
||||
<BlockEntityL2
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txBatchIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } ml={ 1 }>
|
||||
{ item.l2_block_number }
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
number={ item.l2_block_number }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<LinkInternal
|
||||
@@ -53,33 +45,27 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
|
||||
</LinkInternal>
|
||||
</Td>
|
||||
<Td>
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.epoch_number.toString() } }) }
|
||||
fontWeight={ 600 }
|
||||
display="inline-flex"
|
||||
<BlockEntityL1
|
||||
isLoading={ isLoading }
|
||||
number={ item.epoch_number }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
py="2px"
|
||||
>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">
|
||||
{ item.epoch_number }
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
noIcon
|
||||
/>
|
||||
</Td>
|
||||
<Td pr={ 12 }>
|
||||
<VStack spacing={ 3 } alignItems="flex-start">
|
||||
{ item.l1_tx_hashes.map(hash => (
|
||||
<LinkExternal
|
||||
maxW="100%"
|
||||
display="inline-flex"
|
||||
<TxEntityL1
|
||||
key={ hash }
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
maxW="100%"
|
||||
/>
|
||||
)) }
|
||||
</VStack>
|
||||
</Td>
|
||||
|
||||
@@ -3,18 +3,14 @@ import React from 'react';
|
||||
|
||||
import type { L2WithdrawalsItem } from 'types/api/l2Withdrawals';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
@@ -53,19 +49,12 @@ const WithdrawalsListItem = ({ item, isLoading }: Props) => {
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
overflow="hidden"
|
||||
w="100%"
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l2_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l2_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
{ timeAgo && (
|
||||
@@ -90,18 +79,12 @@ const WithdrawalsListItem = ({ item, isLoading }: Props) => {
|
||||
<>
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value py="3px">
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
maxW="100%"
|
||||
display="inline-flex"
|
||||
overflow="hidden"
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ item.l1_tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
</>
|
||||
) }
|
||||
|
||||
@@ -3,18 +3,14 @@ import React from 'react';
|
||||
|
||||
import type { L2WithdrawalsItem } from 'types/api/l2Withdrawals';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import HashStringShorten from 'ui/shared/HashStringShorten';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
@@ -42,18 +38,13 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
|
||||
) : 'N/A' }
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<LinkInternal
|
||||
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
|
||||
display="flex"
|
||||
width="fit-content"
|
||||
alignItems="center"
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
|
||||
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
|
||||
<HashStringShorten hash={ item.l2_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
hash={ item.l2_tx_hash }
|
||||
truncation="constant"
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle" pr={ 12 }>
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block">
|
||||
@@ -68,15 +59,13 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
{ item.l1_tx_hash ? (
|
||||
<LinkExternal
|
||||
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
display="inline-flex"
|
||||
>
|
||||
<Skeleton isLoaded={ !isLoading }>
|
||||
<HashStringShorten hash={ item.l1_tx_hash }/>
|
||||
</Skeleton>
|
||||
</LinkExternal>
|
||||
hash={ item.l1_tx_hash }
|
||||
truncation="constant"
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
) :
|
||||
'N/A'
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function useMarketplaceApps(filter: string, selectedCategoryId: s
|
||||
async() => apiFetch(configUrl),
|
||||
{
|
||||
select: (data) => (data as Array<MarketplaceAppOverview>).sort((a, b) => a.title.localeCompare(b.title)),
|
||||
placeholderData: Array(9).fill(MARKETPLACE_APP),
|
||||
placeholderData: feature.isEnabled ? Array(9).fill(MARKETPLACE_APP) : undefined,
|
||||
staleTime: Infinity,
|
||||
enabled: feature.isEnabled,
|
||||
});
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 241 KiB |
|
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 54 KiB |
@@ -4,9 +4,9 @@ import React, { useCallback } from 'react';
|
||||
import type { TransactionTag } from 'types/api/account';
|
||||
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
|
||||
import TransactionSnippet from 'ui/shared/TransactionSnippet';
|
||||
|
||||
interface Props {
|
||||
item: TransactionTag;
|
||||
@@ -27,7 +27,13 @@ const TransactionTagListItem = ({ item, isLoading, onEditClick, onDeleteClick }:
|
||||
return (
|
||||
<ListItemMobile>
|
||||
<Flex alignItems="flex-start" flexDirection="column" maxW="100%">
|
||||
<TransactionSnippet hash={ item.transaction_hash } isLoading={ isLoading }/>
|
||||
<TxEntity
|
||||
hash={ item.transaction_hash }
|
||||
isLoading={ isLoading }
|
||||
withCopy
|
||||
fontWeight={ 600 }
|
||||
maxW="100%"
|
||||
/>
|
||||
<HStack spacing={ 3 } mt={ 4 }>
|
||||
<Text fontSize="sm" fontWeight={ 500 }>Private tag</Text>
|
||||
<Tag isLoading={ isLoading } isTruncated>{ item.name }</Tag>
|
||||
|
||||
@@ -7,8 +7,8 @@ import React, { useCallback } from 'react';
|
||||
import type { TransactionTag } from 'types/api/account';
|
||||
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
|
||||
import TransactionSnippet from 'ui/shared/TransactionSnippet';
|
||||
|
||||
interface Props {
|
||||
item: TransactionTag;
|
||||
@@ -29,7 +29,12 @@ const TransactionTagTableItem = ({ item, isLoading, onEditClick, onDeleteClick }
|
||||
return (
|
||||
<Tr alignItems="top" key={ item.id }>
|
||||
<Td>
|
||||
<TransactionSnippet hash={ item.transaction_hash } isLoading={ isLoading }/>
|
||||
<TxEntity
|
||||
hash={ item.transaction_hash }
|
||||
isLoading={ isLoading }
|
||||
fontWeight={ 600 }
|
||||
withCopy
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<Tag isLoading={ isLoading } isTruncated>{ item.name }</Tag>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { Flex, Grid, Icon, Image, Box, Text, chakra, Skeleton, useColorMode } from '@chakra-ui/react';
|
||||
import { Flex, Grid, Icon, Image, Box, Text, Skeleton, useColorMode } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { SearchResultItem } from 'types/api/search';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import labelIcon from 'icons/publictags.svg';
|
||||
import iconSuccess from 'icons/status/success.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import highlightText from 'lib/highlightText';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
@@ -16,6 +14,8 @@ import { saveToRecentKeywords } from 'lib/recentSearchKeywords';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
@@ -143,28 +143,42 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
case 'block': {
|
||||
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
|
||||
return (
|
||||
<Flex alignItems="center">
|
||||
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<LinkInternal
|
||||
fontWeight={ 700 }
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block_hash) } }) }
|
||||
<BlockEntity.Container>
|
||||
<BlockEntity.Icon/>
|
||||
<BlockEntity.Link
|
||||
hash={ data.block_hash }
|
||||
number={ Number(data.block_number) }
|
||||
onClick={ handleLinkClick }
|
||||
mr={ 4 }
|
||||
>
|
||||
<Box as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
|
||||
</LinkInternal>
|
||||
</Flex>
|
||||
<BlockEntity.Content
|
||||
asProp={ shouldHighlightHash ? 'span' : 'mark' }
|
||||
number={ Number(data.block_number) }
|
||||
fontSize="sm"
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</BlockEntity.Link>
|
||||
</BlockEntity.Container>
|
||||
);
|
||||
}
|
||||
|
||||
case 'transaction': {
|
||||
return (
|
||||
<Flex alignItems="center" overflow="hidden">
|
||||
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<chakra.mark display="block" overflow="hidden">
|
||||
<AddressLink hash={ data.tx_hash } type="transaction" fontWeight={ 700 } display="block" onClick={ handleLinkClick }/>
|
||||
</chakra.mark>
|
||||
</Flex>
|
||||
<TxEntity.Container>
|
||||
<TxEntity.Icon/>
|
||||
<TxEntity.Link
|
||||
isLoading={ isLoading }
|
||||
hash={ data.tx_hash }
|
||||
onClick={ handleLinkClick }
|
||||
>
|
||||
<TxEntity.Content
|
||||
asProp="mark"
|
||||
hash={ data.tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</TxEntity.Link>
|
||||
</TxEntity.Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { chakra, Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode } from '@chakra-ui/react';
|
||||
import { Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { SearchResultItem } from 'types/api/search';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import blockIcon from 'icons/block.svg';
|
||||
import labelIcon from 'icons/publictags.svg';
|
||||
import iconSuccess from 'icons/status/success.svg';
|
||||
import txIcon from 'icons/transactions.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import highlightText from 'lib/highlightText';
|
||||
import * as mixpanel from 'lib/mixpanel/index';
|
||||
@@ -16,6 +14,8 @@ import { saveToRecentKeywords } from 'lib/recentSearchKeywords';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import LinkExternal from 'ui/shared/LinkExternal';
|
||||
import LinkInternal from 'ui/shared/LinkInternal';
|
||||
@@ -220,16 +220,22 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<Td fontSize="sm">
|
||||
<Flex alignItems="center">
|
||||
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<LinkInternal
|
||||
fontWeight={ 700 }
|
||||
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block_hash) } }) }
|
||||
<BlockEntity.Container>
|
||||
<BlockEntity.Icon/>
|
||||
<BlockEntity.Link
|
||||
hash={ data.block_hash }
|
||||
number={ Number(data.block_number) }
|
||||
onClick={ handleLinkClick }
|
||||
>
|
||||
<Box as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
|
||||
</LinkInternal>
|
||||
</Flex>
|
||||
<BlockEntity.Content
|
||||
asProp={ shouldHighlightHash ? 'span' : 'mark' }
|
||||
number={ Number(data.block_number) }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</BlockEntity.Link>
|
||||
</BlockEntity.Container>
|
||||
</Td>
|
||||
<Td fontSize="sm" verticalAlign="middle">
|
||||
<Box overflow="hidden" whiteSpace="nowrap" as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
|
||||
@@ -247,12 +253,22 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<Td colSpan={ 2 } fontSize="sm">
|
||||
<Flex alignItems="center">
|
||||
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
|
||||
<chakra.mark overflow="hidden">
|
||||
<AddressLink display="block" hash={ data.tx_hash } type="transaction" fontWeight={ 700 } onClick={ handleLinkClick } truncation="dynamic"/>
|
||||
</chakra.mark>
|
||||
</Flex>
|
||||
<TxEntity.Container>
|
||||
<TxEntity.Icon/>
|
||||
<TxEntity.Link
|
||||
isLoading={ isLoading }
|
||||
hash={ data.tx_hash }
|
||||
onClick={ handleLinkClick }
|
||||
>
|
||||
<TxEntity.Content
|
||||
asProp="mark"
|
||||
hash={ data.tx_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 700 }
|
||||
/>
|
||||
</TxEntity.Link>
|
||||
</TxEntity.Container>
|
||||
</Td>
|
||||
<Td fontSize="sm" verticalAlign="middle" isNumeric>
|
||||
<Text variant="secondary">{ dayjs(data.timestamp).format('llll') }</Text>
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
|
||||
|
||||
import CopyIcon from 'icons/copy.svg';
|
||||
|
||||
interface Props {
|
||||
export interface Props {
|
||||
text: string;
|
||||
className?: string;
|
||||
isLoading?: boolean;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Tooltip } from '@chakra-ui/react';
|
||||
import { Tooltip, chakra } from '@chakra-ui/react';
|
||||
import type { As } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import shortenString from 'lib/shortenString';
|
||||
@@ -6,16 +7,17 @@ import shortenString from 'lib/shortenString';
|
||||
interface Props {
|
||||
hash: string;
|
||||
isTooltipDisabled?: boolean;
|
||||
as?: As;
|
||||
}
|
||||
|
||||
const HashStringShorten = ({ hash, isTooltipDisabled }: Props) => {
|
||||
const HashStringShorten = ({ hash, isTooltipDisabled, as = 'span' }: Props) => {
|
||||
if (hash.length <= 8) {
|
||||
return <span>{ hash }</span>;
|
||||
return <chakra.span as={ as }>{ hash }</chakra.span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip label={ hash } isDisabled={ isTooltipDisabled }>
|
||||
{ shortenString(hash) }
|
||||
<chakra.span as={ as }>{ shortenString(hash) }</chakra.span>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
// so i did it with js
|
||||
|
||||
import { Tooltip } from '@chakra-ui/react';
|
||||
import type { As } from '@chakra-ui/react';
|
||||
import { Tooltip, chakra } from '@chakra-ui/react';
|
||||
import _debounce from 'lodash/debounce';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import type { FontFace } from 'use-font-face-observer';
|
||||
@@ -24,9 +25,10 @@ interface Props {
|
||||
fontWeight?: string | number;
|
||||
isTooltipDisabled?: boolean;
|
||||
tailLength?: number;
|
||||
as?: As;
|
||||
}
|
||||
|
||||
const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled, tailLength = TAIL_LENGTH }: Props) => {
|
||||
const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled, tailLength = TAIL_LENGTH, as = 'span' }: Props) => {
|
||||
const elementRef = useRef<HTMLSpanElement>(null);
|
||||
const [ displayedString, setDisplayedString ] = React.useState(hash);
|
||||
|
||||
@@ -88,7 +90,7 @@ const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled,
|
||||
};
|
||||
}, [ calculateString ]);
|
||||
|
||||
const content = <span ref={ elementRef }>{ displayedString }</span>;
|
||||
const content = <chakra.span ref={ elementRef } as={ as }>{ displayedString }</chakra.span>;
|
||||
const isTruncated = hash.length !== displayedString.length;
|
||||
|
||||
if (isTruncated) {
|
||||
|
||||
@@ -5,7 +5,6 @@ import React from 'react';
|
||||
import type { TokenTransfer } from 'types/api/tokenTransfer';
|
||||
|
||||
import eastArrowIcon from 'icons/arrows/east.svg';
|
||||
import transactionIcon from 'icons/transactions.svg';
|
||||
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
@@ -13,6 +12,7 @@ import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import InOutTag from 'ui/shared/InOutTag';
|
||||
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
|
||||
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
|
||||
@@ -66,23 +66,12 @@ const TokenTransferListItem = ({
|
||||
{ 'token_id' in total && <TokenTransferNft hash={ token.address } id={ total.token_id } isLoading={ isLoading }/> }
|
||||
{ showTxInfo && txHash && (
|
||||
<Flex justifyContent="space-between" alignItems="center" lineHeight="24px" width="100%">
|
||||
<Flex>
|
||||
<Icon
|
||||
as={ transactionIcon }
|
||||
boxSize="30px"
|
||||
color="link"
|
||||
isLoading={ isLoading }
|
||||
/>
|
||||
<Address width="100%" ml={ 2 }>
|
||||
<AddressLink
|
||||
hash={ txHash }
|
||||
type="transaction"
|
||||
fontWeight="700"
|
||||
truncation="constant"
|
||||
isLoading={ isLoading }
|
||||
/>
|
||||
</Address>
|
||||
</Flex>
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ txHash }
|
||||
truncation="constant"
|
||||
fontWeight="700"
|
||||
/>
|
||||
{ timestamp && (
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
|
||||
<span>{ timeAgo }</span>
|
||||
|
||||
@@ -10,6 +10,7 @@ import AddressIcon from 'ui/shared/address/AddressIcon';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Tag from 'ui/shared/chakra/Tag';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import InOutTag from 'ui/shared/InOutTag';
|
||||
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
|
||||
import { getTokenTransferTypeText } from 'ui/shared/TokenTransfer/helpers';
|
||||
@@ -59,9 +60,13 @@ const TokenTransferTableItem = ({
|
||||
</Td>
|
||||
{ showTxInfo && txHash && (
|
||||
<Td>
|
||||
<Address display="inline-flex" maxW="100%" fontWeight={ 600 } mt="7px">
|
||||
<AddressLink type="transaction" hash={ txHash } isLoading={ isLoading }/>
|
||||
</Address>
|
||||
<TxEntity
|
||||
hash={ txHash }
|
||||
isLoading={ isLoading }
|
||||
fontWeight={ 600 }
|
||||
noIcon
|
||||
mt="7px"
|
||||
/>
|
||||
{ timestamp && (
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" mt="10px" display="inline-block">
|
||||
<span>{ timeAgo }</span>
|
||||
|
||||
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
@@ -1,25 +0,0 @@
|
||||
import { useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import transactionIcon from 'icons/transactions.svg';
|
||||
import Address from 'ui/shared/address/Address';
|
||||
import AddressLink from 'ui/shared/address/AddressLink';
|
||||
import Icon from 'ui/shared/chakra/Icon';
|
||||
import CopyToClipboard from 'ui/shared/CopyToClipboard';
|
||||
|
||||
interface Props {
|
||||
hash: string;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const TransactionSnippet = ({ hash, isLoading }: Props) => {
|
||||
return (
|
||||
<Address maxW="100%">
|
||||
<Icon as={ transactionIcon } boxSize={ 6 } color={ useColorModeValue('gray.500', 'gray.400') } isLoading={ isLoading }/>
|
||||
<AddressLink hash={ hash } fontWeight="600" type="transaction" ml={ 2 } isLoading={ isLoading }/>
|
||||
<CopyToClipboard text={ hash } isLoading={ isLoading }/>
|
||||
</Address>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(TransactionSnippet);
|
||||
@@ -6,6 +6,9 @@ interface Props {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `ui/shared/entities/address` instead
|
||||
*/
|
||||
const Address = ({ children, className }: Props) => {
|
||||
return <Flex alignItems="center" overflow="hidden" className={ className }>{ children }</Flex>;
|
||||
};
|
||||
|
||||
@@ -24,35 +24,25 @@ type CommonProps = {
|
||||
}
|
||||
|
||||
type AddressTokenTxProps = {
|
||||
type: 'address' | 'token' | 'transaction';
|
||||
type: 'address' | 'token';
|
||||
hash: 'hash';
|
||||
}
|
||||
|
||||
type BlockProps = {
|
||||
type: 'block';
|
||||
hash: string;
|
||||
blockHeight: string;
|
||||
}
|
||||
|
||||
type AddressTokenProps = {
|
||||
type: 'address_token';
|
||||
hash: string;
|
||||
tokenHash: string;
|
||||
}
|
||||
|
||||
type Props = CommonProps & (AddressTokenTxProps | BlockProps | AddressTokenProps);
|
||||
type Props = CommonProps & (AddressTokenTxProps | AddressTokenProps);
|
||||
|
||||
const AddressLink = (props: Props) => {
|
||||
const { alias, type, className, truncation = 'dynamic', hash, fontWeight, target = '_self', isDisabled, isLoading } = props;
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
let url;
|
||||
if (type === 'transaction') {
|
||||
url = route({ pathname: '/tx/[hash]', query: { ...props.query, hash } });
|
||||
} else if (type === 'token') {
|
||||
if (type === 'token') {
|
||||
url = route({ pathname: '/token/[hash]', query: { ...props.query, hash } });
|
||||
} else if (type === 'block') {
|
||||
url = route({ pathname: '/block/[height_or_hash]', query: { ...props.query, height_or_hash: props.blockHeight } });
|
||||
} else if (type === 'address_token') {
|
||||
url = route({ pathname: '/address/[hash]', query: { ...props.query, hash, tab: 'token_transfers', token: props.tokenHash, scroll_to_tabs: 'true' } });
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import { test, expect } from '@playwright/experimental-ct-react';
|
||||
import React from 'react';
|
||||
|
||||
import * as addressMock from 'mocks/address/address';
|
||||
import TestApp from 'playwright/TestApp';
|
||||
|
||||
import AddressEntity from './AddressEntity';
|
||||
|
||||
const iconSizes = [ 'md', 'lg' ];
|
||||
|
||||
test.use({ viewport: { width: 180, height: 100 } });
|
||||
|
||||
test.describe('icon size', () => {
|
||||
iconSizes.forEach((size) => {
|
||||
test(size, async({ mount }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={ addressMock.withoutName }
|
||||
iconSize={ size }
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('contract', () => {
|
||||
test('unverified', async({ mount, page }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={{ ...addressMock.contract, is_verified: false }}
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await component.getByText(/eternal/i).hover();
|
||||
await expect(page).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('verified', async({ mount }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={{ ...addressMock.contract, is_verified: true }}
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('loading', () => {
|
||||
test('without alias', async({ mount }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={ addressMock.withoutName }
|
||||
isLoading
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('with alias', async({ mount }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={ addressMock.withName }
|
||||
isLoading
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
});
|
||||
|
||||
test('external link', async({ mount }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={ addressMock.withoutName }
|
||||
isExternal
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
|
||||
test('customization', async({ mount }) => {
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<AddressEntity
|
||||
address={ addressMock.withoutName }
|
||||
truncation="constant"
|
||||
p={ 3 }
|
||||
borderWidth="1px"
|
||||
borderColor="blue.700"
|
||||
/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
import type { As } from '@chakra-ui/react';
|
||||
import { Flex, Skeleton, Tooltip, chakra } from '@chakra-ui/react';
|
||||
import _omit from 'lodash/omit';
|
||||
import React from 'react';
|
||||
import Jazzicon, { jsNumberForAddress } from 'react-jazzicon';
|
||||
|
||||
import type { AddressParam } from 'types/api/addressParams';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import iconContractVerified from 'icons/contract_verified.svg';
|
||||
import iconContract from 'icons/contract.svg';
|
||||
import * as EntityBase from 'ui/shared/entities/base/components';
|
||||
|
||||
import { getIconProps } from '../base/utils';
|
||||
|
||||
interface LinkProps extends Pick<EntityProps, 'className' | 'address' | 'onClick' | 'isLoading' | 'isExternal' | 'href' | 'query'> {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const Link = chakra((props: LinkProps) => {
|
||||
const defaultHref = route({ pathname: '/address/[hash]', query: { ...props.query, hash: props.address.hash } });
|
||||
|
||||
return (
|
||||
<EntityBase.Link
|
||||
{ ...props }
|
||||
href={ props.href ?? defaultHref }
|
||||
>
|
||||
{ props.children }
|
||||
</EntityBase.Link>
|
||||
);
|
||||
});
|
||||
|
||||
type IconProps = Pick<EntityProps, 'address' | 'isLoading' | 'iconSize'> & {
|
||||
asProp?: As;
|
||||
};
|
||||
|
||||
const Icon = (props: IconProps) => {
|
||||
const styles = {
|
||||
...getIconProps(props.iconSize),
|
||||
marginRight: 2,
|
||||
};
|
||||
|
||||
if (props.isLoading) {
|
||||
return <Skeleton { ...styles } borderRadius="full" flexShrink={ 0 }/>;
|
||||
}
|
||||
|
||||
if (props.address.is_contract) {
|
||||
if (props.address.is_verified) {
|
||||
return (
|
||||
<EntityBase.Icon
|
||||
{ ...props }
|
||||
asProp={ iconContractVerified }
|
||||
color="green.500"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EntityBase.Icon
|
||||
{ ...props }
|
||||
asProp={ iconContract }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip label={ props.address.implementation_name }>
|
||||
<Flex { ...styles }>
|
||||
<Jazzicon diameter={ props.iconSize === 'lg' ? 30 : 20 } seed={ jsNumberForAddress(props.address.hash) }/>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
type ContentProps = Omit<EntityBase.ContentBaseProps, 'text'> & Pick<EntityProps, 'address'>;
|
||||
|
||||
const Content = chakra((props: ContentProps) => {
|
||||
if (props.address.name) {
|
||||
return (
|
||||
<Tooltip label={ props.address.hash } maxW="100vw">
|
||||
<Skeleton isLoaded={ !props.isLoading } overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap" as="span">
|
||||
{ props.address.name }
|
||||
</Skeleton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EntityBase.Content
|
||||
{ ...props }
|
||||
text={ props.address.hash }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
type CopyProps = Omit<EntityBase.CopyBaseProps, 'text'> & Pick<EntityProps, 'address'>;
|
||||
|
||||
const Copy = (props: CopyProps) => {
|
||||
return (
|
||||
<EntityBase.Copy
|
||||
{ ...props }
|
||||
text={ props.address.hash }
|
||||
withCopy={ props.withCopy ?? true }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const Container = EntityBase.Container;
|
||||
|
||||
export interface EntityProps extends EntityBase.EntityBaseProps {
|
||||
address: Pick<AddressParam, 'hash' | 'name' | 'is_contract' | 'is_verified' | 'implementation_name'>;
|
||||
}
|
||||
|
||||
const AddressEntry = (props: EntityProps) => {
|
||||
const linkProps = _omit(props, [ 'className' ]);
|
||||
const partsProps = _omit(props, [ 'className', 'onClick' ]);
|
||||
|
||||
return (
|
||||
<Container className={ props.className }>
|
||||
<Icon { ...partsProps }/>
|
||||
<Link { ...linkProps }>
|
||||
<Content { ...partsProps }/>
|
||||
</Link>
|
||||
<Copy { ...partsProps }/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(chakra(AddressEntry));
|
||||
|
||||
export {
|
||||
Container,
|
||||
Link,
|
||||
Icon,
|
||||
Content,
|
||||
Copy,
|
||||
};
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |