Commit c01c4a8d authored by tom's avatar tom

rest of tx, address and block resources

parent 210c2ffb
...@@ -50,6 +50,9 @@ export const RESOURCES = { ...@@ -50,6 +50,9 @@ export const RESOURCES = {
paginationFields: [ 'block_number' as const, 'items_count' as const ], paginationFields: [ 'block_number' as const, 'items_count' as const ],
filterFields: [ 'type' as const ], filterFields: [ 'type' as const ],
}, },
block: {
path: '/api/v2/blocks/:id',
},
block_txs: { block_txs: {
path: '/api/v2/blocks/:id/transactions', path: '/api/v2/blocks/:id/transactions',
paginationFields: [ 'block_number' as const, 'items_count' as const, 'index' as const ], paginationFields: [ 'block_number' as const, 'items_count' as const, 'index' as const ],
...@@ -65,6 +68,9 @@ export const RESOURCES = { ...@@ -65,6 +68,9 @@ export const RESOURCES = {
paginationFields: [ 'filter' as const, 'hash' as const, 'inserted_at' as const ], paginationFields: [ 'filter' as const, 'hash' as const, 'inserted_at' as const ],
filterFields: [ 'filter' as const, 'type' as const, 'method' as const ], filterFields: [ 'filter' as const, 'type' as const, 'method' as const ],
}, },
tx: {
path: '/api/v2/transactions/:id',
},
tx_internal_txs: { tx_internal_txs: {
path: '/api/v2/transactions/:id/internal-transactions', path: '/api/v2/transactions/:id/internal-transactions',
paginationFields: [ 'block_number' as const, 'items_count' as const, 'transaction_hash' as const, 'index' as const, 'transaction_index' as const ], paginationFields: [ 'block_number' as const, 'items_count' as const, 'transaction_hash' as const, 'index' as const, 'transaction_index' as const ],
...@@ -80,8 +86,20 @@ export const RESOURCES = { ...@@ -80,8 +86,20 @@ export const RESOURCES = {
paginationFields: [ 'block_number' as const, 'items_count' as const, 'transaction_hash' as const, 'index' as const ], paginationFields: [ 'block_number' as const, 'items_count' as const, 'transaction_hash' as const, 'index' as const ],
filterFields: [ 'type' as const ], filterFields: [ 'type' as const ],
}, },
tx_raw_trace: {
path: '/api/v2/transactions/:id/raw-trace',
},
// ADDRESS // ADDRESS
address: {
path: '/api/v2/addresses/:id',
},
address_counters: {
path: '/api/v2/addresses/:id/counters',
},
address_token_balances: {
path: '/api/v2/addresses/:id/token-balances',
},
address_txs: { address_txs: {
path: '/api/v2/addresses/:id/transactions', path: '/api/v2/addresses/:id/transactions',
paginationFields: [ 'block_number' as const, 'items_count' as const, 'index' as const ], paginationFields: [ 'block_number' as const, 'items_count' as const, 'index' as const ],
......
...@@ -3,25 +3,29 @@ import { useQuery } from '@tanstack/react-query'; ...@@ -3,25 +3,29 @@ import { useQuery } from '@tanstack/react-query';
import type { UserInfo, CustomAbis, PublicTags, AddressTags, TransactionTags, ApiKeys, WatchlistAddress } from 'types/api/account'; import type { UserInfo, CustomAbis, PublicTags, AddressTags, TransactionTags, ApiKeys, WatchlistAddress } from 'types/api/account';
import type { import type {
Address,
AddressCounters,
AddressTokenBalance,
AddressTransactionsResponse, AddressTransactionsResponse,
AddressTokenTransferResponse, AddressTokenTransferResponse,
AddressCoinBalanceHistoryResponse, AddressCoinBalanceHistoryResponse,
AddressBlocksValidatedResponse, AddressBlocksValidatedResponse,
AddressInternalTxsResponse, AddressInternalTxsResponse,
} from 'types/api/address'; } from 'types/api/address';
import type { BlocksResponse, BlockTransactionsResponse } from 'types/api/block'; import type { BlocksResponse, BlockTransactionsResponse, Block } from 'types/api/block';
import type { InternalTransactionsResponse } from 'types/api/internalTransaction'; import type { InternalTransactionsResponse } from 'types/api/internalTransaction';
import type { LogsResponse } from 'types/api/log'; import type { LogsResponse } from 'types/api/log';
import type { RawTracesResponse } from 'types/api/rawTrace';
import type { Stats, Charts } from 'types/api/stats'; import type { Stats, Charts } from 'types/api/stats';
import type { TokenTransferResponse } from 'types/api/tokenTransfer'; import type { TokenTransferResponse } from 'types/api/tokenTransfer';
import type { TransactionsResponseValidated, TransactionsResponsePending } from 'types/api/transaction'; import type { TransactionsResponseValidated, TransactionsResponsePending, Transaction } from 'types/api/transaction';
import type { ResourceError, ResourceName } from './resources'; import type { ResourceError, ResourceName } from './resources';
import type { Params as ApiFetchParams } from './useApiFetch'; import type { Params as ApiFetchParams } from './useApiFetch';
import useApiFetch from './useApiFetch'; import useApiFetch from './useApiFetch';
export interface Params<R extends ResourceName> extends ApiFetchParams { export interface Params<R extends ResourceName, E = unknown> extends ApiFetchParams {
queryOptions?: Omit<UseQueryOptions<unknown, ResourceError, ResourcePayload<R>>, 'queryKey' | 'queryFn'>; queryOptions?: Omit<UseQueryOptions<unknown, ResourceError<E>, ResourcePayload<R>>, 'queryKey' | 'queryFn'>;
} }
export function getResourceKey<R extends ResourceName>(resource: R, { pathParams, queryParams }: Params<R> = {}) { export function getResourceKey<R extends ResourceName>(resource: R, { pathParams, queryParams }: Params<R> = {}) {
...@@ -32,39 +36,47 @@ export function getResourceKey<R extends ResourceName>(resource: R, { pathParams ...@@ -32,39 +36,47 @@ export function getResourceKey<R extends ResourceName>(resource: R, { pathParams
return [ resource ]; return [ resource ];
} }
export default function useApiQuery<R extends ResourceName>( export default function useApiQuery<R extends ResourceName, E = unknown>(
resource: R, resource: R,
{ queryOptions, pathParams, queryParams, fetchParams }: Params<R> = {}, { queryOptions, pathParams, queryParams, fetchParams }: Params<R, E> = {},
) { ) {
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
return useQuery<unknown, ResourceError, ResourcePayload<R>>( return useQuery<unknown, ResourceError<E>, ResourcePayload<R>>(
getResourceKey(resource, { pathParams, queryParams }), getResourceKey(resource, { pathParams, queryParams }),
async() => { async() => {
return apiFetch<R, ResourcePayload<R>, ResourceError>(resource, { pathParams, queryParams, fetchParams }); return apiFetch<R, ResourcePayload<R>, ResourceError>(resource, { pathParams, queryParams, fetchParams });
}, queryOptions); }, queryOptions);
} }
/* eslint-disable @typescript-eslint/indent */
export type ResourcePayload<Q extends ResourceName> = export type ResourcePayload<Q extends ResourceName> =
Q extends 'user_info' ? UserInfo : Q extends 'user_info' ? UserInfo :
Q extends 'custom_abi' ? CustomAbis : Q extends 'custom_abi' ? CustomAbis :
Q extends 'public_tags' ? PublicTags : Q extends 'public_tags' ? PublicTags :
Q extends 'private_tags_address' ? AddressTags : Q extends 'private_tags_address' ? AddressTags :
Q extends 'private_tags_tx' ? TransactionTags : Q extends 'private_tags_tx' ? TransactionTags :
Q extends 'api_keys' ? ApiKeys : Q extends 'api_keys' ? ApiKeys :
Q extends 'watchlist' ? Array<WatchlistAddress> : Q extends 'watchlist' ? Array<WatchlistAddress> :
Q extends 'stats_counters' ? Stats : Q extends 'stats_counters' ? Stats :
Q extends 'stats_charts' ? Charts : Q extends 'stats_charts' ? Charts :
Q extends 'blocks' ? BlocksResponse : Q extends 'blocks' ? BlocksResponse :
Q extends 'block_txs' ? BlockTransactionsResponse : Q extends 'block' ? Block :
Q extends 'txs_validated' ? TransactionsResponseValidated : Q extends 'block_txs' ? BlockTransactionsResponse :
Q extends 'txs_pending' ? TransactionsResponsePending : Q extends 'txs_validated' ? TransactionsResponseValidated :
Q extends 'tx_internal_txs' ? InternalTransactionsResponse : Q extends 'txs_pending' ? TransactionsResponsePending :
Q extends 'tx_logs' ? LogsResponse : Q extends 'tx' ? Transaction :
Q extends 'tx_token_transfers' ? TokenTransferResponse : Q extends 'tx_internal_txs' ? InternalTransactionsResponse :
Q extends 'address_txs' ? AddressTransactionsResponse : Q extends 'tx_logs' ? LogsResponse :
Q extends 'address_internal_txs' ? AddressInternalTxsResponse : Q extends 'tx_token_transfers' ? TokenTransferResponse :
Q extends 'address_token_transfers' ? AddressTokenTransferResponse : Q extends 'tx_raw_trace' ? RawTracesResponse :
Q extends 'address_blocks_validated' ? AddressBlocksValidatedResponse : Q extends 'address' ? Address :
Q extends 'address_coin_balance' ? AddressCoinBalanceHistoryResponse : Q extends 'address_counters' ? AddressCounters :
never; Q extends 'address_token_balances' ? Array<AddressTokenBalance> :
Q extends 'address_txs' ? AddressTransactionsResponse :
Q extends 'address_internal_txs' ? AddressInternalTxsResponse :
Q extends 'address_token_transfers' ? AddressTokenTransferResponse :
Q extends 'address_blocks_validated' ? AddressBlocksValidatedResponse :
Q extends 'address_coin_balance' ? AddressCoinBalanceHistoryResponse :
never;
/* eslint-enable @typescript-eslint/indent */
...@@ -4,16 +4,9 @@ export enum QueryKeys { ...@@ -4,16 +4,9 @@ export enum QueryKeys {
indexingStatus='indexingStatus', indexingStatus='indexingStatus',
stats='stats', stats='stats',
charts='stats', charts='stats',
tx = 'tx',
txRawTrace = 'tx-raw-trace',
block = 'block',
chartsTxs = 'charts-txs', chartsTxs = 'charts-txs',
chartsMarket = 'charts-market', chartsMarket = 'charts-market',
indexBlocks='indexBlocks', indexBlocks='indexBlocks',
indexTxs='indexTxs', indexTxs='indexTxs',
jsonRpcUrl='json-rpc-url', jsonRpcUrl='json-rpc-url',
address='address',
addressCounters='address-counters',
addressTokenBalances='address-token-balances',
addressCoinBalanceHistoryByDay='address-coin-balance-history-by-day',
} }
import { Box, Flex, Text, Icon, Grid, Link } from '@chakra-ui/react'; import { Box, Flex, Text, Icon, Grid, Link } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Address as TAddress, AddressCounters, AddressTokenBalance } from 'types/api/address'; import type { Address as TAddress } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import blockIcon from 'icons/block.svg'; import blockIcon from 'icons/block.svg';
import useFetch from 'lib/hooks/useFetch'; import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import link from 'lib/link/link'; import link from 'lib/link/link';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
...@@ -35,24 +33,20 @@ interface Props { ...@@ -35,24 +33,20 @@ interface Props {
const AddressDetails = ({ addressQuery }: Props) => { const AddressDetails = ({ addressQuery }: Props) => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const countersQuery = useQuery<unknown, unknown, AddressCounters>( const countersQuery = useApiQuery('address_counters', {
[ QueryKeys.addressCounters, router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/addresses/${ router.query.id }/counters`), queryOptions: {
{
enabled: Boolean(router.query.id) && Boolean(addressQuery.data), enabled: Boolean(router.query.id) && Boolean(addressQuery.data),
}, },
); });
const tokenBalancesQuery = useApiQuery('address_token_balances', {
const tokenBalancesQuery = useQuery<unknown, unknown, Array<AddressTokenBalance>>( pathParams: { id: router.query.id?.toString() },
[ QueryKeys.addressTokenBalances, router.query.id ], queryOptions: {
async() => await fetch(`/node-api/addresses/${ router.query.id }/token-balances`),
{
enabled: Boolean(router.query.id) && Boolean(addressQuery.data), enabled: Boolean(router.query.id) && Boolean(addressQuery.data),
}, },
); });
if (countersQuery.isLoading || addressQuery.isLoading || tokenBalancesQuery.isLoading) { if (countersQuery.isLoading || addressQuery.isLoading || tokenBalancesQuery.isLoading) {
return <AddressDetailsSkeleton/>; return <AddressDetailsSkeleton/>;
......
...@@ -3,9 +3,9 @@ import React from 'react'; ...@@ -3,9 +3,9 @@ import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { Address } from 'types/api/address'; import type { Address } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import { getResourceKey } from 'lib/api/useApiQuery';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import CurrencyValue from 'ui/shared/CurrencyValue'; import CurrencyValue from 'ui/shared/CurrencyValue';
...@@ -26,7 +26,8 @@ const AddressBalance = ({ data }: Props) => { ...@@ -26,7 +26,8 @@ const AddressBalance = ({ data }: Props) => {
} }
setLastBlockNumber(blockNumber); setLastBlockNumber(blockNumber);
queryClient.setQueryData([ QueryKeys.address, data.hash ], (prevData: Address | undefined) => { const queryKey = getResourceKey('address', { pathParams: { id: data.hash } });
queryClient.setQueryData(queryKey, (prevData: Address | undefined) => {
if (!prevData) { if (!prevData) {
return; return;
} }
......
...@@ -4,12 +4,11 @@ import { useRouter } from 'next/router'; ...@@ -4,12 +4,11 @@ import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { UserInfo } from 'types/api/account'; import type { UserInfo } from 'types/api/account';
import { QueryKeys } from 'types/client/queries';
import starFilledIcon from 'icons/star_filled.svg'; import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg'; import starOutlineIcon from 'icons/star_outline.svg';
import { resourceKey } from 'lib/api/resources'; import { resourceKey } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useLoginUrl from 'lib/hooks/useLoginUrl'; import useLoginUrl from 'lib/hooks/useLoginUrl';
import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing'; import usePreventFocusAfterModalClosing from 'lib/hooks/usePreventFocusAfterModalClosing';
import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal'; import WatchlistAddModal from 'ui/watchlist/AddressModal/AddressModal';
...@@ -42,7 +41,8 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => { ...@@ -42,7 +41,8 @@ const AddressFavoriteButton = ({ className, hash, isAdded }: Props) => {
}, [ addModalProps, deleteModalProps, isAdded, isAuth, loginUrl ]); }, [ addModalProps, deleteModalProps, isAdded, isAuth, loginUrl ]);
const handleAddOrDeleteSuccess = React.useCallback(async() => { const handleAddOrDeleteSuccess = React.useCallback(async() => {
await queryClient.refetchQueries({ queryKey: [ QueryKeys.address, router.query.id ] }); const queryKey = getResourceKey('address', { pathParams: { id: router.query.id?.toString() } });
await queryClient.refetchQueries({ queryKey });
addModalProps.onClose(); addModalProps.onClose();
}, [ addModalProps, queryClient, router.query.id ]); }, [ addModalProps, queryClient, router.query.id ]);
......
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import { QueryKeys } from 'types/client/queries'; import useApiQuery from 'lib/api/useApiQuery';
import useFetch from 'lib/hooks/useFetch';
const MockAddressPage = ({ children }: { children: JSX.Element }): JSX.Element => { const MockAddressPage = ({ children }: { children: JSX.Element }): JSX.Element => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const { data } = useQuery( const { data } = useApiQuery('address', {
[ QueryKeys.address, router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/addresses/${ router.query.id }`), queryOptions: { enabled: Boolean(router.query.id) },
{ });
enabled: Boolean(router.query.id),
},
);
if (!data) { if (!data) {
return <div/>; return <div/>;
......
import { Box, Flex, Icon, IconButton, Skeleton, Tooltip } from '@chakra-ui/react'; import { Box, Flex, Icon, IconButton, Skeleton, Tooltip } from '@chakra-ui/react';
import { useQuery, useQueryClient, useIsFetching } from '@tanstack/react-query'; import { useQueryClient, useIsFetching } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { Address, AddressTokenBalance } from 'types/api/address'; import type { Address } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import walletIcon from 'icons/wallet.svg'; import walletIcon from 'icons/wallet.svg';
import useFetch from 'lib/hooks/useFetch'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
...@@ -18,21 +17,20 @@ import TokenSelectMobile from './TokenSelectMobile'; ...@@ -18,21 +17,20 @@ import TokenSelectMobile from './TokenSelectMobile';
const TokenSelect = () => { const TokenSelect = () => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [ blockNumber, setBlockNumber ] = React.useState<number>(); const [ blockNumber, setBlockNumber ] = React.useState<number>();
const addressQueryData = queryClient.getQueryData<Address>([ QueryKeys.address, router.query.id ]); const addressResourceKey = getResourceKey('address', { pathParams: { id: router.query.id?.toString() } });
const { data, isError, isLoading, refetch } = useQuery<unknown, unknown, Array<AddressTokenBalance>>( const addressQueryData = queryClient.getQueryData<Address>(addressResourceKey);
[ QueryKeys.addressTokenBalances, addressQueryData?.hash ],
async() => await fetch(`/node-api/addresses/${ addressQueryData?.hash }/token-balances`), const { data, isError, isLoading, refetch } = useApiQuery('address_token_balances', {
{ pathParams: { id: addressQueryData?.hash },
enabled: Boolean(addressQueryData), queryOptions: { enabled: Boolean(addressQueryData) },
}, });
); const balancesResourceKey = getResourceKey('address_token_balances', { pathParams: { id: addressQueryData?.hash } });
const balancesIsFetching = useIsFetching({ queryKey: [ QueryKeys.addressTokenBalances, addressQueryData?.hash ] }); const balancesIsFetching = useIsFetching({ queryKey: balancesResourceKey });
const handleTokenBalanceMessage: SocketMessage.AddressTokenBalance['handler'] = React.useCallback((payload) => { const handleTokenBalanceMessage: SocketMessage.AddressTokenBalance['handler'] = React.useCallback((payload) => {
if (payload.block_number !== blockNumber) { if (payload.block_number !== blockNumber) {
......
import { Grid, GridItem, Text, Icon, Link, Box, Tooltip } from '@chakra-ui/react'; import { Grid, GridItem, Text, Icon, Link, Box, Tooltip } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import capitalize from 'lodash/capitalize'; import capitalize from 'lodash/capitalize';
import NextLink from 'next/link'; import NextLink from 'next/link';
...@@ -7,17 +6,13 @@ import { useRouter } from 'next/router'; ...@@ -7,17 +6,13 @@ import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import { scroller, Element } from 'react-scroll'; import { scroller, Element } from 'react-scroll';
import type { Block } from 'types/api/block';
import { QueryKeys } from 'types/client/queries';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import clockIcon from 'icons/clock.svg'; import clockIcon from 'icons/clock.svg';
import flameIcon from 'icons/flame.svg'; import flameIcon from 'icons/flame.svg';
import type { ResourceError } from 'lib/api/resources'; import useApiQuery from 'lib/api/useApiQuery';
import getBlockReward from 'lib/block/getBlockReward'; import getBlockReward from 'lib/block/getBlockReward';
import { WEI, WEI_IN_GWEI, ZERO } from 'lib/consts'; import { WEI, WEI_IN_GWEI, ZERO } from 'lib/consts';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import useFetch from 'lib/hooks/useFetch';
import { space } from 'lib/html-entities'; import { space } from 'lib/html-entities';
import link from 'lib/link/link'; import link from 'lib/link/link';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
...@@ -35,15 +30,11 @@ import Utilization from 'ui/shared/Utilization/Utilization'; ...@@ -35,15 +30,11 @@ import Utilization from 'ui/shared/Utilization/Utilization';
const BlockDetails = () => { const BlockDetails = () => {
const [ isExpanded, setIsExpanded ] = React.useState(false); const [ isExpanded, setIsExpanded ] = React.useState(false);
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const { data, isLoading, isError, error } = useQuery<unknown, ResourceError<{ status: number }>, Block>( const { data, isLoading, isError, error } = useApiQuery<'block', { status: number }>('block', {
[ QueryKeys.block, router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/blocks/${ router.query.id }`), queryOptions: { enabled: Boolean(router.query.id) },
{ });
enabled: Boolean(router.query.id),
},
);
const handleCutClick = React.useCallback(() => { const handleCutClick = React.useCallback(() => {
setIsExpanded((flag) => !flag); setIsExpanded((flag) => !flag);
......
import { Flex, Tag } from '@chakra-ui/react'; import { Flex, Tag } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Address } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import type { RoutedTab } from 'ui/shared/RoutedTabs/types'; import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import useFetch from 'lib/hooks/useFetch'; import useApiQuery from 'lib/api/useApiQuery';
import AddressBlocksValidated from 'ui/address/AddressBlocksValidated'; import AddressBlocksValidated from 'ui/address/AddressBlocksValidated';
import AddressCoinBalance from 'ui/address/AddressCoinBalance'; import AddressCoinBalance from 'ui/address/AddressCoinBalance';
import AddressDetails from 'ui/address/AddressDetails'; import AddressDetails from 'ui/address/AddressDetails';
...@@ -20,15 +17,11 @@ import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs'; ...@@ -20,15 +17,11 @@ import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs';
const AddressPageContent = () => { const AddressPageContent = () => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const addressQuery = useQuery<unknown, unknown, Address>( const addressQuery = useApiQuery('address', {
[ QueryKeys.address, router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/addresses/${ router.query.id }`), queryOptions: { enabled: Boolean(router.query.id) },
{ });
enabled: Boolean(router.query.id),
},
);
const tags = [ const tags = [
...(addressQuery.data?.private_tags || []), ...(addressQuery.data?.private_tags || []),
......
import { Flex, Link, Icon, Tag, Tooltip } from '@chakra-ui/react'; import { Flex, Link, Icon, Tag, Tooltip } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Transaction } from 'types/api/transaction';
import type { RoutedTab } from 'ui/shared/RoutedTabs/types'; import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import eastArrowIcon from 'icons/arrows/east.svg'; import eastArrowIcon from 'icons/arrows/east.svg';
import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/appContext'; import { useAppContext } from 'lib/appContext';
import useFetch from 'lib/hooks/useFetch';
import isBrowser from 'lib/isBrowser'; import isBrowser from 'lib/isBrowser';
import networkExplorers from 'lib/networks/networkExplorers'; import networkExplorers from 'lib/networks/networkExplorers';
import AdBanner from 'ui/shared/ad/AdBanner'; import AdBanner from 'ui/shared/ad/AdBanner';
...@@ -35,7 +33,6 @@ const TABS: Array<RoutedTab> = [ ...@@ -35,7 +33,6 @@ const TABS: Array<RoutedTab> = [
const TransactionPageContent = () => { const TransactionPageContent = () => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const appProps = useAppContext(); const appProps = useAppContext();
const isInBrowser = isBrowser(); const isInBrowser = isBrowser();
...@@ -43,13 +40,10 @@ const TransactionPageContent = () => { ...@@ -43,13 +40,10 @@ const TransactionPageContent = () => {
const hasGoBackLink = referrer && referrer.includes('/txs'); const hasGoBackLink = referrer && referrer.includes('/txs');
const { data } = useQuery<unknown, unknown, Transaction>( const { data } = useApiQuery('tx', {
[ 'tx', router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/transactions/${ router.query.id }`), queryOptions: { enabled: Boolean(router.query.id) },
{ });
enabled: Boolean(router.query.id),
},
);
const explorersLinks = networkExplorers const explorersLinks = networkExplorers
.filter((explorer) => explorer.paths.tx) .filter((explorer) => explorer.paths.tx)
......
...@@ -53,6 +53,7 @@ const TokenTransfer = <Resource extends 'tx_token_transfers' | 'address_token_tr ...@@ -53,6 +53,7 @@ const TokenTransfer = <Resource extends 'tx_token_transfers' | 'address_token_tr
baseAddress, baseAddress,
showTxInfo = true, showTxInfo = true,
enableTimeIncrement, enableTimeIncrement,
pathParams,
}: Props<Resource>) => { }: Props<Resource>) => {
const router = useRouter(); const router = useRouter();
const [ filters, setFilters ] = React.useState<AddressTokenTransferFilters & TokenTransferFilters>( const [ filters, setFilters ] = React.useState<AddressTokenTransferFilters & TokenTransferFilters>(
...@@ -61,6 +62,7 @@ const TokenTransfer = <Resource extends 'tx_token_transfers' | 'address_token_tr ...@@ -61,6 +62,7 @@ const TokenTransfer = <Resource extends 'tx_token_transfers' | 'address_token_tr
const { isError, isLoading, data, pagination, onFilterChange, isPaginationVisible } = useQueryWithPages({ const { isError, isLoading, data, pagination, onFilterChange, isPaginationVisible } = useQueryWithPages({
resourceName, resourceName,
pathParams,
options: { enabled: !isDisabled }, options: { enabled: !isDisabled },
filters: filters as PaginationFiltersX<Resource>, filters: filters as PaginationFiltersX<Resource>,
scroll: { elem: SCROLL_ELEM, offset: SCROLL_OFFSET }, scroll: { elem: SCROLL_ELEM, offset: SCROLL_OFFSET },
......
import { Flex, Textarea, Skeleton } from '@chakra-ui/react'; import { Flex, Textarea, Skeleton } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { RawTracesResponse } from 'types/api/rawTrace'; import useApiQuery from 'lib/api/useApiQuery';
import { QueryKeys } from 'types/client/queries';
import { SECOND } from 'lib/consts'; import { SECOND } from 'lib/consts';
import useFetch from 'lib/hooks/useFetch';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import TxPendingAlert from 'ui/tx/TxPendingAlert'; import TxPendingAlert from 'ui/tx/TxPendingAlert';
...@@ -16,16 +12,14 @@ import useFetchTxInfo from 'ui/tx/useFetchTxInfo'; ...@@ -16,16 +12,14 @@ import useFetchTxInfo from 'ui/tx/useFetchTxInfo';
const TxRawTrace = () => { const TxRawTrace = () => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const txInfo = useFetchTxInfo({ updateDelay: 5 * SECOND }); const txInfo = useFetchTxInfo({ updateDelay: 5 * SECOND });
const { data, isLoading, isError } = useQuery<unknown, unknown, RawTracesResponse>( const { data, isLoading, isError } = useApiQuery('tx_raw_trace', {
[ QueryKeys.txRawTrace, router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/transactions/${ router.query.id }/raw-trace`), queryOptions: {
{
enabled: Boolean(router.query.id) && Boolean(txInfo.data?.status), enabled: Boolean(router.query.id) && Boolean(txInfo.data?.status),
}, },
); });
if (!txInfo.isLoading && !txInfo.isError && !txInfo.data.status) { if (!txInfo.isLoading && !txInfo.isError && !txInfo.data.status) {
return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>; return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>;
......
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { Transaction } from 'types/api/transaction'; import type { Transaction } from 'types/api/transaction';
import { QueryKeys } from 'types/client/queries';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import delay from 'lib/delay'; import delay from 'lib/delay';
import useFetch from 'lib/hooks/useFetch';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
...@@ -23,23 +22,23 @@ type ReturnType = UseQueryResult<Transaction, unknown> & { ...@@ -23,23 +22,23 @@ type ReturnType = UseQueryResult<Transaction, unknown> & {
export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params | undefined = {}): ReturnType { export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params | undefined = {}): ReturnType {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [ socketStatus, setSocketStatus ] = React.useState<'close' | 'error'>(); const [ socketStatus, setSocketStatus ] = React.useState<'close' | 'error'>();
const queryResult = useQuery<unknown, unknown, Transaction>( const queryResult = useApiQuery('tx', {
[ QueryKeys.tx, router.query.id ], pathParams: { id: router.query.id?.toString() },
async() => await fetch(`/node-api/transactions/${ router.query.id }`), queryOptions: {
{
enabled: Boolean(router.query.id), enabled: Boolean(router.query.id),
refetchOnMount: false, refetchOnMount: false,
}, },
); });
const { data, isError, isLoading } = queryResult; const { data, isError, isLoading } = queryResult;
const handleStatusUpdateMessage: SocketMessage.TxStatusUpdate['handler'] = React.useCallback(async() => { const handleStatusUpdateMessage: SocketMessage.TxStatusUpdate['handler'] = React.useCallback(async() => {
updateDelay && await delay(updateDelay); updateDelay && await delay(updateDelay);
queryClient.invalidateQueries({ queryKey: [ QueryKeys.tx, router.query.id ] }); queryClient.invalidateQueries({
queryKey: getResourceKey('tx', { pathParams: { id: router.query.id?.toString() } }),
});
onTxStatusUpdate?.(); onTxStatusUpdate?.();
}, [ onTxStatusUpdate, queryClient, router.query.id, updateDelay ]); }, [ onTxStatusUpdate, queryClient, router.query.id, updateDelay ]);
......
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