Commit 3e24ed76 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Tx interpretation: change margins between elements (#2241)

Paddings: icons + amount/text in interpretation

Fixes #1997
parent 9657e427
...@@ -391,3 +391,8 @@ export const withRecipientNameTag = { ...@@ -391,3 +391,8 @@ export const withRecipientNameTag = {
...withRecipientEns, ...withRecipientEns,
to: addressMock.withNameTag, to: addressMock.withNameTag,
}; };
export const withRecipientContract = {
...withRecipientEns,
to: addressMock.contract,
};
...@@ -2,7 +2,7 @@ import type { AddressMetadataTagApi } from './addressMetadata'; ...@@ -2,7 +2,7 @@ import type { AddressMetadataTagApi } from './addressMetadata';
export interface AddressImplementation { export interface AddressImplementation {
address: string; address: string;
name: string | null; name?: string | null;
} }
export interface AddressTag { export interface AddressTag {
......
...@@ -42,7 +42,7 @@ const DomainsGrid = ({ data }: { data: Array<bens.Domain> }) => { ...@@ -42,7 +42,7 @@ const DomainsGrid = ({ data }: { data: Array<bens.Domain> }) => {
rowGap={ 4 } rowGap={ 4 }
mt={ 2 } mt={ 2 }
> >
{ data.slice(0, 9).map((domain) => <EnsEntity key={ domain.id } name={ domain.name } protocol={ domain.protocol } noCopy/>) } { data.slice(0, 9).map((domain) => <EnsEntity key={ domain.id } domain={ domain.name } protocol={ domain.protocol } noCopy/>) }
</Grid> </Grid>
); );
}; };
...@@ -126,7 +126,7 @@ const AddressEnsDomains = ({ query, addressHash, mainDomainName }: Props) => { ...@@ -126,7 +126,7 @@ const AddressEnsDomains = ({ query, addressHash, mainDomainName }: Props) => {
<Box w="100%"> <Box w="100%">
<chakra.span color="text_secondary" fontSize="xs">Primary*</chakra.span> <chakra.span color="text_secondary" fontSize="xs">Primary*</chakra.span>
<Flex alignItems="center" fontSize="md" mt={ 2 }> <Flex alignItems="center" fontSize="md" mt={ 2 }>
<EnsEntity name={ mainDomain.name } protocol={ mainDomain.protocol } fontWeight={ 600 } noCopy/> <EnsEntity domain={ mainDomain.name } protocol={ mainDomain.protocol } fontWeight={ 600 } noCopy/>
{ mainDomain.expiry_date && { mainDomain.expiry_date &&
<chakra.span color="text_secondary" whiteSpace="pre"> (expires { dayjs(mainDomain.expiry_date).fromNow() })</chakra.span> } <chakra.span color="text_secondary" whiteSpace="pre"> (expires { dayjs(mainDomain.expiry_date).fromNow() })</chakra.span> }
</Flex> </Flex>
......
...@@ -25,7 +25,7 @@ const NameDomainsListItem = ({ ...@@ -25,7 +25,7 @@ const NameDomainsListItem = ({
<ListItemMobileGrid.Container> <ListItemMobileGrid.Container>
<ListItemMobileGrid.Label isLoading={ isLoading }>Domain</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Domain</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<EnsEntity name={ name } protocol={ protocol } isLoading={ isLoading } fontWeight={ 500 }/> <EnsEntity domain={ name } protocol={ protocol } isLoading={ isLoading } fontWeight={ 500 }/>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
{ resolvedAddress && ( { resolvedAddress && (
......
...@@ -24,7 +24,7 @@ const NameDomainsTableItem = ({ ...@@ -24,7 +24,7 @@ const NameDomainsTableItem = ({
return ( return (
<Tr> <Tr>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
<EnsEntity name={ name } protocol={ protocol } isLoading={ isLoading } fontWeight={ 600 }/> <EnsEntity domain={ name } protocol={ protocol } isLoading={ isLoading } fontWeight={ 600 }/>
</Td> </Td>
<Td verticalAlign="middle"> <Td verticalAlign="middle">
{ resolvedAddress && <AddressEntity address={ resolvedAddress } isLoading={ isLoading } fontWeight={ 500 }/> } { resolvedAddress && <AddressEntity address={ resolvedAddress } isLoading={ isLoading } fontWeight={ 500 }/> }
......
...@@ -272,7 +272,11 @@ const AddressPageContent = () => { ...@@ -272,7 +272,11 @@ const AddressPageContent = () => {
const titleContentAfter = ( const titleContentAfter = (
<EntityTags <EntityTags
tags={ tags } tags={ tags }
isLoading={ isLoading || (config.features.addressMetadata.isEnabled && addressMetadataQuery.isPending) } isLoading={
isLoading ||
(config.features.userOps.isEnabled && userOpsAccountQuery.isPlaceholderData) ||
(config.features.addressMetadata.isEnabled && addressMetadataQuery.isPending)
}
/> />
); );
...@@ -302,7 +306,7 @@ const AddressPageContent = () => { ...@@ -302,7 +306,7 @@ const AddressPageContent = () => {
<Flex alignItems="center" w="100%" columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}> <Flex alignItems="center" w="100%" columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}>
{ addressQuery.data?.ens_domain_name && ( { addressQuery.data?.ens_domain_name && (
<EnsEntity <EnsEntity
name={ addressQuery.data?.ens_domain_name } domain={ addressQuery.data?.ens_domain_name }
protocol={ !addressEnsDomainsQuery.isPending ? addressMainDomain?.protocol : null } protocol={ !addressEnsDomainsQuery.isPending ? addressMainDomain?.protocol : null }
fontFamily="heading" fontFamily="heading"
fontSize="lg" fontSize="lg"
...@@ -319,7 +323,7 @@ const AddressPageContent = () => { ...@@ -319,7 +323,7 @@ const AddressPageContent = () => {
fontWeight={ 500 } fontWeight={ 500 }
noLink noLink
isSafeAddress={ isSafeAddress } isSafeAddress={ isSafeAddress }
iconColor={ isSafeAddress ? safeIconColor : undefined } icon={{ color: isSafeAddress ? safeIconColor : undefined }}
mr={ 4 } mr={ 4 }
/> />
{ !isLoading && addressQuery.data?.is_contract && addressQuery.data.token && { !isLoading && addressQuery.data?.is_contract && addressQuery.data.token &&
......
...@@ -167,7 +167,7 @@ const BlockPageContent = () => { ...@@ -167,7 +167,7 @@ const BlockPageContent = () => {
})(); })();
const titleSecondRow = ( const titleSecondRow = (
<> <>
{ !config.UI.views.block.hiddenFields?.miner && ( { !config.UI.views.block.hiddenFields?.miner && blockQuery.data?.miner && (
<Skeleton <Skeleton
isLoaded={ !blockQuery.isPlaceholderData } isLoaded={ !blockQuery.isPlaceholderData }
fontFamily="heading" fontFamily="heading"
...@@ -179,7 +179,7 @@ const BlockPageContent = () => { ...@@ -179,7 +179,7 @@ const BlockPageContent = () => {
<chakra.span flexShrink={ 0 }> <chakra.span flexShrink={ 0 }>
{ `${ capitalize(getNetworkValidationActionText()) } by` } { `${ capitalize(getNetworkValidationActionText()) } by` }
</chakra.span> </chakra.span>
<AddressEntity address={ blockQuery.data?.miner }/> <AddressEntity address={ blockQuery.data.miner }/>
</Skeleton> </Skeleton>
) } ) }
<NetworkExplorers type="block" pathParam={ heightOrHash } ml={{ base: config.UI.views.block.hiddenFields?.miner ? 0 : 3, lg: 'auto' }}/> <NetworkExplorers type="block" pathParam={ heightOrHash } ml={{ base: config.UI.views.block.hiddenFields?.miner ? 0 : 3, lg: 'auto' }}/>
......
...@@ -155,7 +155,7 @@ const CsvExport = () => { ...@@ -155,7 +155,7 @@ const CsvExport = () => {
const limit = (configQuery.data?.limit || 10_000).toLocaleString(undefined, { maximumFractionDigits: 3, notation: 'compact' }); const limit = (configQuery.data?.limit || 10_000).toLocaleString(undefined, { maximumFractionDigits: 3, notation: 'compact' });
if (exportTypeParam === 'holders') { if (exportTypeParam === 'holders' && tokenQuery.data) {
return ( return (
<Flex mb={ 10 } whiteSpace="pre-wrap" flexWrap="wrap"> <Flex mb={ 10 } whiteSpace="pre-wrap" flexWrap="wrap">
<span>Export { exportType.text } for token </span> <span>Export { exportType.text } for token </span>
...@@ -173,6 +173,10 @@ const CsvExport = () => { ...@@ -173,6 +173,10 @@ const CsvExport = () => {
); );
} }
if (!addressQuery.data) {
return null;
}
return ( return (
<Flex mb={ 10 } whiteSpace="pre-wrap" flexWrap="wrap"> <Flex mb={ 10 } whiteSpace="pre-wrap" flexWrap="wrap">
<span>Export { exportType.text } for address </span> <span>Export { exportType.text } for address </span>
......
...@@ -57,7 +57,7 @@ const NameDomain = () => { ...@@ -57,7 +57,7 @@ const NameDomain = () => {
flexWrap={{ base: 'wrap', lg: 'nowrap' }} flexWrap={{ base: 'wrap', lg: 'nowrap' }}
> >
<EnsEntity <EnsEntity
name={ domainName } domain={ domainName }
protocol={ infoQuery.data?.protocol } protocol={ infoQuery.data?.protocol }
isLoading={ isLoading } isLoading={ isLoading }
noLink noLink
......
...@@ -60,7 +60,7 @@ const DefaultView = () => { ...@@ -60,7 +60,7 @@ const DefaultView = () => {
beforeTitle={ ( beforeTitle={ (
<TokenEntity.Icon <TokenEntity.Icon
token={ tokenData } token={ tokenData }
iconSize="lg" size="lg"
/> />
) } ) }
backLink={ backLink } backLink={ backLink }
......
...@@ -52,7 +52,7 @@ const LongNameAndManyTags = () => { ...@@ -52,7 +52,7 @@ const LongNameAndManyTags = () => {
beforeTitle={ ( beforeTitle={ (
<TokenEntity.Icon <TokenEntity.Icon
token={ tokenData } token={ tokenData }
iconSize="lg" size="lg"
/> />
) } ) }
contentAfter={ contentAfter } contentAfter={ contentAfter }
......
...@@ -29,7 +29,7 @@ const NftTokenTransferSnippet = ({ value, token, tokenId }: Props) => { ...@@ -29,7 +29,7 @@ const NftTokenTransferSnippet = ({ value, token, tokenId }: Props) => {
hash={ token.address } hash={ token.address }
id={ tokenId } id={ tokenId }
fontWeight={ 600 } fontWeight={ 600 }
iconSize="md" icon={{ size: 'md' }}
maxW={{ base: '100%', lg: '150px' }} maxW={{ base: '100%', lg: '150px' }}
w="auto" w="auto"
flexShrink={ 0 } flexShrink={ 0 }
......
...@@ -9,7 +9,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -9,7 +9,7 @@ import { test, expect } from 'playwright/lib';
import AddressEntity from './AddressEntity'; import AddressEntity from './AddressEntity';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
test.use({ viewport: { width: 180, height: 140 } }); test.use({ viewport: { width: 180, height: 140 } });
...@@ -19,7 +19,7 @@ test.describe('icon size', () => { ...@@ -19,7 +19,7 @@ test.describe('icon size', () => {
const component = await render( const component = await render(
<AddressEntity <AddressEntity
address={ addressMock.withoutName } address={ addressMock.withoutName }
iconSize={ size } icon={{ size }}
/>, />,
); );
...@@ -69,7 +69,7 @@ test.describe('proxy contract', () => { ...@@ -69,7 +69,7 @@ test.describe('proxy contract', () => {
test('without implementation name', async({ render, page }) => { test('without implementation name', async({ render, page }) => {
const component = await render( const component = await render(
<AddressEntity <AddressEntity
address={{ ...addressMock.contract, implementations: [ { address: addressMock.contract.implementations?.[0].address } ] }} address={{ ...addressMock.contract, implementations: [ { address: addressMock.contract.implementations?.[0].address as string } ] }}
/>, />,
); );
...@@ -81,7 +81,7 @@ test.describe('proxy contract', () => { ...@@ -81,7 +81,7 @@ test.describe('proxy contract', () => {
test('without any name', async({ render, page }) => { test('without any name', async({ render, page }) => {
const component = await render( const component = await render(
<AddressEntity <AddressEntity
address={{ ...addressMock.contract, name: undefined, implementations: [ { address: addressMock.contract.implementations?.[0].address } ] }} address={{ ...addressMock.contract, name: undefined, implementations: [ { address: addressMock.contract.implementations?.[0].address as string } ] }}
/>, />,
); );
......
import type { As } from '@chakra-ui/react'; import type { As } from '@chakra-ui/react';
import { Box, Flex, Skeleton, Tooltip, chakra, VStack } from '@chakra-ui/react'; import { Box, Flex, Skeleton, Tooltip, chakra, VStack } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import type { AddressParam } from 'types/api/addressParams'; import type { AddressParam } from 'types/api/addressParams';
...@@ -10,7 +9,7 @@ import { route } from 'nextjs-routes'; ...@@ -10,7 +9,7 @@ import { route } from 'nextjs-routes';
import { useAddressHighlightContext } from 'lib/contexts/addressHighlight'; import { useAddressHighlightContext } from 'lib/contexts/addressHighlight';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import { getIconProps } from '../base/utils'; import { distributeEntityProps, getIconProps } from '../base/utils';
import AddressEntityContentProxy from './AddressEntityContentProxy'; import AddressEntityContentProxy from './AddressEntityContentProxy';
import AddressIdenticon from './AddressIdenticon'; import AddressIdenticon from './AddressIdenticon';
...@@ -29,10 +28,7 @@ const Link = chakra((props: LinkProps) => { ...@@ -29,10 +28,7 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & Pick<EntityProps, 'address' | 'isSafeAddress'> & { type IconProps = Pick<EntityProps, 'address' | 'isSafeAddress'> & EntityBase.IconBaseProps;
asProp?: As;
name?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => { const Icon = (props: IconProps) => {
if (props.noIcon) { if (props.noIcon) {
...@@ -40,8 +36,8 @@ const Icon = (props: IconProps) => { ...@@ -40,8 +36,8 @@ const Icon = (props: IconProps) => {
} }
const styles = { const styles = {
...getIconProps(props.iconSize), ...getIconProps(props.size),
marginRight: 2, marginRight: props.marginRight ?? 2,
}; };
if (props.isLoading) { if (props.isLoading) {
...@@ -80,7 +76,7 @@ const Icon = (props: IconProps) => { ...@@ -80,7 +76,7 @@ const Icon = (props: IconProps) => {
return ( return (
<Flex marginRight={ styles.marginRight }> <Flex marginRight={ styles.marginRight }>
<AddressIdenticon <AddressIdenticon
size={ props.iconSize === 'lg' ? 30 : 20 } size={ props.size === 'lg' ? 30 : 20 }
hash={ props.address.hash } hash={ props.address.hash }
/> />
</Flex> </Flex>
...@@ -137,18 +133,18 @@ const Copy = (props: CopyProps) => { ...@@ -137,18 +133,18 @@ const Copy = (props: CopyProps) => {
const Container = EntityBase.Container; const Container = EntityBase.Container;
interface AddressProp extends Partial<AddressParam> {
hash: string;
}
export interface EntityProps extends EntityBase.EntityBaseProps { export interface EntityProps extends EntityBase.EntityBaseProps {
address: Pick<AddressParam, address: AddressProp;
'hash' | 'name' | 'is_contract' | 'is_verified' | 'implementations' | 'ens_domain_name' | 'metadata'
>;
isSafeAddress?: boolean; isSafeAddress?: boolean;
noHighlight?: boolean; noHighlight?: boolean;
} }
const AddressEntry = (props: EntityProps) => { const AddressEntry = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
const context = useAddressHighlightContext(props.noHighlight); const context = useAddressHighlightContext(props.noHighlight);
return ( return (
...@@ -162,16 +158,16 @@ const AddressEntry = (props: EntityProps) => { ...@@ -162,16 +158,16 @@ const AddressEntry = (props: EntityProps) => {
position="relative" position="relative"
zIndex={ 0 } zIndex={ 0 }
> >
<Icon { ...partsProps } color={ props.iconColor }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
<Copy { ...partsProps }/> <Copy { ...partsProps.copy }/>
</Container> </Container>
); );
}; };
export default React.memo(chakra(AddressEntry)); export default React.memo(chakra<As, EntityProps>(AddressEntry));
export { export {
Container, Container,
......
...@@ -18,9 +18,7 @@ export type Truncation = 'constant' | 'constant_long' | 'dynamic' | 'tail' | 'no ...@@ -18,9 +18,7 @@ export type Truncation = 'constant' | 'constant_long' | 'dynamic' | 'tail' | 'no
export interface EntityBaseProps { export interface EntityBaseProps {
className?: string; className?: string;
href?: string; href?: string;
iconName?: IconName; icon?: EntityIconProps;
iconSize?: IconSize;
iconColor?: IconProps['color'];
isExternal?: boolean; isExternal?: boolean;
isLoading?: boolean; isLoading?: boolean;
noCopy?: boolean; noCopy?: boolean;
...@@ -81,28 +79,30 @@ const Link = chakra(({ isLoading, children, isExternal, onClick, href, noLink }: ...@@ -81,28 +79,30 @@ const Link = chakra(({ isLoading, children, isExternal, onClick, href, noLink }:
); );
}); });
export interface IconBaseProps extends Pick<EntityBaseProps, 'isLoading' | 'iconSize' | 'noIcon'> { interface EntityIconProps extends Pick<IconProps, 'color' | 'borderRadius' | 'marginRight' | 'boxSize'> {
name: IconName; name?: IconName;
color?: IconProps['color']; size?: IconSize;
borderRadius?: IconProps['borderRadius'];
} }
const Icon = ({ isLoading, iconSize, noIcon, name, color, borderRadius }: IconBaseProps) => { export interface IconBaseProps extends Pick<EntityBaseProps, 'isLoading' | 'noIcon'>, EntityIconProps {
}
const Icon = ({ isLoading, noIcon, size, name, color, borderRadius, marginRight, boxSize }: IconBaseProps) => {
const defaultColor = useColorModeValue('gray.500', 'gray.400'); const defaultColor = useColorModeValue('gray.500', 'gray.400');
if (noIcon) { if (noIcon || !name) {
return null; return null;
} }
const styles = getIconProps(iconSize); const styles = getIconProps(size);
return ( return (
<IconSvg <IconSvg
name={ name } name={ name }
boxSize={ styles.boxSize } boxSize={ boxSize ?? styles.boxSize }
isLoading={ isLoading } isLoading={ isLoading }
borderRadius={ borderRadius ?? 'base' } borderRadius={ borderRadius ?? 'base' }
display="block" display="block"
mr={ 2 } mr={ marginRight ?? 2 }
color={ color ?? defaultColor } color={ color ?? defaultColor }
minW={ 0 } minW={ 0 }
flexShrink={ 0 } flexShrink={ 0 }
......
import type { EntityBaseProps } from './components';
export type IconSize = 'md' | 'lg'; export type IconSize = 'md' | 'lg';
export function getIconProps(size: IconSize = 'md') { export function getIconProps(size: IconSize = 'md') {
...@@ -14,3 +16,16 @@ export function getIconProps(size: IconSize = 'md') { ...@@ -14,3 +16,16 @@ export function getIconProps(size: IconSize = 'md') {
} }
} }
} }
export function distributeEntityProps<Props extends EntityBaseProps>(props: Props) {
const { className, onClick, icon, ...restProps } = props;
return {
container: { className },
icon: { ...restProps, ...icon },
link: { ...restProps, onClick },
content: restProps,
symbol: restProps,
copy: restProps,
};
}
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import { distributeEntityProps } from '../base/utils';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>;
const Link = chakra((props: LinkProps) => { const Link = chakra((props: LinkProps) => {
...@@ -21,11 +23,7 @@ const Link = chakra((props: LinkProps) => { ...@@ -21,11 +23,7 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & { const Icon = (props: EntityBase.IconBaseProps) => {
name?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
...@@ -65,21 +63,20 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -65,21 +63,20 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
} }
const BlobEntity = (props: EntityProps) => { const BlobEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className }> <Container { ...partsProps.container }>
<Icon { ...partsProps }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
<Copy { ...partsProps }/> <Copy { ...partsProps.copy }/>
</Container> </Container>
); );
}; };
export default React.memo(chakra(BlobEntity)); export default React.memo(chakra<As, EntityProps>(BlobEntity));
export { export {
Container, Container,
......
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -11,25 +10,17 @@ import * as BlobEntity from './BlobEntity'; ...@@ -11,25 +10,17 @@ import * as BlobEntity from './BlobEntity';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const BlobEntityL1 = (props: BlobEntity.EntityProps) => { const BlobEntityL1 = (props: BlobEntity.EntityProps) => {
const partsProps = _omit(props, [ 'className', 'onClick' ]);
const linkProps = _omit(props, [ 'className' ]);
if (!rollupFeature.isEnabled) { if (!rollupFeature.isEnabled) {
return null; return null;
} }
const defaultHref = rollupFeature.L1BaseUrl + route({
pathname: '/blobs/[hash]',
query: { hash: props.hash },
});
return ( return (
<BlobEntity.Container className={ props.className }> <BlobEntity.default { ...props } href={ props.href ?? defaultHref } isExternal/>
<BlobEntity.Icon { ...partsProps }/>
<BlobEntity.Link
{ ...linkProps }
isExternal
href={ rollupFeature.L1BaseUrl + route({ pathname: '/blobs/[hash]', query: { hash: props.hash } }) }
>
<BlobEntity.Content { ...partsProps }/>
</BlobEntity.Link>
<BlobEntity.Copy { ...partsProps }/>
</BlobEntity.Container>
); );
}; };
......
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -11,23 +10,18 @@ import * as BlockEntity from './BlockEntity'; ...@@ -11,23 +10,18 @@ import * as BlockEntity from './BlockEntity';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const BatchEntityL2 = (props: BlockEntity.EntityProps) => { const BatchEntityL2 = (props: BlockEntity.EntityProps) => {
const linkProps = _omit(props, [ 'className' ]);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
if (!rollupFeature.isEnabled) { if (!rollupFeature.isEnabled) {
return null; return null;
} }
const defaultHref = route({ pathname: '/batches/[number]', query: { number: props.number.toString() } });
return ( return (
<BlockEntity.Container className={ props.className }> <BlockEntity.default
<BlockEntity.Icon { ...partsProps } name="txn_batches_slim"/> { ...props }
<BlockEntity.Link href={ props.href ?? defaultHref }
{ ...linkProps } icon={{ name: 'txn_batches_slim' }}
href={ route({ pathname: '/batches/[number]', query: { number: props.number.toString() } }) } />
>
<BlockEntity.Content { ...partsProps }/>
</BlockEntity.Link>
</BlockEntity.Container>
); );
}; };
......
...@@ -4,7 +4,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -4,7 +4,7 @@ import { test, expect } from 'playwright/lib';
import BlockEntity from './BlockEntity'; import BlockEntity from './BlockEntity';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
test.use({ viewport: { width: 180, height: 30 } }); test.use({ viewport: { width: 180, height: 30 } });
...@@ -14,7 +14,7 @@ test.describe('icon sizes', () => { ...@@ -14,7 +14,7 @@ test.describe('icon sizes', () => {
const component = await render( const component = await render(
<BlockEntity <BlockEntity
number={ 17943507 } number={ 17943507 }
iconSize={ size } icon={{ size }}
/>, />,
); );
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import { distributeEntityProps } from '../base/utils';
type LinkProps = EntityBase.LinkBaseProps & Partial<Pick<EntityProps, 'hash' | 'number'>>; type LinkProps = EntityBase.LinkBaseProps & Partial<Pick<EntityProps, 'hash' | 'number'>>;
const Link = chakra((props: LinkProps) => { const Link = chakra((props: LinkProps) => {
...@@ -22,11 +24,7 @@ const Link = chakra((props: LinkProps) => { ...@@ -22,11 +24,7 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & { const Icon = (props: EntityBase.IconBaseProps) => {
name?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
...@@ -55,20 +53,19 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -55,20 +53,19 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
} }
const BlockEntity = (props: EntityProps) => { const BlockEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className }> <Container { ...partsProps.container }>
<Icon { ...partsProps }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
</Container> </Container>
); );
}; };
export default React.memo(chakra(BlockEntity)); export default React.memo(chakra<As, EntityProps>(BlockEntity));
export { export {
Container, Container,
......
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -11,25 +10,16 @@ import * as BlockEntity from './BlockEntity'; ...@@ -11,25 +10,16 @@ import * as BlockEntity from './BlockEntity';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const BlockEntityL1 = (props: BlockEntity.EntityProps) => { const BlockEntityL1 = (props: BlockEntity.EntityProps) => {
const linkProps = _omit(props, [ 'className' ]);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
if (!rollupFeature.isEnabled) { if (!rollupFeature.isEnabled) {
return null; return null;
} }
return ( const defaultHref = rollupFeature.L1BaseUrl + route({
<BlockEntity.Container className={ props.className }> pathname: '/block/[height_or_hash]',
<BlockEntity.Icon { ...partsProps }/> query: { height_or_hash: props.hash ?? String(props.number) },
<BlockEntity.Link });
{ ...linkProps }
isExternal return <BlockEntity.default { ...props } href={ props.href ?? defaultHref } isExternal/>;
href={ rollupFeature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: props.hash ?? String(props.number) } }) }
>
<BlockEntity.Content { ...partsProps }/>
</BlockEntity.Link>
</BlockEntity.Container>
);
}; };
export default chakra(BlockEntityL1); export default chakra(BlockEntityL1);
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import config from 'configs/app'; import config from 'configs/app';
...@@ -9,21 +8,11 @@ import * as BlockEntity from './BlockEntity'; ...@@ -9,21 +8,11 @@ import * as BlockEntity from './BlockEntity';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const BlockEntityL2 = (props: BlockEntity.EntityProps) => { const BlockEntityL2 = (props: BlockEntity.EntityProps) => {
const linkProps = _omit(props, [ 'className' ]);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
if (!rollupFeature.isEnabled) { if (!rollupFeature.isEnabled) {
return null; return null;
} }
return ( return <BlockEntity.default { ...props } icon={{ name: 'txn_batches_slim' }}/>;
<BlockEntity.Container className={ props.className }>
<BlockEntity.Icon { ...partsProps } name="txn_batches_slim"/>
<BlockEntity.Link { ...linkProps }>
<BlockEntity.Content { ...partsProps }/>
</BlockEntity.Link>
</BlockEntity.Container>
);
}; };
export default chakra(BlockEntityL2); export default chakra(BlockEntityL2);
...@@ -6,7 +6,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -6,7 +6,7 @@ import { test, expect } from 'playwright/lib';
import EnsEntity from './EnsEntity'; import EnsEntity from './EnsEntity';
const name = 'cat.eth'; const name = 'cat.eth';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
test.use({ viewport: { width: 180, height: 30 } }); test.use({ viewport: { width: 180, height: 30 } });
...@@ -15,8 +15,8 @@ test.describe('icon size', () => { ...@@ -15,8 +15,8 @@ test.describe('icon size', () => {
test(size, async({ render }) => { test(size, async({ render }) => {
const component = await render( const component = await render(
<EnsEntity <EnsEntity
name={ name } domain={ name }
iconSize={ size } icon={{ size }}
/>, />,
); );
...@@ -28,7 +28,7 @@ test.describe('icon size', () => { ...@@ -28,7 +28,7 @@ test.describe('icon size', () => {
test('loading', async({ render }) => { test('loading', async({ render }) => {
const component = await render( const component = await render(
<EnsEntity <EnsEntity
name={ name } domain={ name }
isLoading isLoading
/>, />,
); );
...@@ -39,7 +39,7 @@ test('loading', async({ render }) => { ...@@ -39,7 +39,7 @@ test('loading', async({ render }) => {
test('with long name', async({ render }) => { test('with long name', async({ render }) => {
const component = await render( const component = await render(
<EnsEntity <EnsEntity
name="kitty.kitty.kitty.cat.eth" domain="kitty.kitty.kitty.cat.eth"
/>, />,
); );
...@@ -51,7 +51,7 @@ test('with long name', async({ render }) => { ...@@ -51,7 +51,7 @@ test('with long name', async({ render }) => {
test('customization', async({ render }) => { test('customization', async({ render }) => {
const component = await render( const component = await render(
<EnsEntity <EnsEntity
name={ name } domain={ name }
p={ 3 } p={ 3 }
borderWidth="1px" borderWidth="1px"
borderColor="blue.700" borderColor="blue.700"
...@@ -68,7 +68,7 @@ test.describe('', () => { ...@@ -68,7 +68,7 @@ test.describe('', () => {
const component = await render( const component = await render(
<EnsEntity <EnsEntity
name={ name } domain={ name }
protocol={ domainMock.protocolA } protocol={ domainMock.protocolA }
/>, />,
); );
......
import type { As } from '@chakra-ui/react';
import { Box, chakra, Flex, Image, PopoverBody, PopoverContent, PopoverTrigger, Portal, Skeleton, Text } from '@chakra-ui/react'; import { Box, chakra, Flex, Image, PopoverBody, PopoverContent, PopoverTrigger, Portal, Skeleton, Text } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import type * as bens from '@blockscout/bens-types'; import type * as bens from '@blockscout/bens-types';
...@@ -12,12 +12,12 @@ import IconSvg from 'ui/shared/IconSvg'; ...@@ -12,12 +12,12 @@ import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/links/LinkExternal'; import LinkExternal from 'ui/shared/links/LinkExternal';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
import { getIconProps } from '../base/utils'; import { distributeEntityProps, getIconProps } from '../base/utils';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'name'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'domain'>;
const Link = chakra((props: LinkProps) => { const Link = chakra((props: LinkProps) => {
const defaultHref = route({ pathname: '/name-domains/[name]', query: { name: props.name } }); const defaultHref = route({ pathname: '/name-domains/[name]', query: { name: props.domain } });
return ( return (
<EntityBase.Link <EntityBase.Link
...@@ -29,15 +29,13 @@ const Link = chakra((props: LinkProps) => { ...@@ -29,15 +29,13 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & Pick<EntityProps, 'protocol'> & { type IconProps = Pick<EntityProps, 'protocol'> & EntityBase.IconBaseProps;
iconName?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => { const Icon = (props: IconProps) => {
const icon = <EntityBase.Icon { ...props } name={ props.iconName ?? 'ENS_slim' }/>; const icon = <EntityBase.Icon { ...props } name={ props.name ?? 'ENS_slim' }/>;
if (props.protocol) { if (props.protocol) {
const styles = getIconProps(props.iconSize); const styles = getIconProps(props.size);
if (props.isLoading) { if (props.isLoading) {
return <Skeleton boxSize={ styles.boxSize } borderRadius="sm" mr={ 2 }/>; return <Skeleton boxSize={ styles.boxSize } borderRadius="sm" mr={ 2 }/>;
...@@ -98,24 +96,24 @@ const Icon = (props: IconProps) => { ...@@ -98,24 +96,24 @@ const Icon = (props: IconProps) => {
return icon; return icon;
}; };
type ContentProps = Omit<EntityBase.ContentBaseProps, 'text'> & Pick<EntityProps, 'name'>; type ContentProps = Omit<EntityBase.ContentBaseProps, 'text'> & Pick<EntityProps, 'domain'>;
const Content = chakra((props: ContentProps) => { const Content = chakra((props: ContentProps) => {
return ( return (
<TruncatedValue <TruncatedValue
isLoading={ props.isLoading } isLoading={ props.isLoading }
value={ props.name } value={ props.domain }
/> />
); );
}); });
type CopyProps = Omit<EntityBase.CopyBaseProps, 'text'> & Pick<EntityProps, 'name'>; type CopyProps = Omit<EntityBase.CopyBaseProps, 'text'> & Pick<EntityProps, 'domain'>;
const Copy = (props: CopyProps) => { const Copy = (props: CopyProps) => {
return ( return (
<EntityBase.Copy <EntityBase.Copy
{ ...props } { ...props }
text={ props.name } text={ props.domain }
/> />
); );
}; };
...@@ -123,26 +121,25 @@ const Copy = (props: CopyProps) => { ...@@ -123,26 +121,25 @@ const Copy = (props: CopyProps) => {
const Container = EntityBase.Container; const Container = EntityBase.Container;
export interface EntityProps extends EntityBase.EntityBaseProps { export interface EntityProps extends EntityBase.EntityBaseProps {
name: string; domain: string;
protocol?: bens.ProtocolInfo | null; protocol?: bens.ProtocolInfo | null;
} }
const EnsEntity = (props: EntityProps) => { const EnsEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className }> <Container { ...partsProps.container }>
<Icon { ...partsProps }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
<Copy { ...partsProps }/> <Copy { ...partsProps.copy }/>
</Container> </Container>
); );
}; };
export default React.memo(chakra(EnsEntity)); export default React.memo(chakra<As, EntityProps>(EnsEntity));
export { export {
Container, Container,
......
...@@ -4,7 +4,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -4,7 +4,7 @@ import { test, expect } from 'playwright/lib';
import NftEntity from './NftEntity'; import NftEntity from './NftEntity';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
const hash = '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859'; const hash = '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859';
test.use({ viewport: { width: 180, height: 30 } }); test.use({ viewport: { width: 180, height: 30 } });
...@@ -15,8 +15,8 @@ test.describe('icon sizes', () => { ...@@ -15,8 +15,8 @@ test.describe('icon sizes', () => {
const component = await render( const component = await render(
<NftEntity <NftEntity
hash={ hash } hash={ hash }
id={ 1042 } id="1042"
iconSize={ size } icon={{ size }}
/>, />,
); );
...@@ -29,7 +29,7 @@ test('loading', async({ render }) => { ...@@ -29,7 +29,7 @@ test('loading', async({ render }) => {
const component = await render( const component = await render(
<NftEntity <NftEntity
hash={ hash } hash={ hash }
id={ 1042 } id="1042"
isLoading isLoading
/>, />,
); );
...@@ -41,7 +41,7 @@ test('long id', async({ render }) => { ...@@ -41,7 +41,7 @@ test('long id', async({ render }) => {
const component = await render( const component = await render(
<NftEntity <NftEntity
hash={ hash } hash={ hash }
id={ 1794350723452223 } id="1794350723452223"
/>, />,
); );
...@@ -52,7 +52,7 @@ test('customization', async({ render }) => { ...@@ -52,7 +52,7 @@ test('customization', async({ render }) => {
const component = await render( const component = await render(
<NftEntity <NftEntity
hash={ hash } hash={ hash }
id={ 1042 } id="1042"
p={ 3 } p={ 3 }
borderWidth="1px" borderWidth="1px"
borderColor="blue.700" borderColor="blue.700"
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -7,13 +7,11 @@ import { route } from 'nextjs-routes'; ...@@ -7,13 +7,11 @@ import { route } from 'nextjs-routes';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
const Container = EntityBase.Container; import { distributeEntityProps } from '../base/utils';
type IconProps = Pick<EntityProps, 'isLoading' | 'noIcon' | 'iconSize'> & { const Container = EntityBase.Container;
name?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => { const Icon = (props: EntityBase.IconBaseProps) => {
if (props.noIcon) { if (props.noIcon) {
return null; return null;
} }
...@@ -21,7 +19,7 @@ const Icon = (props: IconProps) => { ...@@ -21,7 +19,7 @@ const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
iconSize={ props.iconSize ?? 'lg' } size={ props.size ?? 'lg' }
name={ props.name ?? 'nft_shield' } name={ props.name ?? 'nft_shield' }
/> />
); );
...@@ -59,20 +57,19 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -59,20 +57,19 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
} }
const NftEntity = (props: EntityProps) => { const NftEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className } w="100%"> <Container w="100%" { ...partsProps.container }>
<Icon { ...partsProps }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
</Container> </Container>
); );
}; };
export default React.memo(chakra(NftEntity)); export default React.memo(chakra<As, EntityProps>(NftEntity));
export { export {
Container, Container,
......
...@@ -6,7 +6,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -6,7 +6,7 @@ import { test, expect } from 'playwright/lib';
import TokenEntity from './TokenEntity'; import TokenEntity from './TokenEntity';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
test.use({ viewport: { width: 300, height: 100 } }); test.use({ viewport: { width: 300, height: 100 } });
...@@ -16,7 +16,7 @@ test.describe('icon size', () => { ...@@ -16,7 +16,7 @@ test.describe('icon size', () => {
const component = await render( const component = await render(
<TokenEntity <TokenEntity
token={ tokenMock.tokenInfo } token={ tokenMock.tokenInfo }
iconSize={ size } icon={{ size }}
/>, />,
); );
...@@ -37,6 +37,7 @@ test('with logo, long name and symbol', async({ page, render }) => { ...@@ -37,6 +37,7 @@ test('with logo, long name and symbol', async({ page, render }) => {
await render( await render(
<TokenEntity <TokenEntity
token={{ token={{
type: 'ERC-20',
name: 'This token is the best token ever', name: 'This token is the best token ever',
symbol: 'DUCK DUCK DUCK', symbol: 'DUCK DUCK DUCK',
address: tokenMock.tokenInfo.address, address: tokenMock.tokenInfo.address,
......
import type { ChakraProps } from '@chakra-ui/react'; import type { As } from '@chakra-ui/react';
import { Image, Skeleton, chakra } from '@chakra-ui/react'; import { Image, Skeleton, chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
...@@ -11,7 +10,7 @@ import * as EntityBase from 'ui/shared/entities/base/components'; ...@@ -11,7 +10,7 @@ import * as EntityBase from 'ui/shared/entities/base/components';
import TokenLogoPlaceholder from 'ui/shared/TokenLogoPlaceholder'; import TokenLogoPlaceholder from 'ui/shared/TokenLogoPlaceholder';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip'; import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
import { getIconProps } from '../base/utils'; import { distributeEntityProps, getIconProps } from '../base/utils';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'token'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'token'>;
...@@ -28,10 +27,7 @@ const Link = chakra((props: LinkProps) => { ...@@ -28,10 +27,7 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Pick<EntityProps, 'token' | 'isLoading' | 'iconSize' | 'noIcon' | 'className'> & { type IconProps = Pick<EntityProps, 'token' | 'className'> & EntityBase.IconBaseProps;
marginRight?: ChakraProps['marginRight'];
boxSize?: ChakraProps['boxSize'];
};
const Icon = (props: IconProps) => { const Icon = (props: IconProps) => {
if (props.noIcon) { if (props.noIcon) {
...@@ -40,7 +36,7 @@ const Icon = (props: IconProps) => { ...@@ -40,7 +36,7 @@ const Icon = (props: IconProps) => {
const styles = { const styles = {
marginRight: props.marginRight ?? 2, marginRight: props.marginRight ?? 2,
boxSize: props.boxSize ?? getIconProps(props.iconSize).boxSize, boxSize: props.boxSize ?? getIconProps(props.size).boxSize,
borderRadius: 'base', borderRadius: 'base',
flexShrink: 0, flexShrink: 0,
}; };
...@@ -143,22 +139,21 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -143,22 +139,21 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
} }
const TokenEntity = (props: EntityProps) => { const TokenEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className } w="100%"> <Container w="100%" { ...partsProps.container }>
<Icon { ...partsProps }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
<Symbol { ...partsProps }/> <Symbol { ...partsProps.symbol }/>
<Copy { ...partsProps }/> <Copy { ...partsProps.copy }/>
</Container> </Container>
); );
}; };
export default React.memo(chakra(TokenEntity)); export default React.memo(chakra<As, EntityProps>(TokenEntity));
export { export {
Container, Container,
......
...@@ -5,7 +5,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -5,7 +5,7 @@ import { test, expect } from 'playwright/lib';
import TxEntity from './TxEntity'; import TxEntity from './TxEntity';
const hash = '0x376db52955d5bce114d0ccea2dcf22289b4eae1b86bcae5a59bb5fdbfef48899'; const hash = '0x376db52955d5bce114d0ccea2dcf22289b4eae1b86bcae5a59bb5fdbfef48899';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
test.use({ viewport: { width: 180, height: 30 } }); test.use({ viewport: { width: 180, height: 30 } });
...@@ -15,7 +15,7 @@ test.describe('icon size', () => { ...@@ -15,7 +15,7 @@ test.describe('icon size', () => {
const component = await render( const component = await render(
<TxEntity <TxEntity
hash={ hash } hash={ hash }
iconSize={ size } icon={{ size }}
/>, />,
); );
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import { distributeEntityProps } from '../base/utils';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>;
const Link = chakra((props: LinkProps) => { const Link = chakra((props: LinkProps) => {
...@@ -21,11 +23,7 @@ const Link = chakra((props: LinkProps) => { ...@@ -21,11 +23,7 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & { const Icon = (props: EntityBase.IconBaseProps) => {
name?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
...@@ -66,21 +64,20 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -66,21 +64,20 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
} }
const TxEntity = (props: EntityProps) => { const TxEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className }> <Container { ...partsProps.container }>
<Icon { ...partsProps } name={ props.iconName } color={ props.iconColor }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
<Copy { ...partsProps }/> <Copy { ...partsProps.copy }/>
</Container> </Container>
); );
}; };
export default React.memo(chakra(TxEntity)); export default React.memo(chakra<As, EntityProps>(TxEntity));
export { export {
Container, Container,
......
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -11,26 +10,16 @@ import * as TxEntity from './TxEntity'; ...@@ -11,26 +10,16 @@ import * as TxEntity from './TxEntity';
const rollupFeature = config.features.rollup; const rollupFeature = config.features.rollup;
const TxEntityL1 = (props: TxEntity.EntityProps) => { const TxEntityL1 = (props: TxEntity.EntityProps) => {
const partsProps = _omit(props, [ 'className', 'onClick' ]);
const linkProps = _omit(props, [ 'className' ]);
if (!rollupFeature.isEnabled) { if (!rollupFeature.isEnabled) {
return null; return null;
} }
return ( const defaultHref = rollupFeature.L1BaseUrl + route({
<TxEntity.Container className={ props.className }> pathname: '/tx/[hash]',
<TxEntity.Icon { ...partsProps }/> query: { hash: props.hash },
<TxEntity.Link });
{ ...linkProps }
isExternal return <TxEntity.default { ...props } href={ props.href ?? defaultHref } isExternal/>;
href={ rollupFeature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: props.hash } }) }
>
<TxEntity.Content { ...partsProps }/>
</TxEntity.Link>
<TxEntity.Copy { ...partsProps }/>
</TxEntity.Container>
);
}; };
export default chakra(TxEntityL1); export default chakra(TxEntityL1);
...@@ -5,7 +5,7 @@ import { test, expect } from 'playwright/lib'; ...@@ -5,7 +5,7 @@ import { test, expect } from 'playwright/lib';
import UserOpEntity from './UserOpEntity'; import UserOpEntity from './UserOpEntity';
const hash = '0x376db52955d5bce114d0ccea2dcf22289b4eae1b86bcae5a59bb5fdbfef48899'; const hash = '0x376db52955d5bce114d0ccea2dcf22289b4eae1b86bcae5a59bb5fdbfef48899';
const iconSizes = [ 'md', 'lg' ]; const iconSizes = [ 'md', 'lg' ] as const;
test.use({ viewport: { width: 180, height: 30 } }); test.use({ viewport: { width: 180, height: 30 } });
...@@ -15,7 +15,7 @@ test.describe('icon size', () => { ...@@ -15,7 +15,7 @@ test.describe('icon size', () => {
const component = await render( const component = await render(
<UserOpEntity <UserOpEntity
hash={ hash } hash={ hash }
iconSize={ size } icon={{ size }}
/>, />,
); );
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import * as EntityBase from 'ui/shared/entities/base/components'; import * as EntityBase from 'ui/shared/entities/base/components';
import { distributeEntityProps } from '../base/utils';
type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>; type LinkProps = EntityBase.LinkBaseProps & Pick<EntityProps, 'hash'>;
const Link = chakra((props: LinkProps) => { const Link = chakra((props: LinkProps) => {
...@@ -21,11 +23,7 @@ const Link = chakra((props: LinkProps) => { ...@@ -21,11 +23,7 @@ const Link = chakra((props: LinkProps) => {
); );
}); });
type IconProps = Omit<EntityBase.IconBaseProps, 'name'> & { const Icon = (props: EntityBase.IconBaseProps) => {
name?: EntityBase.IconBaseProps['name'];
};
const Icon = (props: IconProps) => {
return ( return (
<EntityBase.Icon <EntityBase.Icon
{ ...props } { ...props }
...@@ -65,21 +63,20 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -65,21 +63,20 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
} }
const UserOpEntity = (props: EntityProps) => { const UserOpEntity = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]); const partsProps = distributeEntityProps(props);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return ( return (
<Container className={ props.className }> <Container { ...partsProps.container }>
<Icon { ...partsProps }/> <Icon { ...partsProps.icon }/>
<Link { ...linkProps }> <Link { ...partsProps.link }>
<Content { ...partsProps }/> <Content { ...partsProps.content }/>
</Link> </Link>
<Copy { ...partsProps }/> <Copy { ...partsProps.copy }/>
</Container> </Container>
); );
}; };
export default React.memo(chakra(UserOpEntity)); export default React.memo(chakra<As, EntityProps>(UserOpEntity));
export { export {
Container, Container,
......
...@@ -33,7 +33,7 @@ const Row = ({ name, type, indexed, value, isLoading }: ArrayElement<DecodedInpu ...@@ -33,7 +33,7 @@ const Row = ({ name, type, indexed, value, isLoading }: ArrayElement<DecodedInpu
if (type === 'address' && typeof value === 'string') { if (type === 'address' && typeof value === 'string') {
return ( return (
<AddressEntity <AddressEntity
address={{ hash: value, name: '', implementation_name: null, is_contract: false, is_verified: false }} address={{ hash: value, name: '' }}
isLoading={ isLoading } isLoading={ isLoading }
/> />
); );
......
...@@ -53,7 +53,7 @@ const LogItem = ({ address, index, topics, data, decoded, type, tx_hash: txHash, ...@@ -53,7 +53,7 @@ const LogItem = ({ address, index, topics, data, decoded, type, tx_hash: txHash,
) } ) }
{ hasTxInfo ? <RowHeader isLoading={ isLoading }>Transaction</RowHeader> : <RowHeader isLoading={ isLoading }>Address</RowHeader> } { hasTxInfo ? <RowHeader isLoading={ isLoading }>Transaction</RowHeader> : <RowHeader isLoading={ isLoading }>Address</RowHeader> }
<GridItem display="flex" alignItems="center"> <GridItem display="flex" alignItems="center">
{ type === 'address' ? ( { type === 'address' && txHash ? (
<TxEntity <TxEntity
hash={ txHash } hash={ txHash }
isLoading={ isLoading } isLoading={ isLoading }
......
...@@ -51,7 +51,7 @@ const LogTopic = ({ hex, index, isLoading }: Props) => { ...@@ -51,7 +51,7 @@ const LogTopic = ({ hex, index, isLoading }: Props) => {
case 'address': { case 'address': {
return ( return (
<AddressEntity <AddressEntity
address={{ hash: value, name: '', implementation_name: null, is_contract: false, is_verified: false }} address={{ hash: value, name: '' }}
isLoading={ isLoading } isLoading={ isLoading }
/> />
); );
......
...@@ -56,6 +56,7 @@ const TxInterpretationElementByType = ( ...@@ -56,6 +56,7 @@ const TxInterpretationElementByType = (
<chakra.span display="inline-block" verticalAlign="top" _notFirst={{ marginLeft: 1 }}> <chakra.span display="inline-block" verticalAlign="top" _notFirst={{ marginLeft: 1 }}>
<AddressEntity <AddressEntity
address={ addressDataMap?.[value.hash] || value } address={ addressDataMap?.[value.hash] || value }
icon={{ marginRight: 1 }}
truncation="constant" truncation="constant"
onClick={ onAddressClick } onClick={ onAddressClick }
whiteSpace="initial" whiteSpace="initial"
...@@ -68,6 +69,7 @@ const TxInterpretationElementByType = ( ...@@ -68,6 +69,7 @@ const TxInterpretationElementByType = (
<chakra.span display="inline-block" verticalAlign="top" _notFirst={{ marginLeft: 1 }}> <chakra.span display="inline-block" verticalAlign="top" _notFirst={{ marginLeft: 1 }}>
<TokenEntity <TokenEntity
token={ value } token={ value }
icon={{ marginRight: 1 }}
onlySymbol onlySymbol
noCopy noCopy
width="fit-content" width="fit-content"
...@@ -83,7 +85,8 @@ const TxInterpretationElementByType = ( ...@@ -83,7 +85,8 @@ const TxInterpretationElementByType = (
return ( return (
<chakra.span display="inline-block" verticalAlign="top" _notFirst={{ marginLeft: 1 }}> <chakra.span display="inline-block" verticalAlign="top" _notFirst={{ marginLeft: 1 }}>
<EnsEntity <EnsEntity
name={ value } domain={ value }
icon={{ marginRight: 1 }}
width="fit-content" width="fit-content"
_notFirst={{ marginLeft: 1 }} _notFirst={{ marginLeft: 1 }}
whiteSpace="initial" whiteSpace="initial"
...@@ -146,7 +149,7 @@ const TxInterpretation = ({ summary, isLoading, addressDataMap, className }: Pro ...@@ -146,7 +149,7 @@ const TxInterpretation = ({ summary, isLoading, addressDataMap, className }: Pro
return ( return (
<Skeleton isLoaded={ !isLoading } className={ className } fontWeight={ 500 } whiteSpace="pre-wrap" > <Skeleton isLoaded={ !isLoading } className={ className } fontWeight={ 500 } whiteSpace="pre-wrap" >
<Tooltip label="Transaction summary"> <Tooltip label="Transaction summary">
<IconSvg name="lightning" boxSize={ 5 } color="text_secondary" mr={ 2 } verticalAlign="text-top"/> <IconSvg name="lightning" boxSize={ 5 } color="text_secondary" mr={ 1 } verticalAlign="text-top"/>
</Tooltip> </Tooltip>
{ chunks.map((chunk, index) => { { chunks.map((chunk, index) => {
return ( return (
......
...@@ -68,28 +68,30 @@ const WalletMenuContent = ({ address, ensDomainName, disconnect, isAutoConnectDi ...@@ -68,28 +68,30 @@ const WalletMenuContent = ({ address, ensDomainName, disconnect, isAutoConnectDi
> >
Your wallet is used to interact with apps and contracts in the explorer. Your wallet is used to interact with apps and contracts in the explorer.
</Text> </Text>
<Flex alignItems="center" mb={ 6 }> { address && (
<AddressEntity <Flex alignItems="center" mb={ 6 }>
address={{ hash: address, ens_domain_name: ensDomainName }} <AddressEntity
noTooltip address={{ hash: address, ens_domain_name: ensDomainName }}
truncation="dynamic" noTooltip
fontSize="sm" truncation="dynamic"
fontWeight={ 700 } fontSize="sm"
color="text" fontWeight={ 700 }
onClick={ onAddressClick } color="text"
flex={ 1 } onClick={ onAddressClick }
/> flex={ 1 }
<IconButton />
aria-label="open wallet" <IconButton
icon={ <IconSvg name="gear_slim" boxSize={ 5 }/> } aria-label="open wallet"
variant="simple" icon={ <IconSvg name="gear_slim" boxSize={ 5 }/> }
h="20px" variant="simple"
w="20px" h="20px"
ml={ 1 } w="20px"
onClick={ handleOpenWeb3Modal } ml={ 1 }
isLoading={ isModalOpening } onClick={ handleOpenWeb3Modal }
/> isLoading={ isModalOpening }
</Flex> />
</Flex>
) }
<Button size="sm" width="full" variant="outline" onClick={ disconnect }> <Button size="sm" width="full" variant="outline" onClick={ disconnect }>
Disconnect Disconnect
</Button> </Button>
......
...@@ -113,13 +113,15 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => { ...@@ -113,13 +113,15 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
const secondRow = ( const secondRow = (
<Flex alignItems="center" w="100%" minW={ 0 } columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}> <Flex alignItems="center" w="100%" minW={ 0 } columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}>
<AddressEntity { addressQuery.data && (
address={{ ...addressQuery.data, name: '' }} <AddressEntity
isLoading={ isLoading } address={{ ...addressQuery.data, name: '' }}
fontFamily="heading" isLoading={ isLoading }
fontSize="lg" fontFamily="heading"
fontWeight={ 500 } fontSize="lg"
/> fontWeight={ 500 }
/>
) }
{ !isLoading && tokenQuery.data && <AddressAddToWallet token={ tokenQuery.data } variant="button"/> } { !isLoading && tokenQuery.data && <AddressAddToWallet token={ tokenQuery.data } variant="button"/> }
<AddressQrCode address={ addressQuery.data } isLoading={ isLoading }/> <AddressQrCode address={ addressQuery.data } isLoading={ isLoading }/>
<AccountActionsMenu isLoading={ isLoading }/> <AccountActionsMenu isLoading={ isLoading }/>
...@@ -139,7 +141,7 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => { ...@@ -139,7 +141,7 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
<TokenEntity.Icon <TokenEntity.Icon
token={ tokenQuery.data } token={ tokenQuery.data }
isLoading={ tokenQuery.isPlaceholderData } isLoading={ tokenQuery.isPlaceholderData }
iconSize="lg" size="lg"
/> />
) : null } ) : null }
contentAfter={ contentAfter } contentAfter={ contentAfter }
......
...@@ -89,18 +89,20 @@ const TokenInstancePageTitle = ({ isLoading, token, instance, hash }: Props) => ...@@ -89,18 +89,20 @@ const TokenInstancePageTitle = ({ isLoading, token, instance, hash }: Props) =>
const titleSecondRow = ( const titleSecondRow = (
<Flex alignItems="center" w="100%" minW={ 0 } columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}> <Flex alignItems="center" w="100%" minW={ 0 } columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}>
<TokenEntity { token && (
token={ token } <TokenEntity
isLoading={ isLoading } token={ token }
noSymbol isLoading={ isLoading }
noCopy noSymbol
jointSymbol noCopy
fontFamily="heading" jointSymbol
fontSize="lg" fontFamily="heading"
fontWeight={ 500 } fontSize="lg"
w="auto" fontWeight={ 500 }
maxW="700px" w="auto"
/> maxW="700px"
/>
) }
{ !isLoading && <AddressAddToWallet token={ token } variant="button"/> } { !isLoading && <AddressAddToWallet token={ token } variant="button"/> }
<AddressQrCode address={ address } isLoading={ isLoading }/> <AddressQrCode address={ address } isLoading={ isLoading }/>
<AccountActionsMenu isLoading={ isLoading } showUpdateMetadataItem={ Boolean(instance?.metadata) }/> <AccountActionsMenu isLoading={ isLoading } showUpdateMetadataItem={ Boolean(instance?.metadata) }/>
......
...@@ -47,16 +47,20 @@ const TxDetailsWrapped = ({ data }: Props) => { ...@@ -47,16 +47,20 @@ const TxDetailsWrapped = ({ data }: Props) => {
<DetailsInfoItemDivider/> <DetailsInfoItemDivider/>
<DetailsInfoItem.Label { data.to && (
hint="Address (external or contract) receiving the transaction" <>
> <DetailsInfoItem.Label
{ data.to?.is_contract ? 'Interacted with contract' : 'To' } hint="Address (external or contract) receiving the transaction"
</DetailsInfoItem.Label> >
<DetailsInfoItem.Value> { data.to.is_contract ? 'Interacted with contract' : 'To' }
<Flex flexWrap="nowrap" alignItems="center" maxW="100%"> </DetailsInfoItem.Label>
<AddressEntity address={ data.to }/> <DetailsInfoItem.Value>
</Flex> <Flex flexWrap="nowrap" alignItems="center" maxW="100%">
</DetailsInfoItem.Value> <AddressEntity address={ data.to }/>
</Flex>
</DetailsInfoItem.Value>
</>
) }
<DetailsInfoItemDivider/> <DetailsInfoItemDivider/>
......
...@@ -113,11 +113,12 @@ test.describe('blockscout provider', () => { ...@@ -113,11 +113,12 @@ test.describe('blockscout provider', () => {
test('no interpretation, has method called', async({ render, mockApiResponse }) => { test('no interpretation, has method called', async({ render, mockApiResponse }) => {
// the action button should not render if there is no interpretation // the action button should not render if there is no interpretation
const newTxQuery = { ...txQuery, data: txMock.withRecipientContract } as TxQuery;
const metadataResponse = generateAddressMetadataResponse(protocolTagWithMeta); const metadataResponse = generateAddressMetadataResponse(protocolTagWithMeta);
await mockApiResponse('address_metadata_info', metadataResponse, { queryParams: addressMetadataQueryParams }); await mockApiResponse('address_metadata_info', metadataResponse, { queryParams: addressMetadataQueryParams });
await mockApiResponse('tx_interpretation', { data: { summaries: [] } }, { pathParams: { hash } }); await mockApiResponse('tx_interpretation', { data: { summaries: [] } }, { pathParams: { hash } });
const component = await render(<TxSubHeading hash={ hash } hasTag={ false } txQuery={ txQuery }/>);
const component = await render(<TxSubHeading hash={ hash } hasTag={ false } txQuery={ newTxQuery }/>);
await expect(component).toHaveScreenshot(); await expect(component).toHaveScreenshot();
}); });
......
...@@ -19,7 +19,7 @@ import { createNovesSummaryObject } from './assetFlows/utils/createNovesSummaryO ...@@ -19,7 +19,7 @@ import { createNovesSummaryObject } from './assetFlows/utils/createNovesSummaryO
import type { TxQuery } from './useTxQuery'; import type { TxQuery } from './useTxQuery';
type Props = { type Props = {
hash?: string; hash: string;
hasTag: boolean; hasTag: boolean;
txQuery: TxQuery; txQuery: TxQuery;
} }
......
...@@ -25,9 +25,11 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => { ...@@ -25,9 +25,11 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
const symbol = action.nft?.symbol || action.token?.symbol; const symbol = action.nft?.symbol || action.token?.symbol;
const token = { const token = {
name: name, name: name || '',
symbol: symbol?.toLowerCase() === name?.toLowerCase() ? undefined : symbol, symbol: (symbol?.toLowerCase() === name?.toLowerCase() ? undefined : symbol) || '',
address: action.nft?.address || action.token?.address, address: action.nft?.address || action.token?.address || '',
icon_url: '',
type: action.nft ? 'ERC-721' as const : 'ERC-20' as const,
}; };
return token; return token;
......
...@@ -41,14 +41,14 @@ const TxDetailsAction = ({ action }: Props) => { ...@@ -41,14 +41,14 @@ const TxDetailsAction = ({ action }: Props) => {
const token0 = { const token0 = {
address: data.symbol0 === 'Ether' ? '' : data.address0, address: data.symbol0 === 'Ether' ? '' : data.address0,
name: data.symbol0 === 'Ether' ? config.chain.currency.symbol || null : data.symbol0, name: data.symbol0 === 'Ether' ? config.chain.currency.symbol || null : data.symbol0,
type: 'ERC-20', type: 'ERC-20' as const,
symbol: null, symbol: null,
icon_url: null, icon_url: null,
}; };
const token1 = { const token1 = {
address: data.symbol1 === 'Ether' ? '' : data.address1, address: data.symbol1 === 'Ether' ? '' : data.address1,
name: data.symbol1 === 'Ether' ? config.chain.currency.symbol || null : data.symbol1, name: data.symbol1 === 'Ether' ? config.chain.currency.symbol || null : data.symbol1,
type: 'ERC-20', type: 'ERC-20' as const,
symbol: null, symbol: null,
icon_url: null, icon_url: null,
}; };
...@@ -99,7 +99,7 @@ const TxDetailsAction = ({ action }: Props) => { ...@@ -99,7 +99,7 @@ const TxDetailsAction = ({ action }: Props) => {
const token = { const token = {
address: data.address, address: data.address,
name: data.name, name: data.name,
type: 'ERC-20', type: 'ERC-20' as const,
symbol: null, symbol: null,
icon_url: null, icon_url: null,
}; };
...@@ -133,7 +133,7 @@ const TxDetailsAction = ({ action }: Props) => { ...@@ -133,7 +133,7 @@ const TxDetailsAction = ({ action }: Props) => {
<Flex key={ data.address + id } whiteSpace="pre-wrap" columnGap={ 2 }> <Flex key={ data.address + id } whiteSpace="pre-wrap" columnGap={ 2 }>
<chakra.span flexShrink={ 0 }>1</chakra.span> <chakra.span flexShrink={ 0 }>1</chakra.span>
<chakra.span color="text_secondary" flexShrink={ 0 }>of token ID</chakra.span> <chakra.span color="text_secondary" flexShrink={ 0 }>of token ID</chakra.span>
<NftEntity hash={ data.address } id={ id } w="min-content" iconSize="md"/> <NftEntity hash={ data.address } id={ id } w="min-content" icon={{ size: 'md' }}/>
</Flex> </Flex>
); );
}) })
......
...@@ -54,7 +54,9 @@ const TxsListItem = ({ tx, isLoading, showBlockInfo, currentAddress, enableTimeI ...@@ -54,7 +54,9 @@ const TxsListItem = ({ tx, isLoading, showBlockInfo, currentAddress, enableTimeI
hash={ tx.hash } hash={ tx.hash }
truncation="constant_long" truncation="constant_long"
fontWeight="700" fontWeight="700"
iconName={ tx.tx_types.includes('blob_transaction') ? 'blob' : undefined } icon={{
name: tx.tx_types.includes('blob_transaction') ? 'blob' : undefined,
}}
/> />
<TimeAgoWithTooltip <TimeAgoWithTooltip
timestamp={ tx.timestamp } timestamp={ tx.timestamp }
......
...@@ -198,7 +198,7 @@ const UserOpDetails = ({ query }: Props) => { ...@@ -198,7 +198,7 @@ const UserOpDetails = ({ query }: Props) => {
Block Block
</DetailsInfoItem.Label> </DetailsInfoItem.Label>
<DetailsInfoItem.Value> <DetailsInfoItem.Value>
<BlockEntity number={ data.block_number } isLoading={ isPlaceholderData }/> <BlockEntity number={ Number(data.block_number) } isLoading={ isPlaceholderData }/>
</DetailsInfoItem.Value> </DetailsInfoItem.Value>
<DetailsInfoItem.Label <DetailsInfoItem.Label
......
...@@ -13,7 +13,7 @@ import UserOpEntity from 'ui/shared/entities/userOp/UserOpEntity'; ...@@ -13,7 +13,7 @@ import UserOpEntity from 'ui/shared/entities/userOp/UserOpEntity';
import TxInterpretation from 'ui/shared/tx/interpretation/TxInterpretation'; import TxInterpretation from 'ui/shared/tx/interpretation/TxInterpretation';
type Props = { type Props = {
hash?: string; hash: string;
// userOpQuery: UseQueryResult<UserOp, ResourceError<unknown>>; // userOpQuery: UseQueryResult<UserOp, ResourceError<unknown>>;
} }
......
...@@ -74,7 +74,7 @@ const UserOpsListItem = ({ item, isLoading, showTx, showSender }: Props) => { ...@@ -74,7 +74,7 @@ const UserOpsListItem = ({ item, isLoading, showTx, showSender }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>Block</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Block</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<BlockEntity <BlockEntity
number={ item.block_number } number={ Number(item.block_number) }
isLoading={ isLoading } isLoading={ isLoading }
fontSize="sm" fontSize="sm"
lineHeight={ 5 } lineHeight={ 5 }
......
...@@ -57,7 +57,7 @@ const UserOpsTableItem = ({ item, isLoading, showTx, showSender }: Props) => { ...@@ -57,7 +57,7 @@ const UserOpsTableItem = ({ item, isLoading, showTx, showSender }: Props) => {
) } ) }
<Td verticalAlign="middle"> <Td verticalAlign="middle">
<BlockEntity <BlockEntity
number={ item.block_number } number={ Number(item.block_number) }
isLoading={ isLoading } isLoading={ isLoading }
fontSize="sm" fontSize="sm"
lineHeight={ 5 } lineHeight={ 5 }
......
...@@ -48,6 +48,7 @@ const VerifiedAddressesListItem = ({ item, application, onAdd, onEdit, isLoading ...@@ -48,6 +48,7 @@ const VerifiedAddressesListItem = ({ item, application, onAdd, onEdit, isLoading
} }
const token = { const token = {
type: 'ERC-20' as const,
icon_url: application.iconUrl, icon_url: application.iconUrl,
address: application.tokenAddress, address: application.tokenAddress,
name: item.metadata.tokenName, name: item.metadata.tokenName,
......
...@@ -48,6 +48,7 @@ const VerifiedAddressesTableItem = ({ item, application, onAdd, onEdit, isLoadin ...@@ -48,6 +48,7 @@ const VerifiedAddressesTableItem = ({ item, application, onAdd, onEdit, isLoadin
} }
const token = { const token = {
type: 'ERC-20' as const,
icon_url: application.iconUrl, icon_url: application.iconUrl,
address: application.tokenAddress, address: application.tokenAddress,
name: item.metadata.tokenName, name: item.metadata.tokenName,
......
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