Commit cc4885d8 authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

Merge pull request #855 from blockscout/tx-upd

tx: testnet warning and method badge
parents 6015bb72 b2f0cb6b
......@@ -167,3 +167,28 @@ l2Test('l2', async({ mount, page }) => {
await expect(component).toHaveScreenshot();
});
const mainnetTest = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_IS_TESTNET', value: 'false' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
]) as any,
});
mainnetTest('without testnet warning', async({ mount, page }) => {
await page.route(API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify(txMock.l2tx),
}));
const component = await mount(
<TestApp>
<TxDetails/>
</TestApp>,
{ hooksConfig },
);
await insertAdPlaceholder(page);
await expect(component).toHaveScreenshot();
});
......@@ -6,12 +6,12 @@ import {
Icon as ChakraIcon,
Link,
Spinner,
Tag,
Flex,
Tooltip,
chakra,
useColorModeValue,
Skeleton,
Alert,
} from '@chakra-ui/react';
import BigNumber from 'bignumber.js';
import { route } from 'nextjs-routes';
......@@ -30,6 +30,7 @@ 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 CurrencyValue from 'ui/shared/CurrencyValue';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
......@@ -120,350 +121,363 @@ const TxDetails = () => {
);
return (
<Grid columnGap={ 8 } rowGap={{ base: 3, lg: 3 }} templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }}>
{ socketStatus && (
<GridItem colSpan={{ base: undefined, lg: 2 }} mb={ 2 }>
<TxSocketAlert status={ socketStatus }/>
</GridItem>
) }
<DetailsInfoItem
title="Transaction hash"
hint="Unique character string (TxID) assigned to every verified transaction"
flexWrap="nowrap"
isLoading={ isPlaceholderData }
>
{ data.status === null && <Spinner mr={ 2 } size="sm" flexShrink={ 0 }/> }
<Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
<HashStringShortenDynamic hash={ data.hash }/>
</Skeleton>
<CopyToClipboard text={ data.hash } isLoading={ isPlaceholderData }/>
{ /* api doesn't support navigation between certain address account tx */ }
{ /* <PrevNext ml={ 7 }/> */ }
</DetailsInfoItem>
<DetailsInfoItem
title="Status"
hint="Current transaction state: Success, Failed (Error), or Pending (In Process)"
isLoading={ isPlaceholderData }
>
<TxStatus status={ data.status } errorText={ data.status === 'error' ? data.result : undefined } isLoading={ isPlaceholderData }/>
</DetailsInfoItem>
{ data.revert_reason && (
<>
{ appConfig.network.isTestnet && <Alert status="warning" mb={ 6 }>This is a { appConfig.network.name } testnet transaction only</Alert> }
<Grid columnGap={ 8 } rowGap={{ base: 3, lg: 3 }} templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }}>
{ socketStatus && (
<GridItem colSpan={{ base: undefined, lg: 2 }} mb={ 2 }>
<TxSocketAlert status={ socketStatus }/>
</GridItem>
) }
<DetailsInfoItem
title="Revert reason"
hint="The revert reason of the transaction"
title="Transaction hash"
hint="Unique character string (TxID) assigned to every verified transaction"
flexWrap="nowrap"
isLoading={ isPlaceholderData }
>
<TxRevertReason { ...data.revert_reason }/>
{ data.status === null && <Spinner mr={ 2 } size="sm" flexShrink={ 0 }/> }
<Skeleton isLoaded={ !isPlaceholderData } overflow="hidden">
<HashStringShortenDynamic hash={ data.hash }/>
</Skeleton>
<CopyToClipboard text={ data.hash } isLoading={ isPlaceholderData }/>
{ /* api doesn't support navigation between certain address account tx */ }
{ /* <PrevNext ml={ 7 }/> */ }
</DetailsInfoItem>
) }
<DetailsInfoItem
title="Block"
hint="Block number containing the transaction"
isLoading={ isPlaceholderData }
>
{ data.block === null ?
<Text>Pending</Text> : (
<Skeleton isLoaded={ !isPlaceholderData }>
<LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block) } }) }>
{ data.block }
</LinkInternal>
</Skeleton>
<DetailsInfoItem
title="Status and method"
hint="Current transaction state: Success, Failed (Error), or Pending (In Process)"
isLoading={ isPlaceholderData }
>
<TxStatus status={ data.status } errorText={ data.status === 'error' ? data.result : undefined } isLoading={ isPlaceholderData }/>
{ data.method && (
<Tag colorScheme={ data.method === 'Multicall' ? 'teal' : 'gray' } isLoading={ isPlaceholderData } isTruncated ml={ 3 }>
{ data.method }
</Tag>
) }
{ Boolean(data.confirmations) && (
<>
<TextSeparator color="gray.500"/>
<Skeleton isLoaded={ !isPlaceholderData } color="text_secondary">
<span>{ data.confirmations } Block confirmations</span>
</Skeleton>
</>
</DetailsInfoItem>
{ data.revert_reason && (
<DetailsInfoItem
title="Revert reason"
hint="The revert reason of the transaction"
>
<TxRevertReason { ...data.revert_reason }/>
</DetailsInfoItem>
) }
</DetailsInfoItem>
{ data.timestamp && (
<DetailsInfoItem
title="Timestamp"
hint="Date & time of transaction inclusion, including length of time for confirmation"
title="Block"
hint="Block number containing the transaction"
isLoading={ isPlaceholderData }
>
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
<Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }>{ dayjs(data.timestamp).fromNow() }</Skeleton>
<TextSeparator/>
<Skeleton isLoaded={ !isPlaceholderData } whiteSpace="normal">{ dayjs(data.timestamp).format('LLLL') }</Skeleton>
<TextSeparator color="gray.500"/>
<Skeleton isLoaded={ !isPlaceholderData } color="text_secondary">
<span>{ getConfirmationDuration(data.confirmation_duration) }</span>
</Skeleton>
{ data.block === null ?
<Text>Pending</Text> : (
<Skeleton isLoaded={ !isPlaceholderData }>
<LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block) } }) }>
{ data.block }
</LinkInternal>
</Skeleton>
) }
{ Boolean(data.confirmations) && (
<>
<TextSeparator color="gray.500"/>
<Skeleton isLoaded={ !isPlaceholderData } color="text_secondary">
<span>{ data.confirmations } Block confirmations</span>
</Skeleton>
</>
) }
</DetailsInfoItem>
) }
<DetailsSponsoredItem isLoading={ isPlaceholderData }/>
{ divider }
{ data.timestamp && (
<DetailsInfoItem
title="Timestamp"
hint="Date & time of transaction inclusion, including length of time for confirmation"
isLoading={ isPlaceholderData }
>
<Icon as={ clockIcon } boxSize={ 5 } color="gray.500" isLoading={ isPlaceholderData }/>
<Skeleton isLoaded={ !isPlaceholderData } ml={ 1 }>{ dayjs(data.timestamp).fromNow() }</Skeleton>
<TextSeparator/>
<Skeleton isLoaded={ !isPlaceholderData } whiteSpace="normal">{ dayjs(data.timestamp).format('LLLL') }</Skeleton>
<TextSeparator color="gray.500"/>
<Skeleton isLoaded={ !isPlaceholderData } color="text_secondary">
<span>{ getConfirmationDuration(data.confirmation_duration) }</span>
</Skeleton>
</DetailsInfoItem>
) }
<DetailsSponsoredItem isLoading={ isPlaceholderData }/>
{ actionsExist && (
<>
<TxDetailsActions actions={ data.actions }/>
{ divider }
</>
) }
{ divider }
<DetailsInfoItem
title="From"
hint="Address (external or contract) sending the transaction"
isLoading={ isPlaceholderData }
columnGap={ 3 }
>
<Address>
<AddressIcon address={ data.from } isLoading={ isPlaceholderData }/>
<AddressLink type="address" ml={ 2 } hash={ data.from.hash } isLoading={ isPlaceholderData }/>
<CopyToClipboard text={ data.from.hash } isLoading={ isPlaceholderData }/>
</Address>
{ data.from.name && <Text>{ data.from.name }</Text> }
{ addressFromTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressFromTags }
</Flex>
) }
</DetailsInfoItem>
<DetailsInfoItem
title={ data.to?.is_contract ? 'Interacted with contract' : 'To' }
hint="Address (external or contract) receiving the transaction"
isLoading={ isPlaceholderData }
flexWrap={{ base: 'wrap', lg: 'nowrap' }}
columnGap={ 3 }
>
{ toAddress ? (
{ actionsExist && (
<>
{ data.to && data.to.hash ? (
<Address alignItems="center">
<AddressIcon address={ toAddress } isLoading={ isPlaceholderData }/>
<AddressLink type="address" ml={ 2 } hash={ toAddress.hash } isLoading={ isPlaceholderData }/>
{ executionSuccessBadge }
{ executionFailedBadge }
<CopyToClipboard text={ toAddress.hash } isLoading={ isPlaceholderData }/>
</Address>
) : (
<Flex width={{ base: '100%', lg: 'auto' }} whiteSpace="pre" alignItems="center">
<span>[Contract </span>
<AddressLink type="address" hash={ toAddress.hash }/>
<span> created]</span>
{ executionSuccessBadge }
{ executionFailedBadge }
<CopyToClipboard text={ toAddress.hash }/>
</Flex>
) }
{ toAddress.name && <Text>{ toAddress.name }</Text> }
{ addressToTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressToTags }
</Flex>
) }
<TxDetailsActions actions={ data.actions }/>
{ divider }
</>
) : (
<span>[ Contract creation ]</span>
) }
</DetailsInfoItem>
{ data.token_transfers && <TxDetailsTokenTransfers data={ data.token_transfers } txHash={ data.hash }/> }
{ divider }
<DetailsInfoItem
title="Value"
hint="Value sent in the native token (and USD) if applicable"
isLoading={ isPlaceholderData }
>
<CurrencyValue value={ data.value } currency={ appConfig.network.currency.symbol } exchangeRate={ data.exchange_rate } isLoading={ isPlaceholderData }/>
</DetailsInfoItem>
<DetailsInfoItem
title="Transaction fee"
hint="Total transaction fee"
isLoading={ isPlaceholderData }
>
<CurrencyValue
value={ data.fee.value }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
flexWrap="wrap"
isLoading={ isPlaceholderData }
/>
</DetailsInfoItem>
<DetailsInfoItem
title="Gas price"
hint="Price per unit of gas specified by the sender. Higher gas prices can prioritize transaction inclusion during times of high usage"
isLoading={ isPlaceholderData }
>
<Skeleton isLoaded={ !isPlaceholderData } mr={ 1 }>
{ BigNumber(data.gas_price).dividedBy(WEI).toFixed() } { appConfig.network.currency.symbol }
</Skeleton>
<Skeleton isLoaded={ !isPlaceholderData } color="text_secondary">
<span>({ BigNumber(data.gas_price).dividedBy(WEI_IN_GWEI).toFixed() } Gwei)</span>
</Skeleton>
</DetailsInfoItem>
<DetailsInfoItem
title="Gas usage & limit by txn"
hint="Actual gas amount used by the transaction"
isLoading={ isPlaceholderData }
>
<Skeleton isLoaded={ !isPlaceholderData }>{ BigNumber(data.gas_used || 0).toFormat() }</Skeleton>
<TextSeparator/>
<Skeleton isLoaded={ !isPlaceholderData }>{ BigNumber(data.gas_limit).toFormat() }</Skeleton>
<Utilization ml={ 4 } value={ BigNumber(data.gas_used || 0).dividedBy(BigNumber(data.gas_limit)).toNumber() } isLoading={ isPlaceholderData }/>
</DetailsInfoItem>
{ (data.base_fee_per_gas || data.max_fee_per_gas || data.max_priority_fee_per_gas) && (
<DetailsInfoItem
title="Gas fees (Gwei)"
// eslint-disable-next-line max-len
hint="Base Fee refers to the network Base Fee at the time of the block, while Max Fee & Max Priority Fee refer to the max amount a user is willing to pay for their tx & to give to the miner respectively"
title="From"
hint="Address (external or contract) sending the transaction"
isLoading={ isPlaceholderData }
columnGap={ 3 }
>
{ data.base_fee_per_gas && (
<Skeleton isLoaded={ !isPlaceholderData }>
<Text as="span" fontWeight="500">Base: </Text>
<Text fontWeight="600" as="span">{ BigNumber(data.base_fee_per_gas).dividedBy(WEI_IN_GWEI).toFixed() }</Text>
{ (data.max_fee_per_gas || data.max_priority_fee_per_gas) && <TextSeparator/> }
</Skeleton>
<Address>
<AddressIcon address={ data.from } isLoading={ isPlaceholderData }/>
<AddressLink type="address" ml={ 2 } hash={ data.from.hash } isLoading={ isPlaceholderData }/>
<CopyToClipboard text={ data.from.hash } isLoading={ isPlaceholderData }/>
</Address>
{ data.from.name && <Text>{ data.from.name }</Text> }
{ addressFromTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressFromTags }
</Flex>
) }
{ data.max_fee_per_gas && (
<Box>
<Text as="span" fontWeight="500">Max: </Text>
<Text fontWeight="600" as="span">{ BigNumber(data.max_fee_per_gas).dividedBy(WEI_IN_GWEI).toFixed() }</Text>
{ data.max_priority_fee_per_gas && <TextSeparator/> }
</Box>
) }
{ data.max_priority_fee_per_gas && (
<Box>
<Text as="span" fontWeight="500">Max priority: </Text>
<Text fontWeight="600" as="span">{ BigNumber(data.max_priority_fee_per_gas).dividedBy(WEI_IN_GWEI).toFixed() }</Text>
</Box>
</DetailsInfoItem>
<DetailsInfoItem
title={ data.to?.is_contract ? 'Interacted with contract' : 'To' }
hint="Address (external or contract) receiving the transaction"
isLoading={ isPlaceholderData }
flexWrap={{ base: 'wrap', lg: 'nowrap' }}
columnGap={ 3 }
>
{ toAddress ? (
<>
{ data.to && data.to.hash ? (
<Address alignItems="center">
<AddressIcon address={ toAddress } isLoading={ isPlaceholderData }/>
<AddressLink type="address" ml={ 2 } hash={ toAddress.hash } isLoading={ isPlaceholderData }/>
{ executionSuccessBadge }
{ executionFailedBadge }
<CopyToClipboard text={ toAddress.hash } isLoading={ isPlaceholderData }/>
</Address>
) : (
<Flex width={{ base: '100%', lg: 'auto' }} whiteSpace="pre" alignItems="center">
<span>[Contract </span>
<AddressLink type="address" hash={ toAddress.hash }/>
<span> created]</span>
{ executionSuccessBadge }
{ executionFailedBadge }
<CopyToClipboard text={ toAddress.hash }/>
</Flex>
) }
{ toAddress.name && <Text>{ toAddress.name }</Text> }
{ addressToTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressToTags }
</Flex>
) }
</>
) : (
<span>[ Contract creation ]</span>
) }
</DetailsInfoItem>
) }
{ data.tx_burnt_fee && !appConfig.L2.isL2Network && (
{ data.token_transfers && <TxDetailsTokenTransfers data={ data.token_transfers } txHash={ data.hash }/> }
{ divider }
<DetailsInfoItem
title="Value"
hint="Value sent in the native token (and USD) if applicable"
isLoading={ isPlaceholderData }
>
<CurrencyValue
value={ data.value }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
isLoading={ isPlaceholderData }
/>
</DetailsInfoItem>
<DetailsInfoItem
title="Burnt fees"
hint={ `Amount of ${ appConfig.network.currency.symbol } burned for this transaction. Equals Block Base Fee per Gas * Gas Used` }
title="Transaction fee"
hint="Total transaction fee"
isLoading={ isPlaceholderData }
>
<Icon as={ flameIcon } mr={ 1 } boxSize={ 5 } color="gray.500"/>
<CurrencyValue
value={ String(data.tx_burnt_fee) }
value={ data.fee.value }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
flexWrap="wrap"
isLoading={ isPlaceholderData }
/>
</DetailsInfoItem>
) }
{ appConfig.L2.isL2Network && (
<>
{ data.l1_gas_used && (
<DetailsInfoItem
title="L1 gas used by txn"
hint="L1 gas used by transaction"
isLoading={ isPlaceholderData }
>
<Text>{ BigNumber(data.l1_gas_used).toFormat() }</Text>
</DetailsInfoItem>
) }
{ data.l1_gas_price && (
<DetailsInfoItem
title="L1 gas price"
hint="L1 gas price"
isLoading={ isPlaceholderData }
>
<Text mr={ 1 }>{ BigNumber(data.l1_gas_price).dividedBy(WEI).toFixed() } { appConfig.network.currency.symbol }</Text>
<Text variant="secondary">({ BigNumber(data.l1_gas_price).dividedBy(WEI_IN_GWEI).toFixed() } Gwei)</Text>
</DetailsInfoItem>
) }
{ data.l1_fee && (
<DetailsInfoItem
title="L1 fee"
// eslint-disable-next-line max-len
hint={ `L1 Data Fee which is used to cover the L1 "security" cost from the batch submission mechanism. In combination with L2 execution fee, L1 fee makes the total amount of fees that a transaction pays.` }
isLoading={ isPlaceholderData }
>
<CurrencyValue
value={ data.l1_fee }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
flexWrap="wrap"
/>
</DetailsInfoItem>
) }
{ data.l1_fee_scalar && (
<DetailsInfoItem
title="L1 fee scalar"
hint="A Dynamic overhead (fee scalar) premium, which serves as a buffer in case L1 prices rapidly increase."
isLoading={ isPlaceholderData }
>
<Text>{ data.l1_fee_scalar }</Text>
</DetailsInfoItem>
) }
</>
) }
<GridItem colSpan={{ base: undefined, lg: 2 }}>
<Element name="TxDetails__cutLink">
<Skeleton isLoaded={ !isPlaceholderData } mt={ 6 } display="inline-block">
<Link
display="inline-block"
fontSize="sm"
textDecorationLine="underline"
textDecorationStyle="dashed"
onClick={ handleCutClick }
>
{ isExpanded ? 'Hide details' : 'View details' }
</Link>
<DetailsInfoItem
title="Gas price"
hint="Price per unit of gas specified by the sender. Higher gas prices can prioritize transaction inclusion during times of high usage"
isLoading={ isPlaceholderData }
>
<Skeleton isLoaded={ !isPlaceholderData } mr={ 1 }>
{ BigNumber(data.gas_price).dividedBy(WEI).toFixed() } { appConfig.network.currency.symbol }
</Skeleton>
<Skeleton isLoaded={ !isPlaceholderData } color="text_secondary">
<span>({ BigNumber(data.gas_price).dividedBy(WEI_IN_GWEI).toFixed() } Gwei)</span>
</Skeleton>
</Element>
</GridItem>
{ isExpanded && (
<>
<GridItem colSpan={{ base: undefined, lg: 2 }} mt={{ base: 1, lg: 4 }}/>
</DetailsInfoItem>
<DetailsInfoItem
title="Gas usage & limit by txn"
hint="Actual gas amount used by the transaction"
isLoading={ isPlaceholderData }
>
<Skeleton isLoaded={ !isPlaceholderData }>{ BigNumber(data.gas_used || 0).toFormat() }</Skeleton>
<TextSeparator/>
<Skeleton isLoaded={ !isPlaceholderData }>{ BigNumber(data.gas_limit).toFormat() }</Skeleton>
<Utilization ml={ 4 } value={ BigNumber(data.gas_used || 0).dividedBy(BigNumber(data.gas_limit)).toNumber() } isLoading={ isPlaceholderData }/>
</DetailsInfoItem>
{ (data.base_fee_per_gas || data.max_fee_per_gas || data.max_priority_fee_per_gas) && (
<DetailsInfoItem
title="Other"
hint="Other data related to this transaction"
title="Gas fees (Gwei)"
// eslint-disable-next-line max-len
hint="Base Fee refers to the network Base Fee at the time of the block, while Max Fee & Max Priority Fee refer to the max amount a user is willing to pay for their tx & to give to the miner respectively"
isLoading={ isPlaceholderData }
>
{
[
typeof data.type === 'number' && (
<Box key="type">
<Text as="span" fontWeight="500">Txn type: </Text>
<Text fontWeight="600" as="span">{ data.type }</Text>
{ data.type === 2 && <Text fontWeight="400" as="span" ml={ 1 } variant="secondary">(EIP-1559)</Text> }
</Box>
),
<Box key="nonce">
<Text as="span" fontWeight="500">Nonce: </Text>
<Text fontWeight="600" as="span">{ data.nonce }</Text>
</Box>,
data.position !== null && (
<Box key="position">
<Text as="span" fontWeight="500">Position: </Text>
<Text fontWeight="600" as="span">{ data.position }</Text>
</Box>
),
]
.filter(Boolean)
.map((item, index) => (
<>
{ index !== 0 && <TextSeparator/> }
{ item }
</>
))
}
{ data.base_fee_per_gas && (
<Skeleton isLoaded={ !isPlaceholderData }>
<Text as="span" fontWeight="500">Base: </Text>
<Text fontWeight="600" as="span">{ BigNumber(data.base_fee_per_gas).dividedBy(WEI_IN_GWEI).toFixed() }</Text>
{ (data.max_fee_per_gas || data.max_priority_fee_per_gas) && <TextSeparator/> }
</Skeleton>
) }
{ data.max_fee_per_gas && (
<Box>
<Text as="span" fontWeight="500">Max: </Text>
<Text fontWeight="600" as="span">{ BigNumber(data.max_fee_per_gas).dividedBy(WEI_IN_GWEI).toFixed() }</Text>
{ data.max_priority_fee_per_gas && <TextSeparator/> }
</Box>
) }
{ data.max_priority_fee_per_gas && (
<Box>
<Text as="span" fontWeight="500">Max priority: </Text>
<Text fontWeight="600" as="span">{ BigNumber(data.max_priority_fee_per_gas).dividedBy(WEI_IN_GWEI).toFixed() }</Text>
</Box>
) }
</DetailsInfoItem>
) }
{ data.tx_burnt_fee && !appConfig.L2.isL2Network && (
<DetailsInfoItem
title="Raw input"
hint="Binary data included with the transaction. See logs tab for additional info"
title="Burnt fees"
hint={ `Amount of ${ appConfig.network.currency.symbol } burned for this transaction. Equals Block Base Fee per Gas * Gas Used` }
>
<RawInputData hex={ data.raw_input }/>
<Icon as={ flameIcon } mr={ 1 } boxSize={ 5 } color="gray.500"/>
<CurrencyValue
value={ String(data.tx_burnt_fee) }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
flexWrap="wrap"
/>
</DetailsInfoItem>
{ data.decoded_input && (
) }
{ appConfig.L2.isL2Network && (
<>
{ data.l1_gas_used && (
<DetailsInfoItem
title="L1 gas used by txn"
hint="L1 gas used by transaction"
isLoading={ isPlaceholderData }
>
<Text>{ BigNumber(data.l1_gas_used).toFormat() }</Text>
</DetailsInfoItem>
) }
{ data.l1_gas_price && (
<DetailsInfoItem
title="L1 gas price"
hint="L1 gas price"
isLoading={ isPlaceholderData }
>
<Text mr={ 1 }>{ BigNumber(data.l1_gas_price).dividedBy(WEI).toFixed() } { appConfig.network.currency.symbol }</Text>
<Text variant="secondary">({ BigNumber(data.l1_gas_price).dividedBy(WEI_IN_GWEI).toFixed() } Gwei)</Text>
</DetailsInfoItem>
) }
{ data.l1_fee && (
<DetailsInfoItem
title="L1 fee"
// eslint-disable-next-line max-len
hint={ `L1 Data Fee which is used to cover the L1 "security" cost from the batch submission mechanism. In combination with L2 execution fee, L1 fee makes the total amount of fees that a transaction pays.` }
isLoading={ isPlaceholderData }
>
<CurrencyValue
value={ data.l1_fee }
currency={ appConfig.network.currency.symbol }
exchangeRate={ data.exchange_rate }
flexWrap="wrap"
/>
</DetailsInfoItem>
) }
{ data.l1_fee_scalar && (
<DetailsInfoItem
title="L1 fee scalar"
hint="A Dynamic overhead (fee scalar) premium, which serves as a buffer in case L1 prices rapidly increase."
isLoading={ isPlaceholderData }
>
<Text>{ data.l1_fee_scalar }</Text>
</DetailsInfoItem>
) }
</>
) }
<GridItem colSpan={{ base: undefined, lg: 2 }}>
<Element name="TxDetails__cutLink">
<Skeleton isLoaded={ !isPlaceholderData } mt={ 6 } display="inline-block">
<Link
display="inline-block"
fontSize="sm"
textDecorationLine="underline"
textDecorationStyle="dashed"
onClick={ handleCutClick }
>
{ isExpanded ? 'Hide details' : 'View details' }
</Link>
</Skeleton>
</Element>
</GridItem>
{ isExpanded && (
<>
<GridItem colSpan={{ base: undefined, lg: 2 }} mt={{ base: 1, lg: 4 }}/>
<DetailsInfoItem
title="Decoded input data"
hint="Decoded input data"
title="Other"
hint="Other data related to this transaction"
>
<LogDecodedInputData data={ data.decoded_input }/>
{
[
typeof data.type === 'number' && (
<Box key="type">
<Text as="span" fontWeight="500">Txn type: </Text>
<Text fontWeight="600" as="span">{ data.type }</Text>
{ data.type === 2 && <Text fontWeight="400" as="span" ml={ 1 } variant="secondary">(EIP-1559)</Text> }
</Box>
),
<Box key="nonce">
<Text as="span" fontWeight="500">Nonce: </Text>
<Text fontWeight="600" as="span">{ data.nonce }</Text>
</Box>,
data.position !== null && (
<Box key="position">
<Text as="span" fontWeight="500">Position: </Text>
<Text fontWeight="600" as="span">{ data.position }</Text>
</Box>
),
]
.filter(Boolean)
.map((item, index) => (
<>
{ index !== 0 && <TextSeparator/> }
{ item }
</>
))
}
</DetailsInfoItem>
) }
</>
) }
</Grid>
<DetailsInfoItem
title="Raw input"
hint="Binary data included with the transaction. See logs tab for additional info"
>
<RawInputData hex={ data.raw_input }/>
</DetailsInfoItem>
{ data.decoded_input && (
<DetailsInfoItem
title="Decoded input data"
hint="Decoded input data"
>
<LogDecodedInputData data={ data.decoded_input }/>
</DetailsInfoItem>
) }
</>
) }
</Grid>
</>
);
};
......
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