Commit 077a79e6 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Merge pull request #1125 from blockscout/address-entity

refactor icons for addresses and tokens
parents 1bd65cf3 835c9a54
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M12.91 3H5.272C4.57 3 4 3.57 4 4.273v8.909h1.273v-8.91h7.636V3Zm1.908 2.545h-7c-.703 0-1.273.57-1.273 1.273v8.91c0 .702.57 1.272 1.273 1.272h7c.703 0 1.273-.57 1.273-1.273V6.818c0-.703-.57-1.273-1.273-1.273Zm0 10.182h-7V6.818h7v8.91Z"/>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#copy_svg__a)">
<path d="M8.597 3H1.228C.55 3 0 3.57 0 4.273v8.909h1.228v-8.91h7.369V3Zm1.842 2.545H3.684c-.678 0-1.228.57-1.228 1.273v8.91c0 .702.55 1.272 1.228 1.272h6.755c.678 0 1.228-.57 1.228-1.273V6.818c0-.703-.55-1.273-1.228-1.273Zm0 10.182H3.684V6.818h6.755v8.91Z" fill="currentColor" stroke="currentColor" stroke-width=".3"/>
</g>
<defs>
<clipPath id="copy_svg__a">
<path d="M0 0h20v20H0z"/>
</clipPath>
</defs>
</svg>
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
<path d="M13.61 25a2.262 2.262 0 0 1-1.615-.665l-6.318-6.318a2.265 2.265 0 0 1 0-3.23l8.456-8.457c.76-.76 2.138-1.33 3.183-1.33h5.416c1.235 0 2.28 1.045 2.28 2.28v5.416c0 1.045-.57 2.423-1.33 3.183l-8.456 8.456A2.262 2.262 0 0 1 13.61 25Zm3.706-18.575c-.665 0-1.71.428-2.185.903l-8.456 8.456a.832.832 0 0 0 0 1.187l6.318 6.319c.332.332.902.332 1.188 0l8.456-8.456c.475-.475.902-1.473.902-2.185V7.232a.852.852 0 0 0-.855-.855h-5.368v.047Z" stroke="currentColor" stroke-width=".5"/>
<path d="M19.311 13.504a2.808 2.808 0 0 1-2.803-2.803 2.808 2.808 0 0 1 2.803-2.803 2.808 2.808 0 0 1 2.803 2.803 2.808 2.808 0 0 1-2.803 2.803Zm0-4.276a1.48 1.48 0 0 0-1.473 1.473 1.48 1.48 0 0 0 1.473 1.473 1.48 1.48 0 0 0 1.473-1.473 1.48 1.48 0 0 0-1.473-1.473Z" stroke="currentColor" stroke-width=".5"/>
<svg viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.61 25a2.262 2.262 0 0 1-1.615-.665l-6.318-6.318a2.265 2.265 0 0 1 0-3.23l8.456-8.457c.76-.76 2.138-1.33 3.183-1.33h5.416c1.235 0 2.28 1.045 2.28 2.28v5.416c0 1.045-.57 2.423-1.33 3.183l-8.456 8.456A2.262 2.262 0 0 1 13.61 25Zm3.706-18.575c-.665 0-1.71.428-2.185.903l-8.456 8.456a.832.832 0 0 0 0 1.187l6.318 6.319c.332.332.902.332 1.188 0l8.456-8.456c.475-.475.902-1.473.902-2.185V7.232a.852.852 0 0 0-.855-.855h-5.368v.047Z" fill="currentColor" stroke="currentColor" stroke-width=".5"/>
<path d="M19.311 13.504a2.808 2.808 0 0 1-2.803-2.803 2.808 2.808 0 0 1 2.803-2.803 2.808 2.808 0 0 1 2.803 2.803 2.808 2.808 0 0 1-2.803 2.803Zm0-4.276a1.48 1.48 0 0 0-1.473 1.473 1.48 1.48 0 0 0 1.473 1.473 1.48 1.48 0 0 0 1.473-1.473 1.48 1.48 0 0 0-1.473-1.473Z" fill="currentColor" stroke="currentColor" stroke-width=".5"/>
</svg>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.094 19.3c-.58 0-1.116-.223-1.517-.625l-5.936-5.94a2.13 2.13 0 0 1 0-3.036L9.585 1.75c.714-.714 2.008-1.25 2.99-1.25h5.088c1.16 0 2.142.982 2.142 2.143v5.091c0 .983-.536 2.278-1.25 2.992l-7.944 7.949a2.125 2.125 0 0 1-1.517.625Zm3.481-17.46c-.625 0-1.607.402-2.053.848l-7.944 7.949a.782.782 0 0 0 0 1.116l5.936 5.94c.312.312.848.312 1.115 0l7.944-7.95c.447-.446.848-1.384.848-2.053V2.599a.8.8 0 0 0-.803-.804h-5.043v.045Z" fill="currentColor"/>
<path d="M14.45 8.493a2.639 2.639 0 0 1-2.634-2.634 2.639 2.639 0 0 1 2.633-2.635 2.639 2.639 0 0 1 2.634 2.635 2.639 2.639 0 0 1-2.633 2.634Zm0-4.019a1.39 1.39 0 0 0-1.384 1.385 1.39 1.39 0 0 0 1.383 1.384 1.39 1.39 0 0 0 1.384-1.384 1.39 1.39 0 0 0-1.383-1.385Z" fill="currentColor"/>
</svg>
......@@ -5,22 +5,18 @@ import React from 'react';
import type { Address as TAddress } from 'types/api/address';
import { route } from 'nextjs-routes';
import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery';
import getQueryParamString from 'lib/router/getQueryParamString';
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 DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
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';
import AddressBalance from './details/AddressBalance';
import AddressNameInfo from './details/AddressNameInfo';
......@@ -102,9 +98,13 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
hint="Transaction and address of creation"
isLoading={ addressQuery.isPlaceholderData }
>
<AddressLink type="address" hash={ data.creator_address_hash } truncation="constant"/>
<AddressEntity
address={{ hash: data.creator_address_hash }}
truncation="constant"
noIcon
/>
<Text whiteSpace="pre"> at txn </Text>
<TxEntity hash={ data.creation_tx_hash } truncation="constant" noIcon/>
<TxEntity hash={ data.creation_tx_hash } truncation="constant" noIcon noCopy={ false }/>
</DetailsInfoItem>
) }
{ data.is_contract && data.implementation_address && (
......@@ -113,14 +113,11 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
hint="Implementation address of the proxy contract"
columnGap={ 1 }
>
<LinkInternal href={ route({ pathname: '/address/[hash]', query: { hash: data.implementation_address } }) } overflow="hidden">
{ data.implementation_name || <HashStringShortenDynamic hash={ data.implementation_address }/> }
</LinkInternal>
{ data.implementation_name && (
<Text variant="secondary" overflow="hidden">
<HashStringShortenDynamic hash={ `(${ data.implementation_address })` }/>
</Text>
) }
<AddressEntity
address={{ hash: data.implementation_address, name: data.implementation_name, is_contract: true }}
isLoading={ addressQuery.isPlaceholderData }
noIcon
/>
</DetailsInfoItem>
) }
<AddressBalance data={ data } isLoading={ addressQuery.isPlaceholderData }/>
......
......@@ -22,11 +22,11 @@ import TOKEN_TYPE from 'lib/token/tokenTypes';
import { getTokenTransfersStub } from 'stubs/token';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import HashStringShorten from 'ui/shared/HashStringShorten';
import Pagination from 'ui/shared/pagination/Pagination';
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import TokenLogo from 'ui/shared/TokenLogo';
import TokenTransferFilter from 'ui/shared/TokenTransfer/TokenTransferFilter';
import TokenTransferList from 'ui/shared/TokenTransfer/TokenTransferList';
import TokenTransferTable from 'ui/shared/TokenTransfer/TokenTransferTable';
......@@ -227,19 +227,20 @@ const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Pr
address: tokenFilter || '',
name: '',
icon_url: '',
symbol: '',
}), [ tokenFilter ]);
const tokenFilterComponent = tokenFilter && (
<Flex alignItems="center" flexWrap="wrap" mb={{ base: isActionBarHidden ? 3 : 6, lg: 0 }} mr={ 4 }>
<Text whiteSpace="nowrap" mr={ 2 } py={ 1 }>Filtered by token</Text>
<Flex alignItems="center" py={ 1 }>
<TokenLogo data={ tokenData } boxSize={ 6 } mr={ 2 }/>
<TokenEntity.Icon token={ tokenData } isLoading={ isPlaceholderData }/>
{ isMobile ? <HashStringShorten hash={ tokenFilter }/> : tokenFilter }
<Tooltip label="Reset filter">
<Flex>
<Icon
as={ crossIcon }
boxSize={ 6 }
boxSize={ 5 }
ml={ 1 }
color={ resetTokenIconColor }
cursor="pointer"
......
......@@ -47,6 +47,7 @@ base.describe('base view', () => {
base.use({ viewport: configs.viewport.xl });
base('', async() => {
base.slow();
await expect(component).toHaveScreenshot();
});
});
......
......@@ -12,10 +12,8 @@ import dayjs from 'lib/date/dayjs';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import * as stubs from 'stubs/contract';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import RawDataSnippet from 'ui/shared/RawDataSnippet';
......@@ -107,9 +105,14 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
const decoded = data.decoded_constructor_args
.map(([ value, { name, type } ], index) => {
const valueEl = type === 'address' ?
<LinkInternal href={ route({ pathname: '/address/[hash]', query: { hash: value } }) }>{ value }</LinkInternal> :
<span>{ value }</span>;
const valueEl = type === 'address' ? (
<AddressEntity
address={{ hash: value }}
noIcon
display="inline-flex"
maxW="100%"
/>
) : <span>{ value }</span>;
return (
<Box key={ index }>
<span>Arg [{ index }] { name || '' } ({ type }): </span>
......@@ -171,10 +174,12 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
{ !data?.is_verified && data?.verified_twin_address_hash && !data?.minimal_proxy_address_hash && (
<Alert status="warning" whiteSpace="pre-wrap" flexWrap="wrap">
<span>Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB </span>
<Address>
<AddressIcon address={{ hash: data.verified_twin_address_hash, is_contract: true, implementation_name: null }}/>
<AddressLink type="address" hash={ data.verified_twin_address_hash } truncation="constant" ml={ 2 }/>
</Address>
<AddressEntity
address={{ hash: data.verified_twin_address_hash, is_contract: true, implementation_name: null }}
truncation="constant"
fontSize="sm"
fontWeight="500"
/>
<chakra.span mt={ 1 }>All functions displayed below are from ABI of that contract. In order to verify current contract, proceed with </chakra.span>
<LinkInternal href={ route({ pathname: '/address/[hash]/contract-verification', query: { hash: addressHash || '' } }) }>
Verify & Publish
......@@ -185,10 +190,13 @@ const ContractCode = ({ addressHash, noSocket }: Props) => {
{ data?.minimal_proxy_address_hash && (
<Alert status="warning" flexWrap="wrap" whiteSpace="pre-wrap">
<span>Minimal Proxy Contract for </span>
<Address>
<AddressIcon address={{ hash: data.minimal_proxy_address_hash, is_contract: true, implementation_name: null }}/>
<AddressLink type="address" hash={ data.minimal_proxy_address_hash } truncation="constant" ml={ 2 }/>
</Address>
<AddressEntity
address={{ hash: data.minimal_proxy_address_hash, is_contract: true, implementation_name: null }}
truncation="constant"
fontSize="sm"
fontWeight="500"
noCopy
/>
<span>. </span>
<Box>
<Link href="https://eips.ethereum.org/EIPS/eip-1167">EIP-1167</Link>
......
......@@ -4,8 +4,7 @@ import React from 'react';
import { useAccount, useDisconnect } from 'wagmi';
import useIsMobile from 'lib/hooks/useIsMobile';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
const ContractConnectWallet = () => {
const { open, isOpen } = useWeb3Modal();
......@@ -47,8 +46,12 @@ const ContractConnectWallet = () => {
<Flex columnGap={ 3 } rowGap={ 3 } alignItems={{ base: 'flex-start', lg: 'center' }} flexDir={{ base: 'column', lg: 'row' }}>
<Flex alignItems="center">
<span>Connected to </span>
<AddressIcon address={{ hash: address, is_contract: false, implementation_name: null }} mx={ 2 }/>
<AddressLink type="address" fontWeight={ 600 } hash={ address } truncation={ isMobile ? 'constant' : 'dynamic' }/>
<AddressEntity
address={{ hash: address }}
truncation={ isMobile ? 'constant' : 'dynamic' }
fontWeight={ 600 }
ml={ 2 }
/>
</Flex>
<Button onClick={ handleDisconnect } size="sm" variant="outline">Disconnect</Button>
</Flex>
......
......@@ -24,10 +24,7 @@ import arrowIcon from 'icons/arrows/east-mini.svg';
import iconWarning from 'icons/status/warning.svg';
import useIsMobile from 'lib/hooks/useIsMobile';
import { apos } from 'lib/html-entities';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
interface Props {
className?: string;
......@@ -38,11 +35,13 @@ const Item = (data: SmartContractExternalLibrary) => {
return (
<Flex flexDir="column" py={ 2 } w="100%" rowGap={ 1 }>
<Box>{ data.name }</Box>
<Address>
<AddressIcon address={{ hash: data.address_hash, is_contract: true, implementation_name: null }}/>
<AddressLink hash={ data.address_hash } type="address" ml={ 2 } fontWeight={ 500 } fontSize="sm" target="_blank" query={{ tab: 'contract' }}/>
<CopyToClipboard text={ data.address_hash }/>
</Address>
<AddressEntity
address={{ hash: data.address_hash, is_contract: true, implementation_name: null }}
query={{ tab: 'contract' }}
fontSize="sm"
fontWeight="500"
target="_blank"
/>
</Flex>
);
};
......
import { Flex } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import React from 'react';
import type { Address as TAddress } from 'types/api/address';
import { getResourceKey } from 'lib/api/useApiQuery';
import Address from 'ui/shared/address/Address';
import AddressLink from 'ui/shared/address/AddressLink';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
interface Props {
hash: string | undefined;
......@@ -22,10 +22,10 @@ const ContractImplementationAddress = ({ hash }: Props) => {
}
return (
<Address whiteSpace="pre-wrap" flexWrap="wrap" mb={ 6 }>
<span>Implementation address: </span>
<AddressLink type="address" hash={ data.implementation_address }/>
</Address>
<Flex mb={ 6 } flexWrap="wrap" columnGap={ 2 }>
<span>Implementation address:</span>
<AddressEntity address={{ hash: data.implementation_address, is_contract: true }} noIcon noCopy/>
</Flex>
);
};
......
......@@ -7,9 +7,7 @@ import type { SmartContractMethodOutput } from 'types/api/contract';
import config from 'configs/app';
import { WEI } from 'lib/consts';
import Address from 'ui/shared/address/Address';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
function castValueToString(value: number | string | boolean | bigint | undefined): string {
switch (typeof value) {
......@@ -49,10 +47,10 @@ const ContractMethodStatic = ({ data }: Props) => {
const content = (() => {
if (typeof data.value === 'string' && data.type === 'address' && data.value) {
return (
<Address>
<AddressLink type="address" hash={ data.value }/>
<CopyToClipboard text={ data.value }/>
</Address>
<AddressEntity
address={{ hash: data.value }}
noIcon
/>
);
}
......
......@@ -10,7 +10,6 @@ import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import CurrencyValue from 'ui/shared/CurrencyValue';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import TokenLogo from 'ui/shared/TokenLogo';
interface Props {
data: Pick<Address, 'block_number_balance_updated_at' | 'coin_balance' | 'hash' | 'exchange_rate'>;
......@@ -64,11 +63,6 @@ const AddressBalance = ({ data, isLoading }: Props) => {
handler: handleNewCoinBalanceMessage,
});
const tokenData = React.useMemo(() => ({
name: config.chain.currency.name || '',
icon_url: '',
}), [ ]);
return (
<DetailsInfoItem
title="Balance"
......@@ -77,13 +71,6 @@ const AddressBalance = ({ data, isLoading }: Props) => {
alignItems="flex-start"
isLoading={ isLoading }
>
<TokenLogo
data={ tokenData }
boxSize={ 5 }
mr={ 2 }
fontSize="sm"
isLoading={ isLoading }
/>
<CurrencyValue
value={ data.coin_balance || '0' }
exchangeRate={ data.exchange_rate }
......
......@@ -4,7 +4,7 @@ import React from 'react';
import type { Address } from 'types/api/address';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
interface Props {
data: Pick<Address, 'name' | 'token' | 'is_contract'>;
......@@ -19,7 +19,12 @@ const AddressNameInfo = ({ data, isLoading }: Props) => {
hint="Token name and symbol"
isLoading={ isLoading }
>
<TokenSnippet data={ data.token } isLoading={ isLoading } hideIcon/>
<TokenEntity
token={ data.token }
isLoading={ isLoading }
noIcon
noCopy
/>
</DetailsInfoItem>
);
}
......
......@@ -7,12 +7,9 @@ import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app';
import eastArrowIcon from 'icons/arrows/east.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 Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag';
......@@ -40,7 +37,7 @@ const TxInternalsListItem = ({
const toData = to ? to : createdContract;
const isOut = Boolean(currentAddress && currentAddress === from.hash);
const isIn = Boolean(currentAddress && currentAddress === to?.hash);
const isIn = Boolean(currentAddress && currentAddress === toData?.hash);
return (
<ListItemMobile rowGap={ 3 }>
......@@ -70,21 +67,25 @@ const TxInternalsListItem = ({
/>
</HStack>
<Box w="100%" display="flex" columnGap={ 3 }>
<Address width="calc((100% - 48px) / 2)">
<AddressIcon address={ from } isLoading={ isLoading }/>
<AddressLink type="address" ml={ 2 } fontWeight="500" hash={ from.hash } isDisabled={ isOut } isLoading={ isLoading }/>
{ isIn && <CopyToClipboard text={ from.hash } isLoading={ isLoading }/> }
</Address>
<AddressEntity
address={ from }
isLoading={ isLoading }
noLink={ isOut }
noCopy={ isOut }
width="calc((100% - 48px) / 2)"
/>
{ (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading }/> :
<Icon as={ eastArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
}
{ toData && (
<Address width="calc((100% - 48px) / 2)">
<AddressIcon address={ toData } isLoading={ isLoading }/>
<AddressLink type="address" ml={ 2 } fontWeight="500" hash={ toData.hash } isDisabled={ isIn } isLoading={ isLoading }/>
{ isOut && <CopyToClipboard text={ toData.hash } isLoading={ isLoading }/> }
</Address>
<AddressEntity
address={ toData }
isLoading={ isLoading }
noLink={ isIn }
noCopy={ isIn }
width="calc((100% - 48px) / 2)"
/>
) }
</Box>
<HStack spacing={ 3 }>
......
......@@ -7,12 +7,9 @@ import type { InternalTransaction } from 'types/api/internalTransaction';
import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
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 Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag';
......@@ -39,7 +36,7 @@ const AddressIntTxsTableItem = ({
const toData = to ? to : createdContract;
const isOut = Boolean(currentAddress && currentAddress === from.hash);
const isIn = Boolean(currentAddress && currentAddress === to?.hash);
const isIn = Boolean(currentAddress && currentAddress === toData?.hash);
const timeAgo = useTimeAgoIncrement(timestamp, true);
......@@ -81,34 +78,27 @@ const AddressIntTxsTableItem = ({
/>
</Td>
<Td verticalAlign="middle">
<Address display="inline-flex" maxW="100%">
<AddressIcon address={ from } isLoading={ isLoading }/>
<AddressLink
type="address"
ml={ 2 }
fontWeight="500"
hash={ from.hash }
alias={ from.name }
flexGrow={ 1 }
isDisabled={ isOut }
isLoading={ isLoading }
/>
{ isIn && <CopyToClipboard text={ from.hash } isLoading={ isLoading }/> }
</Address>
<AddressEntity
address={ from }
isLoading={ isLoading }
noLink={ isOut }
noCopy={ isOut }
/>
</Td>
<Td px={ 0 } verticalAlign="middle">
{ (isIn || isOut) ?
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading }/> :
<InOutTag isIn={ isIn } isOut={ isOut } isLoading={ isLoading } w="100%"/> :
<Icon as={ rightArrowIcon } boxSize={ 6 } color="gray.500" isLoading={ isLoading }/>
}
</Td>
<Td verticalAlign="middle">
{ toData && (
<Address display="inline-flex" maxW="100%">
<AddressIcon address={ toData } isLoading={ isLoading }/>
<AddressLink type="address" hash={ toData.hash } alias={ toData.name } fontWeight="500" ml={ 2 } isDisabled={ isIn } isLoading={ isLoading }/>
{ isOut && <CopyToClipboard text={ toData.hash } isLoading={ isLoading }/> }
</Address>
<AddressEntity
address={ toData }
isLoading={ isLoading }
noLink={ isIn }
noCopy={ isIn }
/>
) }
</Td>
<Td isNumeric verticalAlign="middle">
......
......@@ -4,7 +4,7 @@ import React from 'react';
import { route } from 'nextjs-routes';
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import TruncatedValue from 'ui/shared/TruncatedValue';
import type { TokenEnhancedData } from '../utils/tokenUtils';
......@@ -68,7 +68,13 @@ const TokenSelectItem = ({ data }: Props) => {
href={ url }
>
<Flex alignItems="center" w="100%" overflow="hidden">
<TokenSnippet data={ data.token } hideSymbol fontWeight={ 700 } isDisabled/>
<TokenEntity
token={ data.token }
noSymbol
noCopy
noLink
fontWeight={ 700 }
/>
{ data.usd && <Text fontWeight={ 700 } ml="auto">${ data.usd.toFormat(2) }</Text> }
</Flex>
<Flex alignItems="center" justifyContent="space-between" w="100%" whiteSpace="nowrap">
......
......@@ -5,17 +5,14 @@ import type { AddressTokenBalance } from 'types/api/address';
import getCurrencyValue from 'lib/getCurrencyValue';
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TokenLogo from 'ui/shared/TokenLogo';
type Props = AddressTokenBalance & { isLoading: boolean};
const ERC20TokensListItem = ({ token, value, isLoading }: Props) => {
const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' ');
const {
valueStr: tokenQuantity,
usd: tokenValue,
......@@ -24,12 +21,21 @@ const ERC20TokensListItem = ({ token, value, isLoading }: Props) => {
return (
<ListItemMobile rowGap={ 2 }>
<Flex alignItems="center" width="100%">
<TokenLogo data={ token } boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/>
<AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString } isLoading={ isLoading }/>
<TokenEntity
token={ token }
isLoading={ isLoading }
noCopy
jointSymbol
fontWeight="700"
/>
</Flex>
<Flex alignItems="center" pl={ 8 }>
<AddressLink hash={ token.address } type="address" truncation="constant" isLoading={ isLoading }/>
<CopyToClipboard text={ token.address } isLoading={ isLoading }/>
<AddressEntity
address={{ hash: token.address }}
isLoading={ isLoading }
truncation="constant"
noIcon
/>
<AddressAddToWallet token={ token } ml={ 2 } isLoading={ isLoading }/>
</Flex>
{ token.exchange_rate !== undefined && token.exchange_rate !== null && (
......
......@@ -5,9 +5,8 @@ import type { AddressTokenBalance } from 'types/api/address';
import getCurrencyValue from 'lib/getCurrencyValue';
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import TokenLogo from 'ui/shared/TokenLogo';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
type Props = AddressTokenBalance & { isLoading: boolean };
......@@ -17,8 +16,6 @@ const ERC20TokensTableItem = ({
isLoading,
}: Props) => {
const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' ');
const {
valueStr: tokenQuantity,
usd: tokenValue,
......@@ -27,17 +24,21 @@ const ERC20TokensTableItem = ({
return (
<Tr>
<Td verticalAlign="middle">
<Flex alignItems="center">
<TokenLogo data={ token } boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/>
<AddressLink fontWeight="700" hash={ token.address } type="token" alias={ tokenString } isLoading={ isLoading }/>
</Flex>
<TokenEntity
token={ token }
isLoading={ isLoading }
noCopy
jointSymbol
fontWeight="700"
/>
</Td>
<Td verticalAlign="middle">
<Flex alignItems="center" width="150px" justifyContent="space-between">
<Flex alignItems="center">
<AddressLink hash={ token.address } type="address" truncation="constant" isLoading={ isLoading }/>
<CopyToClipboard text={ token.address } isLoading={ isLoading }/>
</Flex>
<AddressEntity
address={{ hash: token.address }}
isLoading={ isLoading }
noIcon
/>
<AddressAddToWallet token={ token } ml={ 4 } isLoading={ isLoading }/>
</Flex>
</Td>
......
......@@ -5,10 +5,9 @@ import React from 'react';
import type { AddressTokenBalance } from 'types/api/address';
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntityWithAddressFilter from 'ui/shared/entities/token/TokenEntityWithAddressFilter';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TokenLogo from 'ui/shared/TokenLogo';
type Props = AddressTokenBalance & { isLoading: boolean};
......@@ -17,17 +16,23 @@ const ERC721TokensListItem = ({ token, value, isLoading }: Props) => {
const hash = router.query.hash?.toString() || '';
const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' ');
return (
<ListItemMobile rowGap={ 2 }>
<Flex alignItems="center" width="100%">
<TokenLogo data={ token } boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/>
<AddressLink fontWeight="700" hash={ hash } tokenHash={ token.address } type="address_token" alias={ tokenString } isLoading={ isLoading }/>
</Flex>
<TokenEntityWithAddressFilter
token={ token }
isLoading={ isLoading }
addressHash={ hash }
noCopy
jointSymbol
fontWeight={ 700 }
/>
<Flex alignItems="center" pl={ 8 }>
<AddressLink hash={ token.address } type="address" truncation="constant" isLoading={ isLoading }/>
<CopyToClipboard text={ token.address } isLoading={ isLoading }/>
<AddressEntity
address={{ hash: token.address }}
isLoading={ isLoading }
truncation="constant"
noIcon
/>
<AddressAddToWallet token={ token } ml={ 2 } isLoading={ isLoading }/>
</Flex>
<HStack spacing={ 3 }>
......
......@@ -5,9 +5,8 @@ import React from 'react';
import type { AddressTokenBalance } from 'types/api/address';
import AddressAddToWallet from 'ui/shared/address/AddressAddToWallet';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import TokenLogo from 'ui/shared/TokenLogo';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntityWithAddressFilter from 'ui/shared/entities/token/TokenEntityWithAddressFilter';
type Props = AddressTokenBalance & { isLoading: boolean};
......@@ -19,22 +18,26 @@ const ERC721TokensTableItem = ({
const router = useRouter();
const hash = router.query.hash?.toString() || '';
const tokenString = [ token.name, token.symbol && `(${ token.symbol })` ].filter(Boolean).join(' ');
return (
<Tr>
<Td verticalAlign="middle">
<Flex alignItems="center">
<TokenLogo data={ token } boxSize={ 6 } mr={ 2 } isLoading={ isLoading }/>
<AddressLink fontWeight="700" hash={ hash } tokenHash={ token.address } type="address_token" alias={ tokenString } isLoading={ isLoading }/>
</Flex>
<TokenEntityWithAddressFilter
token={ token }
addressHash={ hash }
isLoading={ isLoading }
noCopy
jointSymbol
fontWeight="700"
/>
</Td>
<Td verticalAlign="middle">
<Flex alignItems="center" width="150px" justifyContent="space-between">
<Flex alignItems="center">
<AddressLink hash={ token.address } type="address" truncation="dynamic" isLoading={ isLoading }/>
<CopyToClipboard text={ token.address } isLoading={ isLoading }/>
</Flex>
<AddressEntity
address={{ hash: token.address }}
isLoading={ isLoading }
noIcon
/>
<AddressAddToWallet token={ token } ml={ 4 } isLoading={ isLoading }/>
</Flex>
</Td>
......
......@@ -5,10 +5,9 @@ import type { AddressTokenBalance } from 'types/api/address';
import { route } from 'nextjs-routes';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import NftMedia from 'ui/shared/nft/NftMedia';
import TokenLogo from 'ui/shared/TokenLogo';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
import TruncatedValue from 'ui/shared/TruncatedValue';
type Props = AddressTokenBalance & { isLoading: boolean };
......@@ -53,12 +52,12 @@ const NFTItem = ({ token, token_id: tokenId, token_instance: tokenInstance, isLo
</TruncatedTextTooltip>
</Flex>
) }
{ token.name && (
<Flex alignItems="center">
<TokenLogo data={ token } boxSize={ 6 } ml={ 1 } mr={ 1 } isLoading={ isLoading }/>
<TruncatedValue isLoading={ isLoading } value={ token.name } color="text_secondary"/>
</Flex>
) }
<TokenEntity
token={ token }
isLoading={ isLoading }
noCopy
noSymbol
/>
</LinkBox>
);
};
......
......@@ -5,11 +5,8 @@ import React from 'react';
import type { AddressesItem } from 'types/api/addresses';
import config from 'configs/app';
import Address from 'ui/shared/address/Address';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
type Props = {
......@@ -31,19 +28,12 @@ const AddressesListItem = ({
return (
<ListItemMobile rowGap={ 3 }>
<Flex alignItems="center" justifyContent="space-between" w="100%">
<Address maxW="100%" mr={ 8 }>
<AddressIcon address={ item } mr={ 2 } isLoading={ isLoading }/>
<AddressLink
fontWeight={ 700 }
flexGrow={ 1 }
w="calc(100% - 32px)"
hash={ item.hash }
alias={ item.name }
type="address"
isLoading={ isLoading }
/>
<CopyToClipboard text={ item.hash } isLoading={ isLoading }/>
</Address>
<AddressEntity
address={ item }
isLoading={ isLoading }
fontWeight={ 700 }
mr={ 2 }
/>
<Skeleton isLoaded={ !isLoading } fontSize="sm" ml="auto" minW={ 6 } color="text_secondary">
<span>{ index }</span>
</Skeleton>
......
......@@ -5,11 +5,8 @@ import React from 'react';
import type { AddressesItem } from 'types/api/addresses';
import config from 'configs/app';
import Address from 'ui/shared/address/Address';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
type Props = {
item: AddressesItem;
......@@ -37,20 +34,12 @@ const AddressesTableItem = ({
{ index }
</Skeleton>
</Td>
<Td>
<Address display="inline-flex" maxW="100%">
<AddressIcon address={ item } mr={ 2 } isLoading={ isLoading }/>
<AddressLink
fontWeight={ 700 }
flexGrow={ 1 }
w="calc(100% - 32px)"
hash={ item.hash }
alias={ item.name }
type="address"
isLoading={ isLoading }
/>
<CopyToClipboard text={ item.hash } isLoading={ isLoading }/>
</Address>
<Td verticalAlign="middle">
<AddressEntity
address={ item }
isLoading={ isLoading }
fontWeight={ 700 }
/>
</Td>
<Td pl={ 10 }>
{ item.public_tags && item.public_tags.length ? item.public_tags.map(tag => (
......
......@@ -20,11 +20,11 @@ import dayjs from 'lib/date/dayjs';
import { space } from 'lib/html-entities';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import getQueryParamString from 'lib/router/getQueryParamString';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -206,8 +206,10 @@ const BlockDetails = ({ query }: Props) => {
columnGap={ 1 }
isLoading={ isPlaceholderData }
>
<AddressLink type="address" hash={ data.miner.hash } isLoading={ isPlaceholderData }/>
{ data.miner.name && <Text>{ `(${ capitalize(validatorTitle) }: ${ data.miner.name })` }</Text> }
<AddressEntity
address={ data.miner }
isLoading={ isPlaceholderData }
/>
{ /* api doesn't return the block processing time yet */ }
{ /* <Text>{ dayjs.duration(block.minedIn, 'second').humanize(true) }</Text> */ }
</DetailsInfoItem>
......
......@@ -13,8 +13,8 @@ import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import { WEI } from 'lib/consts';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -55,9 +55,12 @@ const BlocksListItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
<span>{ data.size.toLocaleString() } bytes</span>
</Skeleton>
</Flex>
<Flex columnGap={ 2 }>
<Flex columnGap={ 2 } w="100%">
<Text fontWeight={ 500 }>{ capitalize(getNetworkValidatorTitle()) }</Text>
<AddressLink type="address" alias={ data.miner.name } hash={ data.miner.hash } truncation="constant" isLoading={ isLoading }/>
<AddressEntity
address={ data.miner }
isLoading={ isLoading }
/>
</Flex>
<Flex columnGap={ 2 }>
<Text fontWeight={ 500 }>Txn</Text>
......
......@@ -25,9 +25,9 @@ const BlocksTable = ({ data, isLoading, top, page }: Props) => {
<Tr>
<Th width="125px">Block</Th>
<Th width="120px">Size, bytes</Th>
<Th width={ config.features.rollup.isEnabled ? '37%' : '21%' } minW="144px">{ capitalize(getNetworkValidatorTitle()) }</Th>
<Th width={ config.features.rollup.isEnabled ? '37%' : '23%' } minW="160px">{ capitalize(getNetworkValidatorTitle()) }</Th>
<Th width="64px" isNumeric>Txn</Th>
<Th width={ config.features.rollup.isEnabled ? '63%' : '35%' }>Gas used</Th>
<Th width={ config.features.rollup.isEnabled ? '63%' : '33%' }>Gas used</Th>
{ !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.total_reward &&
<Th width="22%">Reward { config.chain.currency.symbol }</Th> }
{ !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.burnt_fees &&
......
......@@ -12,8 +12,8 @@ import flameIcon from 'icons/flame.svg';
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -65,13 +65,8 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
</Skeleton>
</Td>
<Td fontSize="sm">
<AddressLink
type="address"
alias={ data.miner.name }
hash={ data.miner.hash }
truncation="constant"
display="inline-flex"
maxW="100%"
<AddressEntity
address={ data.miner }
isLoading={ isLoading }
/>
</Td>
......
import { Box, Skeleton } from '@chakra-ui/react';
import React, { useCallback } from 'react';
import type { CustomAbi } from 'types/api/account';
import AddressSnippet from 'ui/shared/AddressSnippet';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
......@@ -25,7 +26,16 @@ const CustomAbiListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Prop
return (
<ListItemMobile>
<AddressSnippet address={ item.contract_address } subtitle={ item.name } isLoading={ isLoading }/>
<Box maxW="100%">
<AddressEntity
address={ item.contract_address }
fontWeight="600"
isLoading={ isLoading }
/>
<Skeleton fontSize="sm" color="text_secondary" mt={ 0.5 } ml={ 8 } display="inline-block" isLoaded={ !isLoading }>
<span>{ item.name }</span>
</Skeleton>
</Box>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick } isLoading={ isLoading }/>
</ListItemMobile>
);
......
import {
Tr,
Td,
Box,
Skeleton,
} from '@chakra-ui/react';
import React, { useCallback } from 'react';
import type { CustomAbi } from 'types/api/account';
import AddressSnippet from 'ui/shared/AddressSnippet';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
interface Props {
......@@ -29,7 +31,16 @@ const CustomAbiTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Pro
return (
<Tr alignItems="top" key={ item.id }>
<Td>
<AddressSnippet address={ item.contract_address } subtitle={ item.name } isLoading={ isLoading }/>
<Box maxW="100%">
<AddressEntity
address={ item.contract_address }
fontWeight="600"
isLoading={ isLoading }
/>
<Skeleton fontSize="sm" color="text_secondary" mt={ 0.5 } ml={ 8 } display="inline-block" isLoaded={ !isLoading }>
<span>{ item.name }</span>
</Skeleton>
</Box>
</Td>
<Td>
<TableItemActionButtons onDeleteClick={ onItemDeleteClick } onEditClick={ onItemEditClick } isLoading={ isLoading }/>
......
......@@ -13,7 +13,7 @@ import config from 'configs/app';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
type Props = {
......@@ -66,7 +66,12 @@ const LatestBlocksItem = ({ block, h, isLoading }: Props) => {
<Skeleton isLoaded={ !isLoading }>Reward</Skeleton>
<Skeleton isLoaded={ !isLoading } color="text_secondary"><span>{ totalReward.toFixed() }</span></Skeleton>
<Skeleton isLoaded={ !isLoading } textTransform="capitalize">{ getNetworkValidatorTitle() }</Skeleton>
<AddressLink type="address" alias={ block.miner.name } hash={ block.miner.hash } truncation="constant" maxW="100%" isLoading={ isLoading }/>
<AddressEntity
address={ block.miner }
isLoading={ isLoading }
noIcon
noCopy
/>
</>
) }
</Grid>
......
......@@ -14,10 +14,8 @@ import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
......@@ -83,31 +81,20 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
isLoading={ isLoading }
/>
<Box overflow="hidden" ml={ 1 }>
<Address mb={ 2 }>
<AddressIcon address={ tx.from } isLoading={ isLoading }/>
<AddressLink
type="address"
hash={ tx.from.hash }
alias={ tx.from.name }
fontWeight="500"
ml={ 2 }
fontSize="sm"
<AddressEntity
isLoading={ isLoading }
address={ tx.from }
fontSize="sm"
fontWeight="500"
mb={ 2 }
/>
{ dataTo && (
<AddressEntity
isLoading={ isLoading }
address={ dataTo }
fontSize="sm"
fontWeight="500"
/>
</Address>
{ dataTo && (
<Address>
<AddressIcon address={ dataTo } isLoading={ isLoading }/>
<AddressLink
type="address"
hash={ dataTo.hash }
alias={ dataTo.name }
fontWeight="500"
ml={ 2 }
fontSize="sm"
isLoading={ isLoading }
/>
</Address>
) }
</Box>
</Grid>
......
......@@ -13,10 +13,8 @@ import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
......@@ -67,19 +65,14 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
) }
</Flex>
<Flex alignItems="center" mb={ 3 }>
<Address mr={ 2 }>
<AddressIcon address={ tx.from } isLoading={ isLoading }/>
<AddressLink
type="address"
hash={ tx.from.hash }
alias={ tx.from.name }
fontWeight="500"
ml={ 2 }
truncation="constant"
fontSize="sm"
isLoading={ isLoading }
/>
</Address>
<AddressEntity
isLoading={ isLoading }
address={ tx.from }
truncation="constant"
fontSize="sm"
fontWeight="500"
mr={ 2 }
/>
<Icon
as={ rightArrowIcon }
boxSize={ 6 }
......@@ -87,19 +80,13 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
isLoading={ isLoading }
/>
{ dataTo && (
<Address ml={ 2 }>
<AddressIcon address={ dataTo } isLoading={ isLoading }/>
<AddressLink
type="address"
hash={ dataTo.hash }
alias={ dataTo.name }
fontWeight="500"
ml={ 2 }
truncation="constant"
fontSize="sm"
isLoading={ isLoading }
/>
</Address>
<AddressEntity
isLoading={ isLoading }
address={ dataTo }
truncation="constant"
fontSize="sm"
fontWeight="500"
/>
) }
</Flex>
<Skeleton isLoaded={ !isLoading } mb={ 2 } fontSize="sm" w="fit-content">
......
......@@ -7,7 +7,7 @@ import config from 'configs/app';
import globeIcon from 'icons/globe.svg';
import txIcon from 'icons/transactions.svg';
import { sortByDateDesc } from 'ui/shared/chart/utils/sorts';
import TokenLogo from 'ui/shared/TokenLogo';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
id: 'daily_txs',
......@@ -30,13 +30,15 @@ const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
const nativeTokenData = {
name: config.chain.currency.name || '',
icon_url: '',
symbol: '',
address: '',
};
const coinPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
id: 'coin_price',
title: `${ config.chain.currency.symbol } price`,
value: (stats) => '$' + Number(stats.coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }),
icon: <TokenLogo data={ nativeTokenData } boxSize={ 6 }/>,
icon: <TokenEntity.Icon token={ nativeTokenData } boxSize={ 6 } marginRight={ 0 }/>,
hint: `${ config.chain.currency.symbol } token daily price in USD.`,
api: {
resourceName: 'homepage_chart_market',
......
......@@ -4,16 +4,12 @@ import React from 'react';
import type { L2DepositsItem } from 'types/api/l2Deposits';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import dayjs from 'lib/date/dayjs';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressEntityL1 from 'ui/shared/entities/address/AddressEntityL1';
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 ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
const feature = config.features.rollup;
......@@ -31,7 +27,7 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Container>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 block No</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<ListItemMobileGrid.Value>
<BlockEntityL1
number={ item.l1_block_number }
isLoading={ isLoading }
......@@ -42,7 +38,7 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<ListItemMobileGrid.Value>
<TxEntity
isLoading={ isLoading }
hash={ item.l2_tx_hash }
......@@ -57,7 +53,7 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<ListItemMobileGrid.Value>
<TxEntityL1
isLoading={ isLoading }
hash={ item.l1_tx_hash }
......@@ -67,19 +63,12 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn origin</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/address/[hash]', query: { hash: item.l1_tx_origin } }) }
maxW="100%"
display="flex"
overflow="hidden"
<ListItemMobileGrid.Value>
<AddressEntityL1
address={{ hash: item.l1_tx_origin, name: '', is_contract: false, is_verified: false, implementation_name: '' }}
isLoading={ isLoading }
>
<AddressIcon address={{ hash: item.l1_tx_origin, is_contract: false, implementation_name: '' }} isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 2 }>
<HashStringShortenDynamic hash={ item.l1_tx_origin }/>
</Skeleton>
</LinkExternal>
noCopy
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Gas limit</ListItemMobileGrid.Label>
......
......@@ -4,16 +4,12 @@ import React from 'react';
import type { L2DepositsItem } from 'types/api/l2Deposits';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import dayjs from 'lib/date/dayjs';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressEntityL1 from 'ui/shared/entities/address/AddressEntityL1';
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';
const feature = config.features.rollup;
......@@ -59,18 +55,12 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
/>
</Td>
<Td verticalAlign="middle">
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/address/[hash]', query: { hash: item.l1_tx_origin } }) }
maxW="100%"
display="inline-flex"
overflow="hidden"
<AddressEntityL1
address={{ hash: item.l1_tx_origin, name: '', is_contract: false, is_verified: false, implementation_name: '' }}
isLoading={ isLoading }
>
<AddressIcon address={{ hash: item.l1_tx_origin, is_contract: false, implementation_name: '' }} isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 2 }>
<HashStringShorten hash={ item.l1_tx_origin }/>
</Skeleton>
</LinkExternal>
truncation="constant"
noCopy
/>
</Td>
<Td verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block">
......
......@@ -5,9 +5,7 @@ import type { L2WithdrawalsItem } from 'types/api/l2Withdrawals';
import config from 'configs/app';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import LinkExternal from 'ui/shared/LinkExternal';
......@@ -38,17 +36,17 @@ const WithdrawalsListItem = ({ item, isLoading }: Props) => {
{ item.from && (
<>
<ListItemMobileGrid.Label isLoading={ isLoading }>From</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<Address>
<AddressIcon address={ item.from } isLoading={ isLoading }/>
<AddressLink hash={ item.from.hash } type="address" truncation="dynamic" ml={ 2 } isLoading={ isLoading }/>
</Address>
<ListItemMobileGrid.Value>
<AddressEntity
address={ item.from }
isLoading={ isLoading }
/>
</ListItemMobileGrid.Value>
</>
) }
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<ListItemMobileGrid.Value>
<TxEntity
isLoading={ isLoading }
hash={ item.l2_tx_hash }
......@@ -78,7 +76,7 @@ const WithdrawalsListItem = ({ item, isLoading }: Props) => {
{ item.l1_tx_hash && (
<>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<ListItemMobileGrid.Value>
<TxEntityL1
isLoading={ isLoading }
hash={ item.l1_tx_hash }
......
......@@ -5,9 +5,7 @@ import type { L2WithdrawalsItem } from 'types/api/l2Withdrawals';
import config from 'configs/app';
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 AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import LinkExternal from 'ui/shared/LinkExternal';
......@@ -31,10 +29,11 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
</Td>
<Td verticalAlign="middle">
{ item.from ? (
<Address>
<AddressIcon address={ item.from } isLoading={ isLoading }/>
<AddressLink hash={ item.from.hash } type="address" truncation="constant" ml={ 2 } isLoading={ isLoading }/>
</Address>
<AddressEntity
address={ item.from }
isLoading={ isLoading }
truncation="constant"
/>
) : 'N/A' }
</Td>
<Td verticalAlign="middle">
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment