Commit 540d95ee authored by tom goriunov's avatar tom goriunov Committed by GitHub

Internal transactions list page (#2553)

* Internal transactions list page

Fixes #2526

* update nav icon for internal txns route

* fix ts error

* fix external txs test
parent bb77f8f1
<svg viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="m5.29 9.053 3.723-3.828a.972.972 0 0 1 1.336.06 1.051 1.051 0 0 1 .058 1.394L8.4 8.751h14.37c.262 0 .514.107.7.3.188.191.294.454.294.729 0 .275-.106.537-.293.73a.976.976 0 0 1-.7.298H5.987a.969.969 0 0 1-.55-.17 1.02 1.02 0 0 1-.367-.46 1.062 1.062 0 0 1 .22-1.125Zm18.724 6a.97.97 0 0 1 .55.17c.163.111.291.271.367.46a1.062 1.062 0 0 1-.22 1.125l-3.737 3.841-.006.008a.997.997 0 0 1-.322.255.966.966 0 0 1-1.13-.197 1.06 1.06 0 0 1 .056-1.513l.008-.006 2.021-2.087H15.72c.103-.684.183-1.403 0-2.072l8.294.016Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="m5.29 9.053 3.723-3.828a.972.972 0 0 1 1.336.06 1.051 1.051 0 0 1 .058 1.394L8.4 8.751h14.37c.262 0 .514.107.7.3.188.191.294.454.294.729 0 .275-.106.537-.293.73a.976.976 0 0 1-.7.298H5.987a.969.969 0 0 1-.55-.17 1.02 1.02 0 0 1-.367-.46 1.062 1.062 0 0 1 .22-1.125Zm18.724 6a.97.97 0 0 1 .55.17c.163.111.291.271.367.46a1.062 1.062 0 0 1-.22 1.125l-3.737 3.841-.006.008a.997.997 0 0 1-.322.255.966.966 0 0 1-1.13-.197 1.06 1.06 0 0 1 .056-1.513l.008-.006 2.021-2.087H15.72c.103-.684.183-1.403 0-2.072l8.294.016ZM6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" fill="currentColor"/>
<path clip-rule="evenodd" d="M6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path clip-rule="evenodd" d="M6.209 13.24a.67.67 0 0 1 .504-.24h4.277c.095 0 .186.043.252.12l2.496 2.865c.067.077.104.181.104.29v6.55a.884.884 0 0 1-.209.578.67.67 0 0 1-.504.24H6.713a.67.67 0 0 1-.504-.24.884.884 0 0 1-.209-.579V13.82c0-.217.075-.426.209-.58Zm4.634.579h-4.13v9.005h6.416v-6.38l-2.286-2.625Z" stroke="currentColor" stroke-opacity=".2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" fill="currentColor"/>
<path clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
<path clip-rule="evenodd" d="M10.743 13.224c.206 0 .373.167.373.373v2.24h2.24a.373.373 0 1 1 0 .748h-2.613a.373.373 0 0 1-.374-.374v-2.614c0-.206.167-.373.374-.373Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
......@@ -544,6 +544,9 @@ export const RESOURCES = {
withdrawals_counters: {
path: '/api/v2/withdrawals/counters',
},
internal_txs: {
path: '/api/v2/internal-transactions',
},
// ADDRESSES
addresses: {
......@@ -1273,7 +1276,7 @@ export interface ResourceError<T = unknown> {
export type ResourceErrorAccount<T> = ResourceError<{ errors: T }>;
export type PaginatedResources = 'blocks' | 'block_txs' | 'block_election_rewards' |
'txs_validated' | 'txs_pending' | 'txs_with_blobs' | 'txs_watchlist' | 'txs_execution_node' |
'txs_validated' | 'txs_pending' | 'txs_with_blobs' | 'txs_watchlist' | 'txs_execution_node' | 'internal_txs' |
'tx_internal_txs' | 'tx_logs' | 'tx_token_transfers' | 'tx_state_changes' | 'tx_blobs' |
'addresses' | 'addresses_metadata_search' |
'address_txs' | 'address_internal_txs' | 'address_token_transfers' | 'address_blocks_validated' | 'address_coin_balance' |
......@@ -1342,6 +1345,7 @@ Q extends 'txs_pending' ? TransactionsResponsePending :
Q extends 'txs_with_blobs' ? TransactionsResponseWithBlobs :
Q extends 'txs_watchlist' ? TransactionsResponseWatchlist :
Q extends 'txs_execution_node' ? TransactionsResponseValidated :
Q extends 'internal_txs' ? InternalTransactionsResponse :
Q extends 'tx' ? Transaction :
Q extends 'tx_internal_txs' ? InternalTransactionsResponse :
Q extends 'tx_logs' ? LogsResponseTx :
......@@ -1388,20 +1392,6 @@ Q extends 'verified_contracts' ? VerifiedContractsResponse :
Q extends 'verified_contracts_counters' ? VerifiedContractsCounters :
Q extends 'visualize_sol2uml' ? visualizer.VisualizeResponse :
Q extends 'contract_verification_config' ? SmartContractVerificationConfigRaw :
Q extends 'optimistic_l2_output_roots' ? OptimisticL2OutputRootsResponse :
Q extends 'optimistic_l2_withdrawals' ? OptimisticL2WithdrawalsResponse :
Q extends 'optimistic_l2_deposits' ? OptimisticL2DepositsResponse :
Q extends 'optimistic_l2_txn_batches' ? OptimisticL2TxnBatchesResponse :
Q extends 'optimistic_l2_txn_batches_count' ? number :
Q extends 'optimistic_l2_txn_batch' ? OptimismL2TxnBatch :
Q extends 'optimistic_l2_txn_batch_celestia' ? OptimismL2TxnBatch :
Q extends 'optimistic_l2_txn_batch_txs' ? OptimismL2BatchTxs :
Q extends 'optimistic_l2_txn_batch_blocks' ? OptimismL2BatchBlocks :
Q extends 'optimistic_l2_dispute_games' ? OptimisticL2DisputeGamesResponse :
Q extends 'optimistic_l2_output_roots_count' ? number :
Q extends 'optimistic_l2_withdrawals_count' ? number :
Q extends 'optimistic_l2_deposits_count' ? number :
Q extends 'optimistic_l2_dispute_games_count' ? number :
never;
// !!! IMPORTANT !!!
// See comment above
......@@ -1422,34 +1412,6 @@ Q extends 'validators_blackfort' ? ValidatorsBlackfortResponse :
Q extends 'validators_blackfort_counters' ? ValidatorsBlackfortCountersResponse :
Q extends 'validators_zilliqa' ? ValidatorsZilliqaResponse :
Q extends 'validator_zilliqa' ? ValidatorZilliqa :
Q extends 'shibarium_withdrawals' ? ShibariumWithdrawalsResponse :
Q extends 'shibarium_deposits' ? ShibariumDepositsResponse :
Q extends 'shibarium_withdrawals_count' ? number :
Q extends 'shibarium_deposits_count' ? number :
Q extends 'arbitrum_l2_messages' ? ArbitrumL2MessagesResponse :
Q extends 'arbitrum_l2_messages_count' ? number :
Q extends 'arbitrum_l2_txn_batches' ? ArbitrumL2TxnBatchesResponse :
Q extends 'arbitrum_l2_txn_batches_count' ? number :
Q extends 'arbitrum_l2_txn_batch' ? ArbitrumL2TxnBatch :
Q extends 'arbitrum_l2_txn_batch_celestia' ? ArbitrumL2TxnBatch :
Q extends 'arbitrum_l2_txn_batch_txs' ? ArbitrumL2BatchTxs :
Q extends 'arbitrum_l2_txn_batch_blocks' ? ArbitrumL2BatchBlocks :
Q extends 'arbitrum_l2_txn_withdrawals' ? ArbitrumL2TxnWithdrawalsResponse :
Q extends 'arbitrum_l2_message_claim' ? ArbitrumL2MessageClaimResponse :
Q extends 'zkevm_l2_deposits' ? ZkEvmL2DepositsResponse :
Q extends 'zkevm_l2_deposits_count' ? number :
Q extends 'zkevm_l2_withdrawals' ? ZkEvmL2WithdrawalsResponse :
Q extends 'zkevm_l2_withdrawals_count' ? number :
Q extends 'zkevm_l2_txn_batches' ? ZkEvmL2TxnBatchesResponse :
Q extends 'zkevm_l2_txn_batches_count' ? number :
Q extends 'zkevm_l2_txn_batch' ? ZkEvmL2TxnBatch :
Q extends 'zkevm_l2_txn_batch_txs' ? ZkEvmL2TxnBatchTxs :
Q extends 'zksync_l2_txn_batches' ? ZkSyncBatchesResponse :
Q extends 'zksync_l2_txn_batches_count' ? number :
Q extends 'zksync_l2_txn_batch' ? ZkSyncBatch :
Q extends 'zksync_l2_txn_batch_txs' ? ZkSyncBatchTxs :
Q extends 'scroll_l2_txn_batch_txs' ? ScrollL2TxnBatchTxs :
Q extends 'scroll_l2_txn_batch_blocks' ? ScrollL2TxnBatchBlocks :
Q extends 'contract_security_audits' ? SmartContractSecurityAudits :
Q extends 'addresses_lookup' ? bens.LookupAddressResponse :
Q extends 'address_domain' ? bens.GetAddressResponse :
......@@ -1485,13 +1447,6 @@ Q extends 'rewards_user_daily_claim' ? RewardsUserDailyClaimResponse :
Q extends 'rewards_user_referrals' ? RewardsUserReferralsResponse :
Q extends 'token_transfers_all' ? TokenTransferResponse :
Q extends 'address_xstar_score' ? AddressXStarResponse :
Q extends 'scroll_l2_txn_batches' ? ScrollL2BatchesResponse :
Q extends 'scroll_l2_txn_batches_count' ? number :
Q extends 'scroll_l2_txn_batch' ? ScrollL2TxnBatch :
Q extends 'scroll_l2_deposits' ? ScrollL2MessagesResponse :
Q extends 'scroll_l2_deposits_count' ? number :
Q extends 'scroll_l2_withdrawals' ? ScrollL2MessagesResponse :
Q extends 'scroll_l2_withdrawals_count' ? number :
Q extends 'advanced_filter' ? AdvancedFilterResponse :
Q extends 'advanced_filter_methods' ? AdvancedFilterMethodsResponse :
Q extends 'pools' ? PoolsResponse :
......@@ -1502,10 +1457,66 @@ Q extends 'stats_contracts' ? stats.ContractsPageStats :
never;
/* eslint-enable @stylistic/indent */
export type ResourcePayload<Q extends ResourceName> = ResourcePayloadA<Q> | ResourcePayloadB<Q>;
export type PaginatedResponseItems<Q extends ResourceName> = Q extends PaginatedResources ? ResourcePayloadA<Q>['items'] | ResourcePayloadB<Q>['items'] : never;
/* eslint-disable @stylistic/indent */
export type ResourcePayloadRollups<Q extends ResourceName> =
Q extends 'optimistic_l2_output_roots' ? OptimisticL2OutputRootsResponse :
Q extends 'optimistic_l2_withdrawals' ? OptimisticL2WithdrawalsResponse :
Q extends 'optimistic_l2_deposits' ? OptimisticL2DepositsResponse :
Q extends 'optimistic_l2_txn_batches' ? OptimisticL2TxnBatchesResponse :
Q extends 'optimistic_l2_txn_batches_count' ? number :
Q extends 'optimistic_l2_txn_batch' ? OptimismL2TxnBatch :
Q extends 'optimistic_l2_txn_batch_celestia' ? OptimismL2TxnBatch :
Q extends 'optimistic_l2_txn_batch_txs' ? OptimismL2BatchTxs :
Q extends 'optimistic_l2_txn_batch_blocks' ? OptimismL2BatchBlocks :
Q extends 'optimistic_l2_dispute_games' ? OptimisticL2DisputeGamesResponse :
Q extends 'optimistic_l2_output_roots_count' ? number :
Q extends 'optimistic_l2_withdrawals_count' ? number :
Q extends 'optimistic_l2_deposits_count' ? number :
Q extends 'optimistic_l2_dispute_games_count' ? number :
Q extends 'shibarium_withdrawals' ? ShibariumWithdrawalsResponse :
Q extends 'shibarium_deposits' ? ShibariumDepositsResponse :
Q extends 'shibarium_withdrawals_count' ? number :
Q extends 'shibarium_deposits_count' ? number :
Q extends 'arbitrum_l2_messages' ? ArbitrumL2MessagesResponse :
Q extends 'arbitrum_l2_messages_count' ? number :
Q extends 'arbitrum_l2_txn_batches' ? ArbitrumL2TxnBatchesResponse :
Q extends 'arbitrum_l2_txn_batches_count' ? number :
Q extends 'arbitrum_l2_txn_batch' ? ArbitrumL2TxnBatch :
Q extends 'arbitrum_l2_txn_batch_celestia' ? ArbitrumL2TxnBatch :
Q extends 'arbitrum_l2_txn_batch_txs' ? ArbitrumL2BatchTxs :
Q extends 'arbitrum_l2_txn_batch_blocks' ? ArbitrumL2BatchBlocks :
Q extends 'arbitrum_l2_txn_withdrawals' ? ArbitrumL2TxnWithdrawalsResponse :
Q extends 'arbitrum_l2_message_claim' ? ArbitrumL2MessageClaimResponse :
Q extends 'zkevm_l2_deposits' ? ZkEvmL2DepositsResponse :
Q extends 'zkevm_l2_deposits_count' ? number :
Q extends 'zkevm_l2_withdrawals' ? ZkEvmL2WithdrawalsResponse :
Q extends 'zkevm_l2_withdrawals_count' ? number :
Q extends 'zkevm_l2_txn_batches' ? ZkEvmL2TxnBatchesResponse :
Q extends 'zkevm_l2_txn_batches_count' ? number :
Q extends 'zkevm_l2_txn_batch' ? ZkEvmL2TxnBatch :
Q extends 'zkevm_l2_txn_batch_txs' ? ZkEvmL2TxnBatchTxs :
Q extends 'zksync_l2_txn_batches' ? ZkSyncBatchesResponse :
Q extends 'zksync_l2_txn_batches_count' ? number :
Q extends 'zksync_l2_txn_batch' ? ZkSyncBatch :
Q extends 'zksync_l2_txn_batch_txs' ? ZkSyncBatchTxs :
Q extends 'scroll_l2_txn_batch_txs' ? ScrollL2TxnBatchTxs :
Q extends 'scroll_l2_txn_batch_blocks' ? ScrollL2TxnBatchBlocks :
Q extends 'scroll_l2_txn_batches' ? ScrollL2BatchesResponse :
Q extends 'scroll_l2_txn_batches_count' ? number :
Q extends 'scroll_l2_txn_batch' ? ScrollL2TxnBatch :
Q extends 'scroll_l2_deposits' ? ScrollL2MessagesResponse :
Q extends 'scroll_l2_deposits_count' ? number :
Q extends 'scroll_l2_withdrawals' ? ScrollL2MessagesResponse :
Q extends 'scroll_l2_withdrawals_count' ? number :
never;
/* eslint-enable @stylistic/indent */
export type ResourcePayload<Q extends ResourceName> = ResourcePayloadA<Q> | ResourcePayloadB<Q> | ResourcePayloadRollups<Q>;
export type PaginatedResponseItems<Q extends ResourceName> = Q extends PaginatedResources ?
ResourcePayloadA<Q>['items'] | ResourcePayloadB<Q>['items'] | ResourcePayloadRollups<Q>['items'] :
never;
export type PaginatedResponseNextPageParams<Q extends ResourceName> = Q extends PaginatedResources ?
ResourcePayloadA<Q>['next_page_params'] | ResourcePayloadB<Q>['next_page_params'] :
ResourcePayloadA<Q>['next_page_params'] | ResourcePayloadB<Q>['next_page_params'] | ResourcePayloadRollups<Q>['next_page_params'] :
never;
/* eslint-disable @stylistic/indent */
......
......@@ -44,6 +44,12 @@ export default function useNavItems(): ReturnType {
icon: 'transactions',
isActive: pathname === '/txs' || pathname === '/tx/[hash]',
};
const internalTxs: NavItem | null = {
text: 'Internal transactions',
nextRoute: { pathname: '/internal-txs' as const },
icon: 'internal_txns',
isActive: pathname === '/internal-txs',
};
const userOps: NavItem | null = config.features.userOps.isEnabled ? {
text: 'User operations',
nextRoute: { pathname: '/ops' as const },
......@@ -118,6 +124,7 @@ export default function useNavItems(): ReturnType {
blockchainNavItems = [
[
txs,
internalTxs,
rollupDeposits,
rollupWithdrawals,
],
......@@ -140,6 +147,7 @@ export default function useNavItems(): ReturnType {
blockchainNavItems = [
[
txs,
internalTxs,
rollupDeposits,
rollupWithdrawals,
],
......@@ -155,6 +163,7 @@ export default function useNavItems(): ReturnType {
blockchainNavItems = [
[
txs,
internalTxs,
userOps,
blocks,
rollupTxnBatches,
......@@ -169,6 +178,7 @@ export default function useNavItems(): ReturnType {
} else {
blockchainNavItems = [
txs,
internalTxs,
userOps,
blocks,
topAccounts,
......
......@@ -5,6 +5,7 @@ type OGPageType = 'Homepage' | 'Root page' | 'Regular page';
const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/': 'Homepage',
'/txs': 'Root page',
'/internal-txs': 'Root page',
'/txs/kettle/[hash]': 'Regular page',
'/tx/[hash]': 'Regular page',
'/blocks': 'Root page',
......
......@@ -8,6 +8,7 @@ const DEFAULT_TEMPLATE = 'Open-source block explorer by Blockscout. Search trans
const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': DEFAULT_TEMPLATE,
'/txs': DEFAULT_TEMPLATE,
'/internal-txs': DEFAULT_TEMPLATE,
'/txs/kettle/[hash]': DEFAULT_TEMPLATE,
'/tx/[hash]': 'View transaction %hash% on %network_title%',
'/blocks': DEFAULT_TEMPLATE,
......
......@@ -5,6 +5,7 @@ import config from 'configs/app';
const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/': '%network_name% blockchain explorer - View %network_name% stats',
'/txs': '%network_name% transactions - %network_name% explorer',
'/internal-txs': '%network_name% internal transactions - %network_name% explorer',
'/txs/kettle/[hash]': '%network_name% kettle %hash% transactions',
'/tx/[hash]': '%network_name% transaction %hash%',
'/blocks': '%network_name% blocks',
......
......@@ -3,6 +3,7 @@ import type { Route } from 'nextjs-routes';
export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/': 'Homepage',
'/txs': 'Transactions',
'/internal-txs': 'Internal transactions',
'/txs/kettle/[hash]': 'Kettle transactions',
'/tx/[hash]': 'Transaction details',
'/blocks': 'Blocks',
......
......@@ -46,6 +46,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/gas-tracker">
| StaticRoute<"/graphiql">
| StaticRoute<"/">
| StaticRoute<"/internal-txs">
| StaticRoute<"/login">
| StaticRoute<"/mud-worlds">
| DynamicRoute<"/name-domains/[name]", { "name": string }>
......
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';
import PageNextJs from 'nextjs/PageNextJs';
const InternalTxs = dynamic(() => import('ui/pages/InternalTxs'), { ssr: false });
const Page: NextPage = () => {
return (
<PageNextJs pathname="/internal-txs">
<InternalTxs/>
</PageNextJs>
);
};
export default Page;
export { base as getServerSideProps } from 'nextjs/getServerSideProps';
......@@ -83,6 +83,7 @@
| "info"
| "integration/full"
| "integration/partial"
| "internal_txns"
| "key"
| "lightning_navbar"
| "lightning"
......
......@@ -11,7 +11,8 @@ import { apos } from 'lib/html-entities';
import getQueryParamString from 'lib/router/getQueryParamString';
import { INTERNAL_TX } from 'stubs/internalTx';
import { generateListStub } from 'stubs/utils';
import AddressIntTxsTable from 'ui/address/internals/AddressIntTxsTable';
import InternalTxsList from 'ui/internalTxs/InternalTxsList';
import InternalTxsTable from 'ui/internalTxs/InternalTxsTable';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/pagination/Pagination';
......@@ -19,7 +20,6 @@ import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
import AddressCsvExportLink from './AddressCsvExportLink';
import AddressTxsFilter from './AddressTxsFilter';
import AddressIntTxsList from './internals/AddressIntTxsList';
const getFilterValue = (getFilterValueFromQuery<AddressFromToFilter>).bind(null, AddressFromToFilterValues);
......@@ -71,10 +71,10 @@ const AddressInternalTxs = ({ scrollRef, shouldRender = true, isQueryEnabled = t
const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
<AddressIntTxsList data={ data.items } currentAddress={ hash } isLoading={ isPlaceholderData }/>
<InternalTxsList data={ data.items } currentAddress={ hash } isLoading={ isPlaceholderData }/>
</Show>
<Hide below="lg" ssr={ false }>
<AddressIntTxsTable data={ data.items } currentAddress={ hash } isLoading={ isPlaceholderData }/>
<InternalTxsTable data={ data.items } currentAddress={ hash } isLoading={ isPlaceholderData }/>
</Hide>
</>
) : null ;
......
......@@ -3,19 +3,19 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction';
import AddressIntTxsListItem from 'ui/address/internals/AddressIntTxsListItem';
import InternalTxsListItem from './InternalTxsListItem';
type Props = {
data: Array<InternalTransaction>;
currentAddress: string;
currentAddress?: string;
isLoading?: boolean;
};
const AddressIntTxsList = ({ data, currentAddress, isLoading }: Props) => {
const InternalTxsList = ({ data, currentAddress, isLoading }: Props) => {
return (
<Box>
{ data.map((item, index) => (
<AddressIntTxsListItem
<InternalTxsListItem
key={ item.transaction_hash + '_' + index }
{ ...item }
currentAddress={ currentAddress }
......@@ -26,4 +26,4 @@ const AddressIntTxsList = ({ data, currentAddress, isLoading }: Props) => {
);
};
export default AddressIntTxsList;
export default InternalTxsList;
......@@ -16,9 +16,9 @@ import TxStatus from 'ui/shared/statusTag/TxStatus';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
type Props = InternalTransaction & { currentAddress: string; isLoading?: boolean };
type Props = InternalTransaction & { currentAddress?: string; isLoading?: boolean };
const TxInternalsListItem = ({
const InternalTxsListItem = ({
type,
from,
to,
......@@ -83,4 +83,4 @@ const TxInternalsListItem = ({
);
};
export default TxInternalsListItem;
export default InternalTxsListItem;
......@@ -7,15 +7,15 @@ import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import { currencyUnits } from 'lib/units';
import { default as Thead } from 'ui/shared/TheadSticky';
import AddressIntTxsTableItem from './AddressIntTxsTableItem';
import InternalTxsTableItem from './InternalTxsTableItem';
interface Props {
data: Array<InternalTransaction>;
currentAddress: string;
currentAddress?: string;
isLoading?: boolean;
}
const AddressIntTxsTable = ({ data, currentAddress, isLoading }: Props) => {
const InternalTxsTable = ({ data, currentAddress, isLoading }: Props) => {
return (
<AddressHighlightProvider>
<Table>
......@@ -32,7 +32,7 @@ const AddressIntTxsTable = ({ data, currentAddress, isLoading }: Props) => {
</Thead>
<Tbody>
{ data.map((item, index) => (
<AddressIntTxsTableItem
<InternalTxsTableItem
key={ item.transaction_hash + '_' + index }
{ ...item }
currentAddress={ currentAddress }
......@@ -46,4 +46,4 @@ const AddressIntTxsTable = ({ data, currentAddress, isLoading }: Props) => {
);
};
export default AddressIntTxsTable;
export default InternalTxsTable;
......@@ -14,9 +14,9 @@ import TxStatus from 'ui/shared/statusTag/TxStatus';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
type Props = InternalTransaction & { currentAddress: string; isLoading?: boolean };
type Props = InternalTransaction & { currentAddress?: string; isLoading?: boolean };
const AddressIntTxsTableItem = ({
const InternalTxsTableItem = ({
type,
from,
to,
......@@ -36,7 +36,7 @@ const AddressIntTxsTableItem = ({
return (
<Tr alignItems="top">
<Td verticalAlign="middle">
<Flex rowGap={ 3 } flexWrap="wrap">
<Flex rowGap={ 3 } flexDir="column">
<TxEntity
hash={ txnHash }
isLoading={ isLoading }
......@@ -91,4 +91,4 @@ const AddressIntTxsTableItem = ({
);
};
export default React.memo(AddressIntTxsTableItem);
export default React.memo(InternalTxsTableItem);
import { Hide, Show } from '@chakra-ui/react';
import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
import { INTERNAL_TX } from 'stubs/internalTx';
import { generateListStub } from 'stubs/utils';
import InternalTxsList from 'ui/internalTxs/InternalTxsList';
import InternalTxsTable from 'ui/internalTxs/InternalTxsTable';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/pagination/Pagination';
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
const InternalTxs = () => {
const isMobile = useIsMobile();
const { isError, isPlaceholderData, data, pagination } = useQueryWithPages({
resourceName: 'internal_txs',
options: {
placeholderData: generateListStub<'internal_txs'>(
INTERNAL_TX,
50,
{
next_page_params: {
items_count: 50,
block_number: 1,
index: 1,
transaction_hash: '0x123',
transaction_index: 1,
},
},
),
},
});
const actionBar = (!isMobile || pagination.isVisible) ? (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
) : null;
const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
<InternalTxsList data={ data.items } isLoading={ isPlaceholderData }/>
</Show>
<Hide below="lg" ssr={ false }>
<InternalTxsTable data={ data.items } isLoading={ isPlaceholderData }/>
</Hide>
</>
) : null;
return (
<>
<PageTitle
title="Internal transactions"
withTextAd
/>
<DataListDisplay
isError={ isError }
items={ data?.items }
emptyText="There are no internal transactions."
content={ content }
actionBar={ actionBar }
/>
</>
);
};
export default InternalTxs;
......@@ -5,14 +5,17 @@ import { test, expect } from 'playwright/lib';
import TxExternalTxs from './TxExternalTxs';
const EXT_TX_HASH = '2uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNtdWJrYDGkCHsRwd2LKXubrQUzXMaojGxZmHZ85XVJN8EJ3LW8';
const EXT_TX_HASH_1 = '1uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNtdWJrYDGkCHsRwd2LKXubrQUzXMaojGxZmHZ85XVJN8EJ3LW8';
const EXT_TX_HASH_2 = '2uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNtdWJrYDGkCHsRwd2LKXubrQUzXMaojGxZmHZ85XVJN8EJ3LW8';
test('base view', async({ page, render, mockEnvs, mockAssetResponse }) => {
await mockEnvs(ENVS_MAP.externalTxs);
await mockAssetResponse('http://example.url', './playwright/mocks/image_s.jpg');
await render(<TxExternalTxs data={ Array(13).fill(EXT_TX_HASH) }/>);
await page.getByText('13 Solana txns').hover();
await render(<TxExternalTxs data={ [ EXT_TX_HASH_1, EXT_TX_HASH_2 ] }/>);
await page.getByText('2 Solana txns').hover();
const popover = page.getByText('Solana transactions');
await expect(popover).toBeVisible();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 500, height: 500 } });
await expect(page.getByText('1uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNtd...3LW8')).toBeVisible();
await expect(page.getByText('2uwpB95K9ae8yrpxxVXJ27ivvHXqrmy82jsamgNt...3LW8')).toBeVisible();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 500, height: 300 } });
});
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