Commit 8df64251 authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

Merge pull request #862 from blockscout/update-tx-state

tx state changes changes!
parents 2fea665e 2f780ab3
......@@ -219,6 +219,7 @@ export const RESOURCES = {
tx_state_changes: {
path: '/api/v2/transactions/:hash/state-changes',
pathParams: [ 'hash' as const ],
filterFields: [],
},
withdrawals: {
path: '/api/v2/withdrawals',
......@@ -512,7 +513,7 @@ export type ResourceErrorAccount<T> = ResourceError<{ errors: T }>
export type PaginatedResources = 'blocks' | 'block_txs' |
'txs_validated' | 'txs_pending' | 'txs_watchlist' |
'tx_internal_txs' | 'tx_logs' | 'tx_token_transfers' |
'tx_internal_txs' | 'tx_logs' | 'tx_token_transfers' | 'tx_state_changes' |
'addresses' |
'address_txs' | 'address_internal_txs' | 'address_token_transfers' | 'address_blocks_validated' | 'address_coin_balance' |
'search' |
......
......@@ -72,6 +72,36 @@ export const receiveMintedToken: TxStateChange = {
type: 'token',
};
export const transfer1155Token: TxStateChange = {
address: {
hash: '0x51243E83Db20F8FC2761D894067A2A9eb7B158DE',
implementation_name: null,
is_contract: false,
is_verified: false,
name: null,
private_tags: [],
public_tags: [],
watchlist_names: [],
},
balance_after: '1',
balance_before: '0',
change: '1',
is_miner: false,
token: {
address: '0x56Cc277717106E528A9FcC2CD342Ff98db758041',
decimals: null,
exchange_rate: null,
holders: '50413',
icon_url: null,
name: null,
symbol: null,
total_supply: null,
type: 'ERC-1155',
},
token_id: '1',
type: 'token',
};
export const receiveCoin: TxStateChange = {
address: {
hash: '0x8dC847Af872947Ac18d5d63fA646EB65d4D99560',
......@@ -110,9 +140,16 @@ export const sendCoin: TxStateChange = {
type: 'coin',
};
export const baseResponse = [
mintToken,
receiveMintedToken,
sendCoin,
receiveCoin,
];
export const baseResponse = {
items: [
mintToken,
receiveMintedToken,
sendCoin,
receiveCoin,
transfer1155Token,
],
next_page_params: {
items_count: 50,
state_changes: null,
},
};
import type { TxStateChange, TxStateChanges } from 'types/api/txStateChanges';
import type { TxStateChange } from 'types/api/txStateChanges';
import { ADDRESS_PARAMS } from './addressParams';
import { TOKEN_INFO_ERC_721 } from './token';
......@@ -40,7 +40,7 @@ export const STATE_CHANGE_TOKEN: TxStateChange = {
type: 'token',
};
export const TX_STATE_CHANGES: TxStateChanges = [
export const TX_STATE_CHANGES: Array<TxStateChange> = [
STATE_CHANGE_MINER,
STATE_CHANGE_COIN,
STATE_CHANGE_TOKEN,
......
import type { AddressParam } from './addressParams';
import type { TokenInfo } from './token';
import type { Erc1155TotalPayload, Erc721TotalPayload } from './tokenTransfer';
import type { Erc721TotalPayload } from './tokenTransfer';
export type TxStateChange = (TxStateChangeCoin | TxStateChangeToken) & {
address: AddressParam;
......@@ -34,24 +34,18 @@ export interface TxStateChangeTokenErc721 {
}>;
}
export type TxStateChangeTokenErc1155 = TxStateChangeTokenErc1155Single | TxStateChangeTokenErc1155Batch;
export interface TxStateChangeTokenErc1155Single {
type: 'token';
token: TokenInfo<'ERC-1155'>;
change: Array<{
direction: ChangeDirection;
total: Erc1155TotalPayload;
}>;
}
export interface TxStateChangeTokenErc1155Batch {
export interface TxStateChangeTokenErc1155 {
type: 'token';
token: TokenInfo<'ERC-1155'>;
change: Array<{
direction: ChangeDirection;
total: Array<Erc1155TotalPayload>;
}>;
change: string;
token_id: string;
}
export type TxStateChanges = Array<TxStateChange>;
export type TxStateChanges = {
items: Array<TxStateChange>;
next_page_params: {
items_count: number;
// ???
state_changes: null;
};
};
import { Accordion, Hide, Show, Text } from '@chakra-ui/react';
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import { SECOND } from 'lib/consts';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { TX_STATE_CHANGES } from 'stubs/txStateChanges';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import TxStateList from 'ui/tx/state/TxStateList';
import TxStateTable from 'ui/tx/state/TxStateTable';
import useFetchTxInfo from 'ui/tx/useFetchTxInfo';
......@@ -14,11 +16,18 @@ import TxSocketAlert from './TxSocketAlert';
const TxState = () => {
const txInfo = useFetchTxInfo({ updateDelay: 5 * SECOND });
const { data, isPlaceholderData, isError } = useApiQuery('tx_state_changes', {
const { data, isPlaceholderData, isError, isPaginationVisible, pagination } = useQueryWithPages({
resourceName: 'tx_state_changes',
pathParams: { hash: txInfo.data?.hash },
queryOptions: {
enabled: Boolean(txInfo.data?.hash) && Boolean(txInfo.data?.status),
placeholderData: TX_STATE_CHANGES,
options: {
enabled: !txInfo.isPlaceholderData && Boolean(txInfo.data?.hash) && Boolean(txInfo.data?.status),
placeholderData: {
items: TX_STATE_CHANGES,
next_page_params: {
items_count: 1,
state_changes: null,
},
},
},
});
......@@ -29,14 +38,20 @@ const TxState = () => {
const content = data ? (
<Accordion allowMultiple defaultIndex={ [] }>
<Hide below="lg" ssr={ false }>
<TxStateTable data={ data } isLoading={ isPlaceholderData }/>
<TxStateTable data={ data.items } isLoading={ isPlaceholderData } top={ isPaginationVisible ? 80 : 0 }/>
</Hide>
<Show below="lg" ssr={ false }>
<TxStateList data={ data } isLoading={ isPlaceholderData }/>
<TxStateList data={ data.items } isLoading={ isPlaceholderData }/>
</Show>
</Accordion>
) : null;
const actionBar = isPaginationVisible ? (
<ActionBar mt={ -6 } showShadow>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
) : null;
return (
<>
<Text mb={ 6 }>
......@@ -45,9 +60,10 @@ const TxState = () => {
</Text>
<DataListDisplay
isError={ isError }
items={ data }
items={ data?.items }
emptyText="There are no state changes for this transaction."
content={ content }
actionBar={ actionBar }
/>
</>
);
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import type { TxStateChanges } from 'types/api/txStateChanges';
import type { TxStateChange } from 'types/api/txStateChanges';
import TxStateListItem from 'ui/tx/state/TxStateListItem';
interface Props {
data: TxStateChanges;
data: Array<TxStateChange>;
isLoading?: boolean;
}
......
......@@ -6,20 +6,21 @@ import {
} from '@chakra-ui/react';
import React from 'react';
import type { TxStateChanges } from 'types/api/txStateChanges';
import type { TxStateChange } from 'types/api/txStateChanges';
import { default as Thead } from 'ui/shared/TheadSticky';
import TxStateTableItem from 'ui/tx/state/TxStateTableItem';
interface Props {
data: TxStateChanges;
data: Array<TxStateChange>;
isLoading?: boolean;
top: number;
}
const TxStateTable = ({ data, isLoading }: Props) => {
const TxStateTable = ({ data, isLoading, top }: Props) => {
return (
<Table variant="simple" minWidth="1000px" size="sm" w="auto">
<Thead top={ 0 }>
<Thead top={ top }>
<Tr>
<Th width="140px">Type</Th>
<Th width="146px">Address</Th>
......
......@@ -3,10 +3,8 @@ import React from 'react';
import TokenTransferNft from 'ui/shared/TokenTransfer/TokenTransferNft';
import type { TxStateChangeNftItemFlatten } from './utils';
interface Props {
items: Array<TxStateChangeNftItemFlatten>;
items: Array<{total: { token_id: string} }>;
tokenAddress: string;
isLoading?: boolean;
}
......
......@@ -2,8 +2,7 @@ import { Flex, Skeleton, Tooltip } from '@chakra-ui/react';
import BigNumber from 'bignumber.js';
import React from 'react';
import type { TxStateChange, TxStateChangeTokenErc1155, TxStateChangeTokenErc1155Single, TxStateChangeTokenErc721 } from 'types/api/txStateChanges';
import type { ArrayElement } from 'types/utils';
import type { TxStateChange } from 'types/api/txStateChanges';
import appConfig from 'configs/app/config';
import { ZERO_ADDRESS } from 'lib/consts';
......@@ -12,6 +11,7 @@ import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import trimTokenSymbol from 'lib/token/trimTokenSymbol';
import AddressLink from 'ui/shared/address/AddressLink';
import Tag from 'ui/shared/chakra/Tag';
import TokenTransferNft from 'ui/shared/TokenTransfer/TokenTransferNft';
import TxStateTokenIdList from './TxStateTokenIdList';
......@@ -98,11 +98,22 @@ export function getStateElements(data: TxStateChange, isLoading?: boolean) {
const tokenId = (() => {
if (!Array.isArray(data.change)) {
return null;
if ('token_id' in data && data.token_id) {
return (
<TokenTransferNft
hash={ data.token.address }
id={ data.token_id }
w="auto"
truncation="constant"
isLoading={ isLoading }
/>
);
} else {
return null;
}
}
const items = (data.change as Array<TxStateChangeNftItem>).reduce(flattenTotal, []);
return <TxStateTokenIdList items={ items } tokenAddress={ data.token.address } isLoading={ isLoading }/>;
return <TxStateTokenIdList items={ data.change } tokenAddress={ data.token.address } isLoading={ isLoading }/>;
})();
return {
......@@ -127,16 +138,3 @@ export function getStateElements(data: TxStateChange, isLoading?: boolean) {
}
}
}
export type TxStateChangeNftItem = ArrayElement<TxStateChangeTokenErc721['change'] | TxStateChangeTokenErc1155['change']>;
export type TxStateChangeNftItemFlatten = ArrayElement<TxStateChangeTokenErc721['change'] | TxStateChangeTokenErc1155Single['change']>;
function flattenTotal(result: Array<TxStateChangeNftItemFlatten>, item: TxStateChangeNftItem): Array<TxStateChangeNftItemFlatten> {
if (Array.isArray(item.total)) {
result.push(...item.total.map((total) => ({ ...item, total })));
} else {
result.push({ ...item, total: item.total });
}
return result;
}
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