diff --git a/icons/token-transfers.svg b/icons/token-transfers.svg new file mode 100644 index 0000000000..f3bef44d80 --- /dev/null +++ b/icons/token-transfers.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/lib/api/resources.ts b/lib/api/resources.ts index 3ff37aeb2f..dddcab88a1 100644 --- a/lib/api/resources.ts +++ b/lib/api/resources.ts @@ -599,6 +599,12 @@ export const RESOURCES = { filterFields: [], }, + // TOKEN TRANSFERS + token_transfers_all: { + path: '/api/v2/token-transfers', + filterFields: [ 'type' as const ], + }, + // APP STATS stats: { path: '/api/v2/stats', @@ -1015,7 +1021,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' | 'block_election_reward 'zksync_l2_txn_batches' | 'zksync_l2_txn_batch_txs' | 'withdrawals' | 'address_withdrawals' | 'block_withdrawals' | 'watchlist' | 'private_tags_address' | 'private_tags_tx' | -'domains_lookup' | 'addresses_lookup' | 'user_ops' | 'validators_stability' | 'validators_blackfort' | 'noves_address_history'; +'domains_lookup' | 'addresses_lookup' | 'user_ops' | 'validators_stability' | 'validators_blackfort' | 'noves_address_history' | +'token_transfers_all'; export type PaginatedResponse = ResourcePayload; @@ -1184,6 +1191,7 @@ Q extends 'address_mud_records' ? AddressMudRecords : Q extends 'address_mud_record' ? AddressMudRecord : Q extends 'withdrawals' ? WithdrawalsResponse : Q extends 'withdrawals_counters' ? WithdrawalsCounters : +Q extends 'token_transfers_all' ? TokenTransferResponse : never; /* eslint-enable @typescript-eslint/indent */ @@ -1218,6 +1226,7 @@ Q extends 'user_ops' ? UserOpsFilters : Q extends 'validators_stability' ? ValidatorsStabilityFilters : Q extends 'address_mud_tables' ? AddressMudTablesFilter : Q extends 'address_mud_records' ? AddressMudRecordsFilter : +Q extends 'token_transfers_all' ? TokenTransferFilters : never; /* eslint-enable @typescript-eslint/indent */ diff --git a/lib/hooks/useNavItems.tsx b/lib/hooks/useNavItems.tsx index a3db79064e..5814aae2ee 100644 --- a/lib/hooks/useNavItems.tsx +++ b/lib/hooks/useNavItems.tsx @@ -181,6 +181,21 @@ export default function useNavItems(): ReturnType { ].filter(Boolean); } + const tokensNavItems = [ + { + text: 'Tokens', + nextRoute: { pathname: '/tokens' as const }, + icon: 'token', + isActive: pathname.startsWith('/token'), + }, + { + text: 'Token transfers', + nextRoute: { pathname: '/token-transfers' as const }, + icon: 'token-transfers', + isActive: pathname === '/token-transfers', + }, + ]; + const apiNavItems: Array = [ config.features.restApiDocs.isEnabled ? { text: 'REST API', @@ -234,9 +249,9 @@ export default function useNavItems(): ReturnType { }, { text: 'Tokens', - nextRoute: { pathname: '/tokens' as const }, icon: 'token', - isActive: pathname.startsWith('/token'), + isActive: tokensNavItems.flat().some(item => isInternalItem(item) && item.isActive), + subItems: tokensNavItems, }, config.features.marketplace.isEnabled ? { text: 'DApps', diff --git a/lib/metadata/getPageOgType.ts b/lib/metadata/getPageOgType.ts index 7babaa72b8..38d6008db6 100644 --- a/lib/metadata/getPageOgType.ts +++ b/lib/metadata/getPageOgType.ts @@ -51,6 +51,7 @@ const OG_TYPE_DICT: Record = { '/validators': 'Root page', '/gas-tracker': 'Root page', '/mud-worlds': 'Root page', + '/token-transfers': 'Root page', // service routes, added only to make typescript happy '/login': 'Regular page', diff --git a/lib/metadata/templates/description.ts b/lib/metadata/templates/description.ts index 49351be252..2d0067474d 100644 --- a/lib/metadata/templates/description.ts +++ b/lib/metadata/templates/description.ts @@ -55,6 +55,7 @@ const TEMPLATE_MAP: Record = { '/validators': DEFAULT_TEMPLATE, '/gas-tracker': DEFAULT_TEMPLATE, '/mud-worlds': DEFAULT_TEMPLATE, + '/token-transfers': DEFAULT_TEMPLATE, // service routes, added only to make typescript happy '/login': DEFAULT_TEMPLATE, diff --git a/lib/metadata/templates/title.ts b/lib/metadata/templates/title.ts index c8ef390d71..9d7c20bb27 100644 --- a/lib/metadata/templates/title.ts +++ b/lib/metadata/templates/title.ts @@ -51,6 +51,7 @@ const TEMPLATE_MAP: Record = { '/validators': '%network_name% validators list', '/gas-tracker': '%network_name% gas tracker - Current gas fees', '/mud-worlds': '%network_name% MUD worlds list', + '/token-transfers': '%network_name% token transfers', // service routes, added only to make typescript happy '/login': '%network_name% login', diff --git a/lib/mixpanel/getPageType.ts b/lib/mixpanel/getPageType.ts index af56fb6693..e46c155f41 100644 --- a/lib/mixpanel/getPageType.ts +++ b/lib/mixpanel/getPageType.ts @@ -49,6 +49,7 @@ export const PAGE_TYPE_DICT: Record = { '/validators': 'Validators list', '/gas-tracker': 'Gas tracker', '/mud-worlds': 'MUD worlds', + '/token-transfers': 'Token transfers', // service routes, added only to make typescript happy '/login': 'Login', diff --git a/mocks/tokens/tokenTransfer.ts b/mocks/tokens/tokenTransfer.ts index b88cd499ff..d6b93ad890 100644 --- a/mocks/tokens/tokenTransfer.ts +++ b/mocks/tokens/tokenTransfer.ts @@ -42,6 +42,7 @@ export const erc20: TokenTransfer = { tx_hash: '0x62d597ebcf3e8d60096dd0363bc2f0f5e2df27ba1dacd696c51aa7c9409f3193', type: 'token_transfer', timestamp: '2022-10-10T14:34:30.000000Z', + block_number: '12345', block_hash: '1', log_index: '1', method: 'updateSmartAsset', @@ -88,6 +89,7 @@ export const erc721: TokenTransfer = { tx_hash: '0xf13bc7afe5e02b494dd2f22078381d36a4800ef94a0ccc147431db56c301e6cc', type: 'token_transfer', timestamp: '2022-10-10T14:34:30.000000Z', + block_number: '12345', block_hash: '1', log_index: '1', method: 'updateSmartAsset', @@ -136,6 +138,7 @@ export const erc1155A: TokenTransfer = { tx_hash: '0x05d6589367633c032d757a69c5fb16c0e33e3994b0d9d1483f82aeee1f05d746', type: 'token_minting', timestamp: '2022-10-10T14:34:30.000000Z', + block_number: '12345', block_hash: '1', log_index: '1', }; @@ -214,6 +217,7 @@ export const erc404A: TokenTransfer = { type: 'token_transfer', method: 'swap', timestamp: '2022-10-10T14:34:30.000000Z', + block_number: '12345', block_hash: '1', log_index: '1', }; diff --git a/nextjs/nextjs-routes.d.ts b/nextjs/nextjs-routes.d.ts index 47205b94e2..aee33cd320 100644 --- a/nextjs/nextjs-routes.d.ts +++ b/nextjs/nextjs-routes.d.ts @@ -59,6 +59,7 @@ declare module "nextjs-routes" { | StaticRoute<"/stats"> | DynamicRoute<"/token/[hash]", { "hash": string }> | DynamicRoute<"/token/[hash]/instance/[id]", { "hash": string; "id": string }> + | StaticRoute<"/token-transfers"> | StaticRoute<"/tokens"> | DynamicRoute<"/tx/[hash]", { "hash": string }> | StaticRoute<"/txs"> diff --git a/pages/token-transfers.tsx b/pages/token-transfers.tsx new file mode 100644 index 0000000000..1901a859d9 --- /dev/null +++ b/pages/token-transfers.tsx @@ -0,0 +1,19 @@ +import type { NextPage } from 'next'; +import dynamic from 'next/dynamic'; +import React from 'react'; + +import PageNextJs from 'nextjs/PageNextJs'; + +const TokenTransfers = dynamic(() => import('ui/pages/TokenTransfers'), { ssr: false }); + +const Page: NextPage = () => { + return ( + + + + ); +}; + +export default Page; + +export { base as getServerSideProps } from 'nextjs/getServerSideProps'; diff --git a/public/icons/name.d.ts b/public/icons/name.d.ts index c9c5819bc6..897b7fbcf5 100644 --- a/public/icons/name.d.ts +++ b/public/icons/name.d.ts @@ -149,6 +149,7 @@ | "swap" | "testnet" | "token-placeholder" + | "token-transfers" | "token" | "tokens" | "tokens/xdai" diff --git a/stubs/token.ts b/stubs/token.ts index 3f06faa420..1449bcc0a7 100644 --- a/stubs/token.ts +++ b/stubs/token.ts @@ -91,6 +91,7 @@ export const getTokenInstanceHoldersStub = (type?: TokenType, pagination: TokenH export const TOKEN_TRANSFER_ERC_20: TokenTransfer = { block_hash: BLOCK_HASH, + block_number: '123456', from: ADDRESS_PARAMS, log_index: '4', method: 'addLiquidity', diff --git a/types/api/tokenTransfer.ts b/types/api/tokenTransfer.ts index bb580516dd..48f4c7291f 100644 --- a/types/api/tokenTransfer.ts +++ b/types/api/tokenTransfer.ts @@ -51,6 +51,7 @@ interface TokenTransferBase { from: AddressParam; to: AddressParam; timestamp: string; + block_number: string; block_hash: string; log_index: string; method?: string; diff --git a/ui/pages/TokenTransfers.pw.tsx b/ui/pages/TokenTransfers.pw.tsx new file mode 100644 index 0000000000..b8378a3664 --- /dev/null +++ b/ui/pages/TokenTransfers.pw.tsx @@ -0,0 +1,14 @@ +import { Box } from '@chakra-ui/react'; +import React from 'react'; + +import { mixTokens } from 'mocks/tokens/tokenTransfer'; +import { test, expect } from 'playwright/lib'; + +import TokenTransfers from './TokenTransfers'; + +test('base view +@mobile', async({ render, mockTextAd, mockApiResponse }) => { + await mockTextAd(); + await mockApiResponse('token_transfers_all', mixTokens, { queryParams: { type: [] } }); + const component = await render( ); + await expect(component).toHaveScreenshot(); +}); diff --git a/ui/pages/TokenTransfers.tsx b/ui/pages/TokenTransfers.tsx new file mode 100644 index 0000000000..5a4a7a4ca4 --- /dev/null +++ b/ui/pages/TokenTransfers.tsx @@ -0,0 +1,86 @@ +import { Show, Hide } from '@chakra-ui/react'; +import { useRouter } from 'next/router'; +import React from 'react'; + +import type { TokenType } from 'types/api/token'; + +import { getTokenTransfersStub } from 'stubs/token'; +import ActionBar, { ACTION_BAR_HEIGHT_DESKTOP } from 'ui/shared/ActionBar'; +import DataListDisplay from 'ui/shared/DataListDisplay'; +import PopoverFilter from 'ui/shared/filters/PopoverFilter'; +import TokenTypeFilter from 'ui/shared/filters/TokenTypeFilter'; +import PageTitle from 'ui/shared/Page/PageTitle'; +import Pagination from 'ui/shared/pagination/Pagination'; +import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages'; +import { getTokenFilterValue } from 'ui/tokens/utils'; +import TokenTransfersListItem from 'ui/tokenTransfers/TokenTransfersListItem'; +import TokenTransfersTable from 'ui/tokenTransfers/TokenTransfersTable'; +const TokenTransfers = () => { + const router = useRouter(); + const [ typeFilter, setTypeFilter ] = React.useState>(getTokenFilterValue(router.query.type) || []); + + const tokenTransfersQuery = useQueryWithPages({ + resourceName: 'token_transfers_all', + filters: { type: typeFilter }, + options: { + placeholderData: getTokenTransfersStub(), + }, + }); + + const handleTokenTypesChange = React.useCallback((value: Array) => { + tokenTransfersQuery.onFilterChange({ type: value }); + setTypeFilter(value); + }, [ tokenTransfersQuery ]); + + const content = ( + <> + + { tokenTransfersQuery.data?.items.map((item, index) => ( + + )) } + + + + + + ); + + const filter = ( + + onChange={ handleTokenTypesChange } defaultValue={ typeFilter } nftOnly={ false }/> + + ); + + const actionBar = ( + + { filter } + + + ); + + return ( + <> + + + + ); +}; + +export default TokenTransfers; diff --git a/ui/pages/__screenshots__/TokenTransfers.pw.tsx_default_base-view-mobile-1.png b/ui/pages/__screenshots__/TokenTransfers.pw.tsx_default_base-view-mobile-1.png new file mode 100644 index 0000000000..1e860b0977 Binary files /dev/null and b/ui/pages/__screenshots__/TokenTransfers.pw.tsx_default_base-view-mobile-1.png differ diff --git a/ui/pages/__screenshots__/TokenTransfers.pw.tsx_mobile_base-view-mobile-1.png b/ui/pages/__screenshots__/TokenTransfers.pw.tsx_mobile_base-view-mobile-1.png new file mode 100644 index 0000000000..0d1e9cb66e Binary files /dev/null and b/ui/pages/__screenshots__/TokenTransfers.pw.tsx_mobile_base-view-mobile-1.png differ diff --git a/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-horizontal-navigation-1.png b/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-horizontal-navigation-1.png index 05f4bce2e4..f523fb8da6 100644 Binary files a/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-horizontal-navigation-1.png and b/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-horizontal-navigation-1.png differ diff --git a/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-vertical-navigation-1.png b/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-vertical-navigation-1.png index f4e2c356fd..c84d148382 100644 Binary files a/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-vertical-navigation-1.png and b/ui/shared/layout/__screenshots__/Layout.pw.tsx_default_xxl-screen-vertical-navigation-1.png differ diff --git a/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_auth-base-view-1.png b/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_auth-base-view-1.png index 8433bb4836..a72f4e3b40 100644 Binary files a/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_auth-base-view-1.png and b/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_auth-base-view-1.png differ diff --git a/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_base-view-1.png b/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_base-view-1.png index 977e889971..f700bb1a7f 100644 Binary files a/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_base-view-1.png and b/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_base-view-1.png differ diff --git a/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_dark-mode-base-view-1.png b/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_dark-mode-base-view-1.png index e7d8a14e99..3bd2dcf65c 100644 Binary files a/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_dark-mode-base-view-1.png and b/ui/snippets/header/__screenshots__/Burger.pw.tsx_default_dark-mode-base-view-1.png differ diff --git a/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_base-view-dark-mode-1.png b/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_base-view-dark-mode-1.png index dcdc0bf595..d20e9efa84 100644 Binary files a/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_base-view-dark-mode-1.png and b/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_base-view-dark-mode-1.png differ diff --git a/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_base-view-dark-mode-1.png b/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_base-view-dark-mode-1.png index ae0fdffe40..2ad3ef7fee 100644 Binary files a/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_base-view-dark-mode-1.png and b/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_base-view-dark-mode-1.png differ diff --git a/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_with-groped-items-1.png b/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_with-groped-items-1.png index 15bf22a354..3f231cb594 100644 Binary files a/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_with-groped-items-1.png and b/ui/snippets/navigation/horizontal/__screenshots__/NavigationDesktop.pw.tsx_default_with-groped-items-1.png differ diff --git a/ui/snippets/navigation/vertical/NavigationDesktop.pw.tsx b/ui/snippets/navigation/vertical/NavigationDesktop.pw.tsx index 16000c2415..c37d840fe6 100644 --- a/ui/snippets/navigation/vertical/NavigationDesktop.pw.tsx +++ b/ui/snippets/navigation/vertical/NavigationDesktop.pw.tsx @@ -99,7 +99,7 @@ test.describe('with tooltips', () => { await component.locator('header').hover(); await page.locator('div[aria-label="Expand/Collapse menu"]').click(); - await page.locator('a[aria-label="Tokens link"]').hover(); + await page.locator('a[aria-label="DApps link"]').hover(); await expect(component).toHaveScreenshot(); }); diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_auth-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_auth-xl-screen-dark-mode-1.png index 2f319988b0..4cef46f32b 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_auth-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_auth-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_hover-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_hover-xl-screen-dark-mode-1.png index 8ccb65a327..afd1c49193 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_hover-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_hover-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_no-auth-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_no-auth-xl-screen-dark-mode-1.png index f1437bacce..64604d9ea8 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_no-auth-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_no-auth-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_with-highlighted-routes-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_with-highlighted-routes-xl-screen-dark-mode-1.png index 1efb64fae0..a700ec8dbe 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_with-highlighted-routes-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_dark-color-mode_with-highlighted-routes-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_auth-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_auth-xl-screen-dark-mode-1.png index 089d5a985d..534a1b22d6 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_auth-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_auth-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_hover-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_hover-xl-screen-dark-mode-1.png index 02922b2f28..4cc268661b 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_hover-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_hover-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_no-auth-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_no-auth-xl-screen-dark-mode-1.png index c5bb8f6d69..e10833c4b8 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_no-auth-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_no-auth-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-highlighted-routes-xl-screen-dark-mode-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-highlighted-routes-xl-screen-dark-mode-1.png index 2cca0d31a0..b9c1e08aa2 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-highlighted-routes-xl-screen-dark-mode-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-highlighted-routes-xl-screen-dark-mode-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-submenu-xl-screen-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-submenu-xl-screen-1.png index 4b8669777d..84db608a18 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-submenu-xl-screen-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-submenu-xl-screen-1.png differ diff --git a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-tooltips-1.png b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-tooltips-1.png index 54fcbfb516..f894cb00f4 100644 Binary files a/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-tooltips-1.png and b/ui/snippets/navigation/vertical/__screenshots__/NavigationDesktop.pw.tsx_default_with-tooltips-1.png differ diff --git a/ui/tokenTransfers/TokenTransfersListItem.tsx b/ui/tokenTransfers/TokenTransfersListItem.tsx new file mode 100644 index 0000000000..5db6021f04 --- /dev/null +++ b/ui/tokenTransfers/TokenTransfersListItem.tsx @@ -0,0 +1,110 @@ +import { Flex, Skeleton } from '@chakra-ui/react'; +import React from 'react'; + +import type { TokenTransfer } from 'types/api/tokenTransfer'; + +import getCurrencyValue from 'lib/getCurrencyValue'; +import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes'; +import Tag from 'ui/shared/chakra/Tag'; +import AddressEntity from 'ui/shared/entities/address/AddressEntity'; +import BlockEntity from 'ui/shared/entities/block/BlockEntity'; +import NftEntity from 'ui/shared/entities/nft/NftEntity'; +import TokenEntity from 'ui/shared/entities/token/TokenEntity'; +import TxEntity from 'ui/shared/entities/tx/TxEntity'; +import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid'; +import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip'; + +type Props = { + item: TokenTransfer; + isLoading: boolean; +} + +const TokenTransfersListItem = ({ item, isLoading }: Props) => { + + const { valueStr } = 'value' in item.total && item.total.value !== null ? getCurrencyValue({ + value: item.total.value, + exchangeRate: item.token.exchange_rate, + accuracy: 8, + accuracyUsd: 2, + decimals: item.total.decimals || '0', + }) : { valueStr: null }; + + return ( + + Txn hash + + + + + Age + + + + + { item.method && ( + <> + Method + { item.method } + + + ) } + + Block + + + + + From + + + + + To + + + + + { 'token_id' in item.total && (NFT_TOKEN_TYPE_IDS.includes(item.token.type)) && item.total.token_id !== null && ( + <> + Token ID + + + + + ) } + + { valueStr && (item.token.type === 'ERC-20' || item.token.type === 'ERC-1155') && ( + <> + Amount + + + + { valueStr } + + + + + + ) } + + ); +}; + +export default TokenTransfersListItem; diff --git a/ui/tokenTransfers/TokenTransfersTable.tsx b/ui/tokenTransfers/TokenTransfersTable.tsx new file mode 100644 index 0000000000..a6563976e4 --- /dev/null +++ b/ui/tokenTransfers/TokenTransfersTable.tsx @@ -0,0 +1,44 @@ +import { Table, Tbody, Tr, Th } from '@chakra-ui/react'; +import React from 'react'; + +import type { TokenTransfer } from 'types/api/tokenTransfer'; + +import { AddressHighlightProvider } from 'lib/contexts/addressHighlight'; +import { default as Thead } from 'ui/shared/TheadSticky'; +import TokenTransferTableItem from 'ui/tokenTransfers/TokenTransfersTableItem'; + +interface Props { + items?: Array; + top: number; + isLoading?: boolean; +} + +const TokenTransferTable = ({ items, top, isLoading }: Props) => { + return ( + + + + + + + + + + + + + + { items?.map((item, index) => ( + + )) } + +
Txn hashMethodBlockFrom/ToToken IDAmount
+
+ ); +}; + +export default React.memo(TokenTransferTable); diff --git a/ui/tokenTransfers/TokenTransfersTableItem.tsx b/ui/tokenTransfers/TokenTransfersTableItem.tsx new file mode 100644 index 0000000000..35b051d3e1 --- /dev/null +++ b/ui/tokenTransfers/TokenTransfersTableItem.tsx @@ -0,0 +1,97 @@ +import { Tr, Td, Flex, Skeleton } from '@chakra-ui/react'; +import React from 'react'; + +import type { TokenTransfer } from 'types/api/tokenTransfer'; + +import getCurrencyValue from 'lib/getCurrencyValue'; +import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes'; +import AddressFromTo from 'ui/shared/address/AddressFromTo'; +import Tag from 'ui/shared/chakra/Tag'; +import BlockEntity from 'ui/shared/entities/block/BlockEntity'; +import NftEntity from 'ui/shared/entities/nft/NftEntity'; +import TokenEntity from 'ui/shared/entities/token/TokenEntity'; +import TxEntity from 'ui/shared/entities/tx/TxEntity'; +import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip'; + +type Props = { + item: TokenTransfer; + isLoading?: boolean; +} + +const TokenTransferTableItem = ({ item, isLoading }: Props) => { + const { valueStr } = 'value' in item.total && item.total.value !== null ? getCurrencyValue({ + value: item.total.value, + exchangeRate: item.token.exchange_rate, + accuracy: 8, + accuracyUsd: 2, + decimals: item.total.decimals || '0', + }) : { valueStr: null }; + + return ( + + + + + + + { item.method && { item.method } } + + + + + + + + + { 'token_id' in item.total && (NFT_TOKEN_TYPE_IDS.includes(item.token.type)) && item.total.token_id !== null ? ( + + ) : '-' } + + + { valueStr ? ( + + + { valueStr } + + + + ) : '-' + } + + + ); +}; + +export default React.memo(TokenTransferTableItem); diff --git a/ui/txs/TxsTableItem.tsx b/ui/txs/TxsTableItem.tsx index c47d7a2395..476a480368 100644 --- a/ui/txs/TxsTableItem.tsx +++ b/ui/txs/TxsTableItem.tsx @@ -112,7 +112,7 @@ const TxsTableItem = ({ tx, showBlockInfo, currentAddress, enableTimeIncrement, ) } { !config.UI.views.tx.hiddenFields?.tx_fee && ( - +