Commit ca4603fc authored by isstuev's avatar isstuev

review fixes

parent ccbfdff1
...@@ -4,10 +4,13 @@ import { getEnvValue } from '../utils'; ...@@ -4,10 +4,13 @@ import { getEnvValue } from '../utils';
const title = 'Transaction interpretation'; const title = 'Transaction interpretation';
const config: Feature<{ isEnabled: true }> = (() => { const provider = getEnvValue('NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER') || 'none';
if (getEnvValue('NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED') === 'true') {
const config: Feature<{ provider: string }> = (() => {
if (provider !== 'none') {
return Object.freeze({ return Object.freeze({
title, title,
provider,
isEnabled: true, isEnabled: true,
}); });
} }
......
...@@ -42,7 +42,7 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s.blockscout.com ...@@ -42,7 +42,7 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED=true NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
#meta #meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true
...@@ -438,7 +438,7 @@ const schema = yup ...@@ -438,7 +438,7 @@ const schema = yup
return isNoneSchema.isValidSync(data) || isArrayOfWalletsSchema.isValidSync(data); return isNoneSchema.isValidSync(data) || isArrayOfWalletsSchema.isValidSync(data);
}), }),
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET: yup.boolean(), NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET: yup.boolean(),
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED: yup.boolean(), NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER: yup.string().oneOf([ 'blockscout', 'none' ]),
NEXT_PUBLIC_AD_TEXT_PROVIDER: yup.string<AdTextProviders>().oneOf(SUPPORTED_AD_TEXT_PROVIDERS), NEXT_PUBLIC_AD_TEXT_PROVIDER: yup.string<AdTextProviders>().oneOf(SUPPORTED_AD_TEXT_PROVIDERS),
NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE: yup.boolean(), NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE: yup.boolean(),
NEXT_PUBLIC_OG_DESCRIPTION: yup.string(), NEXT_PUBLIC_OG_DESCRIPTION: yup.string(),
......
...@@ -51,7 +51,7 @@ frontend: ...@@ -51,7 +51,7 @@ frontend:
NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg
NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg
NEXT_PUBLIC_API_HOST: eth.blockscout.com NEXT_PUBLIC_API_HOST: eth-goerli.blockscout.com
NEXT_PUBLIC_STATS_API_HOST: https://stats-goerli.k8s-dev.blockscout.com/ NEXT_PUBLIC_STATS_API_HOST: https://stats-goerli.k8s-dev.blockscout.com/
NEXT_PUBLIC_VISUALIZE_API_HOST: http://visualizer-svc.visualizer-testing.svc.cluster.local/ NEXT_PUBLIC_VISUALIZE_API_HOST: http://visualizer-svc.visualizer-testing.svc.cluster.local/
NEXT_PUBLIC_CONTRACT_INFO_API_HOST: https://contracts-info-test.k8s-dev.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST: https://contracts-info-test.k8s-dev.blockscout.com
...@@ -65,7 +65,6 @@ frontend: ...@@ -65,7 +65,6 @@ frontend:
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/eth-goerli.json NEXT_PUBLIC_MARKETPLACE_CONFIG_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace/eth-goerli.json
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']" NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']"
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED: true
NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE: gradient_avatar NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE: gradient_avatar
NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS: "['top_accounts']" NEXT_PUBLIC_VIEWS_ADDRESS_HIDDEN_VIEWS: "['top_accounts']"
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: true NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: true
......
...@@ -476,11 +476,9 @@ This feature is **enabled by default** with the `['metamask']` value. To switch ...@@ -476,11 +476,9 @@ This feature is **enabled by default** with the `['metamask']` value. To switch
### Transaction interpretation ### Transaction interpretation
<!-- Nikita will provide feature description -->
| Variable | Type| Description | Compulsoriness | Default value | Example value | | Variable | Type| Description | Compulsoriness | Default value | Example value |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED | `boolean`| Set to `true` to enable transaction interpretation | - | - | `true` | | NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER | `blockscout` \| `none` | Transaction interpretation provider that displays human readable transaction description | - | `none` | `blockscout` |
&nbsp; &nbsp;
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
| "graphQL" | "graphQL"
| "info" | "info"
| "key" | "key"
| "lightning"
| "link" | "link"
| "lock" | "lock"
| "minus" | "minus"
......
import type { RawTracesResponse } from 'types/api/rawTrace'; import type { RawTracesResponse } from 'types/api/rawTrace';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import type { TxInterpretationResponse } from 'types/api/txInterpretation';
import { ADDRESS_PARAMS } from './addressParams'; import { ADDRESS_PARAMS } from './addressParams';
...@@ -60,56 +59,3 @@ export const TX_ZKEVM_L2: Transaction = { ...@@ -60,56 +59,3 @@ export const TX_ZKEVM_L2: Transaction = {
}; };
export const TX_RAW_TRACE: RawTracesResponse = []; export const TX_RAW_TRACE: RawTracesResponse = [];
export const TX_INTERPRETATION: TxInterpretationResponse = {
data: {
summaries: [
{
summary_template: '{action_type} {source_amount} Ether into {destination_amount} {destination_token}',
summary_template_variables: {
action_type: { type: 'string', value: 'Wrap' },
source_amount: { type: 'currency', value: '0.7' },
destination_amount: { type: 'currency', value: '0.7' },
destination_token: {
type: 'token',
value: {
name: 'Museion',
type: 'ERC-20',
symbol: 'MUSA',
address: '0x486a3c5f34cDc4EF133f248f1C81168D78da52e8',
holders: '1152',
decimals: '18',
icon_url: null,
total_supply: '210000000000000000000000000',
exchange_rate: null,
circulating_market_cap: null,
},
},
},
},
{
summary_template: '{action_type} {source_amount} Ether into {destination_amount} {destination_token}',
summary_template_variables: {
action_type: { type: 'string', value: 'Wrap' },
source_amount: { type: 'currency', value: '0.7' },
destination_amount: { type: 'currency', value: '0.7' },
destination_token: {
type: 'token',
value: {
name: 'Museion',
type: 'ERC-20',
symbol: 'MUSA',
address: '0x486a3c5f34cDc4EF133f248f1C81168D78da52e8',
holders: '1152',
decimals: '18',
icon_url: null,
total_supply: '210000000000000000000000000',
exchange_rate: null,
circulating_market_cap: null,
},
},
},
},
],
},
};
import type { TxInterpretationResponse } from 'types/api/txInterpretation';
import { TOKEN_INFO_ERC_20 } from './token';
export const TX_INTERPRETATION: TxInterpretationResponse = {
data: {
summaries: [
{
summary_template: '{action_type} {source_amount} Ether into {destination_amount} {destination_token}',
summary_template_variables: {
action_type: { type: 'string', value: 'Wrap' },
source_amount: { type: 'currency', value: '0.7' },
destination_amount: { type: 'currency', value: '0.7' },
destination_token: {
type: 'token',
value: TOKEN_INFO_ERC_20,
},
},
},
{
summary_template: '{action_type} {source_amount} Ether into {destination_amount} {destination_token}',
summary_template_variables: {
action_type: { type: 'string', value: 'Wrap' },
source_amount: { type: 'currency', value: '0.7' },
destination_amount: { type: 'currency', value: '0.7' },
destination_token: {
type: 'token',
value: TOKEN_INFO_ERC_20,
},
},
},
],
},
};
import { Box, Flex, Link } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -8,24 +7,20 @@ import config from 'configs/app'; ...@@ -8,24 +7,20 @@ import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import { TX, TX_INTERPRETATION } from 'stubs/tx'; import { TX } from 'stubs/tx';
import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu';
import TextAd from 'ui/shared/ad/TextAd'; import TextAd from 'ui/shared/ad/TextAd';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import EntityTags from 'ui/shared/EntityTags'; import EntityTags from 'ui/shared/EntityTags';
import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs'; import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton'; import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
import useTabIndexFromQuery from 'ui/shared/Tabs/useTabIndexFromQuery'; import useTabIndexFromQuery from 'ui/shared/Tabs/useTabIndexFromQuery';
import { TX_ACTIONS_BLOCK_ID } from 'ui/tx/details/txDetailsActions/TxDetailsActionsWrapper';
import TxInterpretation from 'ui/tx/interpretation/TxInterpretation';
import TxDetails from 'ui/tx/TxDetails'; import TxDetails from 'ui/tx/TxDetails';
import TxDetailsWrapped from 'ui/tx/TxDetailsWrapped'; import TxDetailsWrapped from 'ui/tx/TxDetailsWrapped';
import TxInternals from 'ui/tx/TxInternals'; import TxInternals from 'ui/tx/TxInternals';
import TxLogs from 'ui/tx/TxLogs'; import TxLogs from 'ui/tx/TxLogs';
import TxRawTrace from 'ui/tx/TxRawTrace'; import TxRawTrace from 'ui/tx/TxRawTrace';
import TxState from 'ui/tx/TxState'; import TxState from 'ui/tx/TxState';
import TxSubHeading from 'ui/tx/TxSubHeading';
import TxTokenTransfer from 'ui/tx/TxTokenTransfer'; import TxTokenTransfer from 'ui/tx/TxTokenTransfer';
const TransactionPageContent = () => { const TransactionPageContent = () => {
...@@ -42,21 +37,11 @@ const TransactionPageContent = () => { ...@@ -42,21 +37,11 @@ const TransactionPageContent = () => {
}, },
}); });
const hasInterpretationFeature = config.features.txInterpretation.isEnabled;
const txInterpretationQuery = useApiQuery('tx_interpretation', {
pathParams: { hash },
queryOptions: {
enabled: Boolean(hash) && hasInterpretationFeature,
placeholderData: TX_INTERPRETATION,
},
});
const tabs: Array<RoutedTab> = [ const tabs: Array<RoutedTab> = [
{ {
id: 'index', id: 'index',
title: config.features.suave.isEnabled && data?.wrapped ? 'Confidential compute tx details' : 'Details', title: config.features.suave.isEnabled && data?.wrapped ? 'Confidential compute tx details' : 'Details',
component: <TxDetails txInterpretationQuery={ txInterpretationQuery }/>, component: <TxDetails/>,
}, },
config.features.suave.isEnabled && data?.wrapped ? config.features.suave.isEnabled && data?.wrapped ?
{ id: 'wrapped', title: 'Regular tx details', component: <TxDetailsWrapped data={ data.wrapped }/> } : { id: 'wrapped', title: 'Regular tx details', component: <TxDetailsWrapped data={ data.wrapped }/> } :
...@@ -90,28 +75,7 @@ const TransactionPageContent = () => { ...@@ -90,28 +75,7 @@ const TransactionPageContent = () => {
}; };
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
const hasInterpretation = hasInterpretationFeature && const titleSecondRow = <TxSubHeading hash={ hash } hasTag={ Boolean(data?.tx_tag) }/>;
(txInterpretationQuery.isPlaceholderData || txInterpretationQuery.data?.data.summaries.length);
const titleSecondRow = (
<Box display={{ base: 'block', lg: 'flex' }} alignItems="center" w="100%">
{ hasInterpretationFeature && (
<Flex mr={{ base: 0, lg: 6 }} flexWrap="wrap" alignItems="center">
<TxInterpretation
summary={ txInterpretationQuery.data?.data.summaries[0] }
isLoading={ txInterpretationQuery.isPlaceholderData }
/>
{ !txInterpretationQuery.isPlaceholderData && txInterpretationQuery.data?.data.summaries && txInterpretationQuery.data?.data.summaries.length > 1 &&
<Link ml={ 3 } href={ `#${ TX_ACTIONS_BLOCK_ID }` }>all actions</Link> }
</Flex>
) }
{ !hasInterpretation && <TxEntity hash={ hash } noLink noCopy={ false } fontWeight={ 500 } mr={{ base: 0, lg: 2 }} fontFamily="heading"/> }
<Flex alignItems="center" justifyContent={{ base: 'start', lg: 'space-between' }} flexGrow={ 1 }>
{ !data?.tx_tag && <AccountActionsMenu mr={ 3 } mt={{ base: 3, lg: 0 }}/> }
<NetworkExplorers type="tx" pathParam={ hash } ml={{ base: 0, lg: 'auto' }} mt={{ base: 3, lg: 0 }}/>
</Flex>
</Box>
);
return ( return (
<> <>
......
...@@ -12,18 +12,15 @@ import { ...@@ -12,18 +12,15 @@ import {
Skeleton, Skeleton,
Alert, Alert,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import { scroller, Element } from 'react-scroll'; import { scroller, Element } from 'react-scroll';
import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction'; import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction';
import type { TxInterpretationResponse } from 'types/api/txInterpretation';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import type { ResourceError } from 'lib/api/resources';
import { WEI, WEI_IN_GWEI } from 'lib/consts'; import { WEI, WEI_IN_GWEI } from 'lib/consts';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
...@@ -47,8 +44,7 @@ import TextSeparator from 'ui/shared/TextSeparator'; ...@@ -47,8 +44,7 @@ import TextSeparator from 'ui/shared/TextSeparator';
import TxFeeStability from 'ui/shared/tx/TxFeeStability'; import TxFeeStability from 'ui/shared/tx/TxFeeStability';
import Utilization from 'ui/shared/Utilization/Utilization'; import Utilization from 'ui/shared/Utilization/Utilization';
import VerificationSteps from 'ui/shared/verificationSteps/VerificationSteps'; import VerificationSteps from 'ui/shared/verificationSteps/VerificationSteps';
import TxDetailsActionsFallback from 'ui/tx/details/txDetailsActions/TxDetailsActionsFallback'; import TxDetailsActions from 'ui/tx/details/txDetailsActions/TxDetailsActions';
import TxDetailsActionsInterpretation from 'ui/tx/details/txDetailsActions/TxDetailsActionsInterpretation';
import TxDetailsFeePerGas from 'ui/tx/details/TxDetailsFeePerGas'; import TxDetailsFeePerGas from 'ui/tx/details/TxDetailsFeePerGas';
import TxDetailsGasPrice from 'ui/tx/details/TxDetailsGasPrice'; import TxDetailsGasPrice from 'ui/tx/details/TxDetailsGasPrice';
import TxDetailsOther from 'ui/tx/details/TxDetailsOther'; import TxDetailsOther from 'ui/tx/details/TxDetailsOther';
...@@ -59,11 +55,7 @@ import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers'; ...@@ -59,11 +55,7 @@ import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers';
import TxSocketAlert from 'ui/tx/TxSocketAlert'; import TxSocketAlert from 'ui/tx/TxSocketAlert';
import useFetchTxInfo from 'ui/tx/useFetchTxInfo'; import useFetchTxInfo from 'ui/tx/useFetchTxInfo';
type Props = { const TxDetails = () => {
txInterpretationQuery?: UseQueryResult<TxInterpretationResponse, ResourceError>;
}
const TxDetails = ({ txInterpretationQuery }: Props) => {
const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo(); const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo();
const [ isExpanded, setIsExpanded ] = React.useState(false); const [ isExpanded, setIsExpanded ] = React.useState(false);
...@@ -248,25 +240,7 @@ const TxDetails = ({ txInterpretationQuery }: Props) => { ...@@ -248,25 +240,7 @@ const TxDetails = ({ txInterpretationQuery }: Props) => {
<DetailsInfoItemDivider/> <DetailsInfoItemDivider/>
{ config.features.txInterpretation.isEnabled && txInterpretationQuery !== undefined && ( <TxDetailsActions hash={ data.hash } actions={ data.actions } isTxDataLoading={ isPlaceholderData }/>
<>
<TxDetailsActionsInterpretation
actions={ txInterpretationQuery.data?.data.summaries }
isLoading={ isPlaceholderData || txInterpretationQuery.isPlaceholderData }
/>
{ (isPlaceholderData ||
txInterpretationQuery.isPlaceholderData ||
(txInterpretationQuery.data?.data.summaries && txInterpretationQuery.data?.data.summaries.length > 1)) &&
<DetailsInfoItemDivider/> }
</>
) }
{ /* if tx interpretation is not configured, show tx actions from tx info */ }
{ !config.features.txInterpretation.isEnabled && data.actions && data.actions.length > 0 && (
<>
<TxDetailsActionsFallback actions={ data.actions } isLoading={ isPlaceholderData }/>
<DetailsInfoItemDivider/>
</>
) }
<DetailsInfoItem <DetailsInfoItem
title="From" title="From"
......
import { Box, Flex, Link } from '@chakra-ui/react';
import React from 'react';
import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import { TX_INTERPRETATION } from 'stubs/txInterpretation';
import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import NetworkExplorers from 'ui/shared/NetworkExplorers';
import { TX_ACTIONS_BLOCK_ID } from 'ui/tx/details/txDetailsActions/TxDetailsActionsWrapper';
import TxInterpretation from 'ui/tx/interpretation/TxInterpretation';
type Props = {
hash?: string;
hasTag: boolean;
}
const TxSubHeading = ({ hash, hasTag }: Props) => {
const hasInterpretationFeature = config.features.txInterpretation.isEnabled;
const txInterpretationQuery = useApiQuery('tx_interpretation', {
pathParams: { hash },
queryOptions: {
enabled: Boolean(hash) && hasInterpretationFeature,
placeholderData: TX_INTERPRETATION,
},
});
const hasInterpretation = hasInterpretationFeature &&
(txInterpretationQuery.isPlaceholderData || txInterpretationQuery.data?.data.summaries.length);
return (
<Box display={{ base: 'block', lg: 'flex' }} alignItems="center" w="100%">
{ hasInterpretationFeature && (
<Flex mr={{ base: 0, lg: 6 }} flexWrap="wrap" alignItems="center">
<TxInterpretation
summary={ txInterpretationQuery.data?.data.summaries[0] }
isLoading={ txInterpretationQuery.isPlaceholderData }
fontSize="lg"
/>
{ !txInterpretationQuery.isPlaceholderData && txInterpretationQuery.data?.data.summaries && txInterpretationQuery.data?.data.summaries.length > 1 &&
<Link ml={ 3 } href={ `#${ TX_ACTIONS_BLOCK_ID }` }>all actions</Link> }
</Flex>
) }
{ !hasInterpretation && <TxEntity hash={ hash } noLink noCopy={ false } fontWeight={ 500 } mr={{ base: 0, lg: 2 }} fontFamily="heading"/> }
<Flex alignItems="center" justifyContent={{ base: 'start', lg: 'space-between' }} flexGrow={ 1 }>
{ !hasTag && <AccountActionsMenu mr={ 3 } mt={{ base: 3, lg: 0 }}/> }
<NetworkExplorers type="tx" pathParam={ hash } ml={{ base: 0, lg: 'auto' }} mt={{ base: 3, lg: 0 }}/>
</Flex>
</Box>
);
};
export default TxSubHeading;
import React from 'react';
import type { TxAction } from 'types/api/txAction';
import config from 'configs/app';
import TxDetailsActionsInterpretation from 'ui/tx/details/txDetailsActions/TxDetailsActionsInterpretation';
import TxDetailsActionsRaw from 'ui/tx/details/txDetailsActions/TxDetailsActionsRaw';
type Props = {
isTxDataLoading: boolean;
actions?: Array<TxAction>;
hash?: string;
}
const TxDetailsActions = ({ isTxDataLoading, actions, hash }: Props) => {
if (config.features.txInterpretation.isEnabled) {
return <TxDetailsActionsInterpretation hash={ hash } isTxDataLoading={ isTxDataLoading }/>;
}
/* if tx interpretation is not configured, show tx actions from tx info */
if (actions && actions.length > 0) {
return <TxDetailsActionsRaw actions={ actions } isLoading={ isTxDataLoading }/>;
}
return null;
};
export default TxDetailsActions;
import React from 'react'; import React from 'react';
import type { TxInterpretationSummary } from 'types/api/txInterpretation'; import useApiQuery from 'lib/api/useApiQuery';
import { TX_INTERPRETATION } from 'stubs/txInterpretation';
import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
import TxInterpretation from 'ui/tx/interpretation/TxInterpretation'; import TxInterpretation from 'ui/tx/interpretation/TxInterpretation';
import TxDetailsActionsWrapper from './TxDetailsActionsWrapper'; import TxDetailsActionsWrapper from './TxDetailsActionsWrapper';
interface Props { interface Props {
actions?: Array<TxInterpretationSummary>; hash?: string;
isLoading: boolean; isTxDataLoading: boolean;
} }
const TxDetailsActionsInterpretation = ({ isLoading, actions }: Props) => { const TxDetailsActionsInterpretation = ({ hash, isTxDataLoading }: Props) => {
const txInterpretationQuery = useApiQuery('tx_interpretation', {
pathParams: { hash },
queryOptions: {
enabled: Boolean(hash),
placeholderData: TX_INTERPRETATION,
refetchOnMount: false,
},
});
const actions = txInterpretationQuery.data?.data.summaries;
if (!actions || actions.length < 2) { if (!actions || actions.length < 2) {
return null; return null;
} }
return ( return (
<TxDetailsActionsWrapper isLoading={ isLoading }> <>
{ actions.map((action, index: number) => <TxInterpretation key={ index } summary={ action } isLoading={ isLoading }/>) } <TxDetailsActionsWrapper isLoading={ isTxDataLoading || txInterpretationQuery.isPlaceholderData }>
</TxDetailsActionsWrapper> { actions.map((action, index: number) => (
<TxInterpretation
key={ index }
summary={ action }
isLoading={ isTxDataLoading || txInterpretationQuery.isPlaceholderData }
/>
),
) }
</TxDetailsActionsWrapper>
<DetailsInfoItemDivider/>
</>
); );
}; };
......
...@@ -2,6 +2,8 @@ import React from 'react'; ...@@ -2,6 +2,8 @@ import React from 'react';
import type { TxAction } from 'types/api/txAction'; import type { TxAction } from 'types/api/txAction';
import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
import TxDetailsAction from './TxDetailsAction'; import TxDetailsAction from './TxDetailsAction';
import TxDetailsActionsWrapper from './TxDetailsActionsWrapper'; import TxDetailsActionsWrapper from './TxDetailsActionsWrapper';
...@@ -10,12 +12,15 @@ interface Props { ...@@ -10,12 +12,15 @@ interface Props {
isLoading: boolean; isLoading: boolean;
} }
const TxDetailsActionsFallback = ({ actions, isLoading }: Props) => { const TxDetailsActionsRaw = ({ actions, isLoading }: Props) => {
return ( return (
<TxDetailsActionsWrapper isLoading={ isLoading }> <>
{ actions.map((action, index: number) => <TxDetailsAction key={ index } action={ action }/>) } <TxDetailsActionsWrapper isLoading={ isLoading }>
</TxDetailsActionsWrapper> { actions.map((action, index: number) => <TxDetailsAction key={ index } action={ action }/>) }
</TxDetailsActionsWrapper>
<DetailsInfoItemDivider/>
</>
); );
}; };
export default TxDetailsActionsFallback; export default TxDetailsActionsRaw;
...@@ -36,7 +36,7 @@ const TxDetailsActions = ({ children, isLoading }: Props) => { ...@@ -36,7 +36,7 @@ const TxDetailsActions = ({ children, isLoading }: Props) => {
isLoading={ isLoading } isLoading={ isLoading }
> >
<Flex <Flex
id="tx-actions" id={ TX_ACTIONS_BLOCK_ID }
flexDirection="column" flexDirection="column"
alignItems="stretch" alignItems="stretch"
rowGap={ 5 } rowGap={ 5 }
......
import { Skeleton, Flex, Text, Icon, chakra } from '@chakra-ui/react'; import { Skeleton, Flex, Text, chakra } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { TxInterpretationSummary, TxInterpretationVariable } from 'types/api/txInterpretation'; import type { TxInterpretationSummary, TxInterpretationVariable } from 'types/api/txInterpretation';
import config from 'configs/app'; import config from 'configs/app';
import actionIcon from 'icons/action.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
import { extractVariables, getStringChunks, NATIVE_COIN_SYMBOL_VAR_NAME } from './utils'; import { extractVariables, getStringChunks, NATIVE_COIN_SYMBOL_VAR_NAME } from './utils';
...@@ -45,8 +45,10 @@ const TxInterpretationElementByType = ({ variable }: { variable?: TxInterpretati ...@@ -45,8 +45,10 @@ const TxInterpretationElementByType = ({ variable }: { variable?: TxInterpretati
numberString = BigNumber(value).toPrecision(2); numberString = BigNumber(value).toPrecision(2);
} else if (BigNumber(value).isLessThan(10000)) { } else if (BigNumber(value).isLessThan(10000)) {
numberString = BigNumber(value).dp(2).toFormat(); numberString = BigNumber(value).dp(2).toFormat();
} else { } else if (BigNumber(value).isLessThan(1000000)) {
numberString = BigNumber(value).dividedBy(1000).toFormat(2) + 'K'; numberString = BigNumber(value).dividedBy(1000).toFormat(2) + 'K';
} else {
numberString = BigNumber(value).dividedBy(1000000).toFormat(2) + 'M';
} }
return <Text>{ numberString + ' ' }</Text>; return <Text>{ numberString + ' ' }</Text>;
} }
...@@ -74,10 +76,10 @@ const TxInterpretation = ({ summary, isLoading, className }: Props) => { ...@@ -74,10 +76,10 @@ const TxInterpretation = ({ summary, isLoading, className }: Props) => {
return ( return (
<Skeleton display="flex" flexWrap="wrap" alignItems="center" isLoaded={ !isLoading } className={ className }> <Skeleton display="flex" flexWrap="wrap" alignItems="center" isLoaded={ !isLoading } className={ className }>
<Icon as={ actionIcon } boxSize={ 5 } color="text_secondary" mr={ 2 }/> <IconSvg name="lightning" boxSize={ 5 } color="text_secondary" mr={ 2 }/>
{ chunks.map((chunk, index) => { { chunks.map((chunk, index) => {
return ( return (
<Flex whiteSpace="pre" key={ chunk + index } fontSize="lg" fontWeight={ 500 }> <Flex whiteSpace="pre" key={ chunk + index } fontWeight={ 500 }>
<Text color="text_secondary">{ chunk.trim() + (chunk.trim() && variablesNames[index] ? ' ' : '') }</Text> <Text color="text_secondary">{ chunk.trim() + (chunk.trim() && variablesNames[index] ? ' ' : '') }</Text>
{ index < variablesNames.length && ( { index < variablesNames.length && (
variablesNames[index] === NATIVE_COIN_SYMBOL_VAR_NAME ? variablesNames[index] === NATIVE_COIN_SYMBOL_VAR_NAME ?
......
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