mirror of
https://github.com/luxfi/explore.git
synced 2026-07-27 05:54:15 +00:00
review fixes
This commit is contained in:
@@ -4,10 +4,13 @@ import { getEnvValue } from '../utils';
|
||||
|
||||
const title = 'Transaction interpretation';
|
||||
|
||||
const config: Feature<{ isEnabled: true }> = (() => {
|
||||
if (getEnvValue('NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED') === 'true') {
|
||||
const provider = getEnvValue('NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER') || 'none';
|
||||
|
||||
const config: Feature<{ provider: string }> = (() => {
|
||||
if (provider !== 'none') {
|
||||
return Object.freeze({
|
||||
title,
|
||||
provider,
|
||||
isEnabled: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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_CONTRACT_INFO_API_HOST=https://contracts-info.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
|
||||
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
|
||||
return isNoneSchema.isValidSync(data) || isArrayOfWalletsSchema.isValidSync(data);
|
||||
}),
|
||||
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_PROMOTE_BLOCKSCOUT_IN_TITLE: yup.boolean(),
|
||||
NEXT_PUBLIC_OG_DESCRIPTION: yup.string(),
|
||||
|
||||
@@ -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_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_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_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
|
||||
@@ -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_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
|
||||
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_HIDDEN_VIEWS: "['top_accounts']"
|
||||
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED: true
|
||||
|
||||
+1
-3
@@ -476,11 +476,9 @@ This feature is **enabled by default** with the `['metamask']` value. To switch
|
||||
|
||||
### Transaction interpretation
|
||||
|
||||
<!-- Nikita will provide feature description -->
|
||||
|
||||
| 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` |
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 226 B |
Vendored
+1
@@ -52,6 +52,7 @@
|
||||
| "graphQL"
|
||||
| "info"
|
||||
| "key"
|
||||
| "lightning"
|
||||
| "link"
|
||||
| "lock"
|
||||
| "minus"
|
||||
|
||||
-54
@@ -1,6 +1,5 @@
|
||||
import type { RawTracesResponse } from 'types/api/rawTrace';
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { TxInterpretationResponse } from 'types/api/txInterpretation';
|
||||
|
||||
import { ADDRESS_PARAMS } from './addressParams';
|
||||
|
||||
@@ -60,56 +59,3 @@ export const TX_ZKEVM_L2: Transaction = {
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Box, Flex, Link } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
@@ -8,24 +7,20 @@ import config from 'configs/app';
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
import { useAppContext } from 'lib/contexts/app';
|
||||
import getQueryParamString from 'lib/router/getQueryParamString';
|
||||
import { TX, TX_INTERPRETATION } from 'stubs/tx';
|
||||
import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu';
|
||||
import { TX } from 'stubs/tx';
|
||||
import TextAd from 'ui/shared/ad/TextAd';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import EntityTags from 'ui/shared/EntityTags';
|
||||
import NetworkExplorers from 'ui/shared/NetworkExplorers';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
|
||||
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 TxDetailsWrapped from 'ui/tx/TxDetailsWrapped';
|
||||
import TxInternals from 'ui/tx/TxInternals';
|
||||
import TxLogs from 'ui/tx/TxLogs';
|
||||
import TxRawTrace from 'ui/tx/TxRawTrace';
|
||||
import TxState from 'ui/tx/TxState';
|
||||
import TxSubHeading from 'ui/tx/TxSubHeading';
|
||||
import TxTokenTransfer from 'ui/tx/TxTokenTransfer';
|
||||
|
||||
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> = [
|
||||
{
|
||||
id: 'index',
|
||||
title: config.features.suave.isEnabled && data?.wrapped ? 'Confidential compute tx details' : 'Details',
|
||||
component: <TxDetails txInterpretationQuery={ txInterpretationQuery }/>,
|
||||
component: <TxDetails/>,
|
||||
},
|
||||
config.features.suave.isEnabled && data?.wrapped ?
|
||||
{ id: 'wrapped', title: 'Regular tx details', component: <TxDetailsWrapped data={ data.wrapped }/> } :
|
||||
@@ -90,28 +75,7 @@ const TransactionPageContent = () => {
|
||||
};
|
||||
}, [ appProps.referrer ]);
|
||||
|
||||
const hasInterpretation = hasInterpretationFeature &&
|
||||
(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>
|
||||
);
|
||||
const titleSecondRow = <TxSubHeading hash={ hash } hasTag={ Boolean(data?.tx_tag) }/>;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
+3
-29
@@ -12,18 +12,15 @@ import {
|
||||
Skeleton,
|
||||
Alert,
|
||||
} from '@chakra-ui/react';
|
||||
import type { UseQueryResult } from '@tanstack/react-query';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import React from 'react';
|
||||
import { scroller, Element } from 'react-scroll';
|
||||
|
||||
import { ZKEVM_L2_TX_STATUSES } from 'types/api/transaction';
|
||||
import type { TxInterpretationResponse } from 'types/api/txInterpretation';
|
||||
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import config from 'configs/app';
|
||||
import type { ResourceError } from 'lib/api/resources';
|
||||
import { WEI, WEI_IN_GWEI } from 'lib/consts';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
|
||||
@@ -47,8 +44,7 @@ import TextSeparator from 'ui/shared/TextSeparator';
|
||||
import TxFeeStability from 'ui/shared/tx/TxFeeStability';
|
||||
import Utilization from 'ui/shared/Utilization/Utilization';
|
||||
import VerificationSteps from 'ui/shared/verificationSteps/VerificationSteps';
|
||||
import TxDetailsActionsFallback from 'ui/tx/details/txDetailsActions/TxDetailsActionsFallback';
|
||||
import TxDetailsActionsInterpretation from 'ui/tx/details/txDetailsActions/TxDetailsActionsInterpretation';
|
||||
import TxDetailsActions from 'ui/tx/details/txDetailsActions/TxDetailsActions';
|
||||
import TxDetailsFeePerGas from 'ui/tx/details/TxDetailsFeePerGas';
|
||||
import TxDetailsGasPrice from 'ui/tx/details/TxDetailsGasPrice';
|
||||
import TxDetailsOther from 'ui/tx/details/TxDetailsOther';
|
||||
@@ -59,11 +55,7 @@ import TxAllowedPeekers from 'ui/tx/TxAllowedPeekers';
|
||||
import TxSocketAlert from 'ui/tx/TxSocketAlert';
|
||||
import useFetchTxInfo from 'ui/tx/useFetchTxInfo';
|
||||
|
||||
type Props = {
|
||||
txInterpretationQuery?: UseQueryResult<TxInterpretationResponse, ResourceError>;
|
||||
}
|
||||
|
||||
const TxDetails = ({ txInterpretationQuery }: Props) => {
|
||||
const TxDetails = () => {
|
||||
const { data, isPlaceholderData, isError, socketStatus, error } = useFetchTxInfo();
|
||||
|
||||
const [ isExpanded, setIsExpanded ] = React.useState(false);
|
||||
@@ -248,25 +240,7 @@ const TxDetails = ({ txInterpretationQuery }: Props) => {
|
||||
|
||||
<DetailsInfoItemDivider/>
|
||||
|
||||
{ config.features.txInterpretation.isEnabled && txInterpretationQuery !== undefined && (
|
||||
<>
|
||||
<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/>
|
||||
</>
|
||||
) }
|
||||
<TxDetailsActions hash={ data.hash } actions={ data.actions } isTxDataLoading={ isPlaceholderData }/>
|
||||
|
||||
<DetailsInfoItem
|
||||
title="From"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
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;
|
||||
@@ -0,0 +1,28 @@
|
||||
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;
|
||||
@@ -1,21 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { TxAction } from 'types/api/txAction';
|
||||
|
||||
import TxDetailsAction from './TxDetailsAction';
|
||||
import TxDetailsActionsWrapper from './TxDetailsActionsWrapper';
|
||||
|
||||
interface Props {
|
||||
actions: Array<TxAction>;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
const TxDetailsActionsFallback = ({ actions, isLoading }: Props) => {
|
||||
return (
|
||||
<TxDetailsActionsWrapper isLoading={ isLoading }>
|
||||
{ actions.map((action, index: number) => <TxDetailsAction key={ index } action={ action }/>) }
|
||||
</TxDetailsActionsWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default TxDetailsActionsFallback;
|
||||
@@ -1,24 +1,47 @@
|
||||
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 TxDetailsActionsWrapper from './TxDetailsActionsWrapper';
|
||||
|
||||
interface Props {
|
||||
actions?: Array<TxInterpretationSummary>;
|
||||
isLoading: boolean;
|
||||
hash?: string;
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<TxDetailsActionsWrapper isLoading={ isLoading }>
|
||||
{ actions.map((action, index: number) => <TxInterpretation key={ index } summary={ action } isLoading={ isLoading }/>) }
|
||||
</TxDetailsActionsWrapper>
|
||||
<>
|
||||
<TxDetailsActionsWrapper isLoading={ isTxDataLoading || txInterpretationQuery.isPlaceholderData }>
|
||||
{ actions.map((action, index: number) => (
|
||||
<TxInterpretation
|
||||
key={ index }
|
||||
summary={ action }
|
||||
isLoading={ isTxDataLoading || txInterpretationQuery.isPlaceholderData }
|
||||
/>
|
||||
),
|
||||
) }
|
||||
</TxDetailsActionsWrapper>
|
||||
<DetailsInfoItemDivider/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { TxAction } from 'types/api/txAction';
|
||||
|
||||
import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
|
||||
|
||||
import TxDetailsAction from './TxDetailsAction';
|
||||
import TxDetailsActionsWrapper from './TxDetailsActionsWrapper';
|
||||
|
||||
interface Props {
|
||||
actions: Array<TxAction>;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
const TxDetailsActionsRaw = ({ actions, isLoading }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<TxDetailsActionsWrapper isLoading={ isLoading }>
|
||||
{ actions.map((action, index: number) => <TxDetailsAction key={ index } action={ action }/>) }
|
||||
</TxDetailsActionsWrapper>
|
||||
<DetailsInfoItemDivider/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TxDetailsActionsRaw;
|
||||
@@ -36,7 +36,7 @@ const TxDetailsActions = ({ children, isLoading }: Props) => {
|
||||
isLoading={ isLoading }
|
||||
>
|
||||
<Flex
|
||||
id="tx-actions"
|
||||
id={ TX_ACTIONS_BLOCK_ID }
|
||||
flexDirection="column"
|
||||
alignItems="stretch"
|
||||
rowGap={ 5 }
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
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 React from 'react';
|
||||
|
||||
import type { TxInterpretationSummary, TxInterpretationVariable } from 'types/api/txInterpretation';
|
||||
|
||||
import config from 'configs/app';
|
||||
import actionIcon from 'icons/action.svg';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import { extractVariables, getStringChunks, NATIVE_COIN_SYMBOL_VAR_NAME } from './utils';
|
||||
|
||||
@@ -45,8 +45,10 @@ const TxInterpretationElementByType = ({ variable }: { variable?: TxInterpretati
|
||||
numberString = BigNumber(value).toPrecision(2);
|
||||
} else if (BigNumber(value).isLessThan(10000)) {
|
||||
numberString = BigNumber(value).dp(2).toFormat();
|
||||
} else {
|
||||
} else if (BigNumber(value).isLessThan(1000000)) {
|
||||
numberString = BigNumber(value).dividedBy(1000).toFormat(2) + 'K';
|
||||
} else {
|
||||
numberString = BigNumber(value).dividedBy(1000000).toFormat(2) + 'M';
|
||||
}
|
||||
return <Text>{ numberString + ' ' }</Text>;
|
||||
}
|
||||
@@ -74,10 +76,10 @@ const TxInterpretation = ({ summary, isLoading, className }: Props) => {
|
||||
|
||||
return (
|
||||
<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) => {
|
||||
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>
|
||||
{ index < variablesNames.length && (
|
||||
variablesNames[index] === NATIVE_COIN_SYMBOL_VAR_NAME ?
|
||||
|
||||
Reference in New Issue
Block a user