Commit e6e1639e authored by isstuev's avatar isstuev

get tokens info from watchlist responce

parent 7fee6df6
...@@ -480,9 +480,6 @@ export const RESOURCES = { ...@@ -480,9 +480,6 @@ export const RESOURCES = {
}, },
// DEPRECATED // DEPRECATED
old_api: {
path: '/api',
},
csv_export_txs: { csv_export_txs: {
path: '/transactions-csv', path: '/transactions-csv',
}, },
......
import type { PublicTag, AddressTag, TransactionTag, ApiKey, CustomAbi, VerifiedAddress, TokenInfoApplication } from 'types/api/account'; import type { PublicTag, AddressTag, TransactionTag, ApiKey, CustomAbi, VerifiedAddress, TokenInfoApplication, WatchlistAddress } from 'types/api/account';
import type { TWatchlistItem } from 'types/client/account';
import { ADDRESS_PARAMS, ADDRESS_HASH } from './addressParams'; import { ADDRESS_PARAMS, ADDRESS_HASH } from './addressParams';
import { TX_HASH } from './tx'; import { TX_HASH } from './tx';
...@@ -30,7 +29,7 @@ export const PUBLIC_TAG: PublicTag = { ...@@ -30,7 +29,7 @@ export const PUBLIC_TAG: PublicTag = {
website: 'example.com', website: 'example.com',
}; };
export const WATCH_LIST_ITEM_WITH_TOKEN_INFO: TWatchlistItem = { export const WATCH_LIST_ITEM_WITH_TOKEN_INFO: WatchlistAddress = {
address: ADDRESS_PARAMS, address: ADDRESS_PARAMS,
address_balance: '7072643779453701031672', address_balance: '7072643779453701031672',
address_hash: ADDRESS_HASH, address_hash: ADDRESS_HASH,
...@@ -55,6 +54,8 @@ export const WATCH_LIST_ITEM_WITH_TOKEN_INFO: TWatchlistItem = { ...@@ -55,6 +54,8 @@ export const WATCH_LIST_ITEM_WITH_TOKEN_INFO: TWatchlistItem = {
}, },
}, },
tokens_count: 42, tokens_count: 42,
tokens_fiat_value: '12345',
tokens_overflow: false,
}; };
export const API_KEY: ApiKey = { export const API_KEY: ApiKey = {
......
...@@ -66,12 +66,9 @@ export interface WatchlistAddress { ...@@ -66,12 +66,9 @@ export interface WatchlistAddress {
notification_methods: NotificationMethods; notification_methods: NotificationMethods;
id: string; id: string;
address: AddressParam; address: AddressParam;
} tokens_count: number;
tokens_fiat_value: string;
export interface WatchlistTokensResponse { tokens_overflow: boolean;
message: string;
result?: Array<unknown>;
status: string;
} }
export interface WatchlistAddressNew { export interface WatchlistAddressNew {
......
import type { WatchlistAddress } from '../api/account';
export type TWatchlistItem = WatchlistAddress & {tokens_count: number};
export type TWatchlist = Array<TWatchlistItem>;
export interface CsrfData { export interface CsrfData {
token: string; token: string;
} }
import { Box, Button, Skeleton, useDisclosure } from '@chakra-ui/react'; import { Box, Button, Skeleton, useDisclosure } from '@chakra-ui/react';
import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import type { WatchlistAddress, WatchlistTokensResponse } from 'types/api/account'; import type { WatchlistAddress } from 'types/api/account';
import type { TWatchlist, TWatchlistItem } from 'types/client/account';
import type { ResourceError } from 'lib/api/resources';
import { resourceKey } from 'lib/api/resources'; import { resourceKey } from 'lib/api/resources';
import useApiFetch from 'lib/api/useApiFetch'; import useApiQuery from 'lib/api/useApiQuery';
import useRedirectForInvalidAuthToken from 'lib/hooks/useRedirectForInvalidAuthToken'; import useRedirectForInvalidAuthToken from 'lib/hooks/useRedirectForInvalidAuthToken';
import { WATCH_LIST_ITEM_WITH_TOKEN_INFO } from 'stubs/account'; import { WATCH_LIST_ITEM_WITH_TOKEN_INFO } from 'stubs/account';
import AccountPageDescription from 'ui/shared/AccountPageDescription'; import AccountPageDescription from 'ui/shared/AccountPageDescription';
...@@ -19,45 +17,21 @@ import WatchListItem from 'ui/watchlist/WatchlistTable/WatchListItem'; ...@@ -19,45 +17,21 @@ import WatchListItem from 'ui/watchlist/WatchlistTable/WatchListItem';
import WatchlistTable from 'ui/watchlist/WatchlistTable/WatchlistTable'; import WatchlistTable from 'ui/watchlist/WatchlistTable/WatchlistTable';
const WatchList: React.FC = () => { const WatchList: React.FC = () => {
const apiFetch = useApiFetch(); const { data, isPlaceholderData, isError } = useApiQuery('watchlist', {
const { data, isPlaceholderData, isError } = useQuery<unknown, ResourceError, TWatchlist>( queryOptions: {
[ resourceKey('watchlist') ],
async() => {
const watchlistAddresses = await apiFetch<'watchlist', Array<WatchlistAddress>>('watchlist');
if (!Array.isArray(watchlistAddresses)) {
return;
}
const watchlistTokens = await Promise.all(watchlistAddresses.map(({ address }) => {
if (!address?.hash) {
return Promise.resolve(0);
}
return apiFetch<'old_api', WatchlistTokensResponse>('old_api', { queryParams: { address: address.hash, module: 'account', action: 'tokenlist' } })
.then((response) => {
if ('result' in response && Array.isArray(response.result)) {
return response.result.length;
}
return 0;
});
}));
return watchlistAddresses.map((item, index) => ({ ...item, tokens_count: watchlistTokens[index] }));
},
{
placeholderData: Array(3).fill(WATCH_LIST_ITEM_WITH_TOKEN_INFO), placeholderData: Array(3).fill(WATCH_LIST_ITEM_WITH_TOKEN_INFO),
}, },
); });
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const addressModalProps = useDisclosure(); const addressModalProps = useDisclosure();
const deleteModalProps = useDisclosure(); const deleteModalProps = useDisclosure();
useRedirectForInvalidAuthToken(); useRedirectForInvalidAuthToken();
const [ addressModalData, setAddressModalData ] = useState<TWatchlistItem>(); const [ addressModalData, setAddressModalData ] = useState<WatchlistAddress>();
const [ deleteModalData, setDeleteModalData ] = useState<TWatchlistItem>(); const [ deleteModalData, setDeleteModalData ] = useState<WatchlistAddress>();
const onEditClick = useCallback((data: TWatchlistItem) => { const onEditClick = useCallback((data: WatchlistAddress) => {
setAddressModalData(data); setAddressModalData(data);
addressModalProps.onOpen(); addressModalProps.onOpen();
}, [ addressModalProps ]); }, [ addressModalProps ]);
...@@ -73,7 +47,7 @@ const WatchList: React.FC = () => { ...@@ -73,7 +47,7 @@ const WatchList: React.FC = () => {
addressModalProps.onClose(); addressModalProps.onClose();
}, [ addressModalProps, queryClient ]); }, [ addressModalProps, queryClient ]);
const onDeleteClick = useCallback((data: TWatchlistItem) => { const onDeleteClick = useCallback((data: WatchlistAddress) => {
setDeleteModalData(data); setDeleteModalData(data);
deleteModalProps.onOpen(); deleteModalProps.onOpen();
}, [ deleteModalProps ]); }, [ deleteModalProps ]);
...@@ -84,7 +58,7 @@ const WatchList: React.FC = () => { ...@@ -84,7 +58,7 @@ const WatchList: React.FC = () => {
}, [ deleteModalProps ]); }, [ deleteModalProps ]);
const onDeleteSuccess = useCallback(async() => { const onDeleteSuccess = useCallback(async() => {
queryClient.setQueryData([ resourceKey('watchlist') ], (prevData: TWatchlist | undefined) => { queryClient.setQueryData([ resourceKey('watchlist') ], (prevData: Array<WatchlistAddress> | undefined) => {
return prevData?.filter((item) => item.id !== deleteModalData?.id); return prevData?.filter((item) => item.id !== deleteModalData?.id);
}); });
}, [ deleteModalData?.id, queryClient ]); }, [ deleteModalData?.id, queryClient ]);
......
...@@ -9,8 +9,7 @@ import React, { useCallback, useState } from 'react'; ...@@ -9,8 +9,7 @@ import React, { useCallback, useState } from 'react';
import type { SubmitHandler, ControllerRenderProps } from 'react-hook-form'; import type { SubmitHandler, ControllerRenderProps } from 'react-hook-form';
import { useForm, Controller } from 'react-hook-form'; import { useForm, Controller } from 'react-hook-form';
import type { WatchlistErrors } from 'types/api/account'; import type { WatchlistAddress, WatchlistErrors } from 'types/api/account';
import type { TWatchlistItem } from 'types/client/account';
import type { ResourceErrorAccount } from 'lib/api/resources'; import type { ResourceErrorAccount } from 'lib/api/resources';
import useApiFetch from 'lib/api/useApiFetch'; import useApiFetch from 'lib/api/useApiFetch';
...@@ -28,7 +27,7 @@ const NOTIFICATIONS = [ 'native', 'ERC-20', 'ERC-721' ] as const; ...@@ -28,7 +27,7 @@ const NOTIFICATIONS = [ 'native', 'ERC-20', 'ERC-721' ] as const;
const TAG_MAX_LENGTH = 35; const TAG_MAX_LENGTH = 35;
type Props = { type Props = {
data?: Partial<TWatchlistItem>; data?: Partial<WatchlistAddress>;
onSuccess: () => Promise<void>; onSuccess: () => Promise<void>;
setAlertVisible: (isAlertVisible: boolean) => void; setAlertVisible: (isAlertVisible: boolean) => void;
isAdd: boolean; isAdd: boolean;
......
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import type { TWatchlistItem } from 'types/client/account'; import type { WatchlistAddress } from 'types/api/account';
import FormModal from 'ui/shared/FormModal'; import FormModal from 'ui/shared/FormModal';
...@@ -11,7 +11,7 @@ type Props = { ...@@ -11,7 +11,7 @@ type Props = {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onSuccess: () => Promise<void>; onSuccess: () => Promise<void>;
data?: Partial<TWatchlistItem>; data?: Partial<WatchlistAddress>;
} }
const AddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data, isAdd }) => { const AddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data, isAdd }) => {
...@@ -25,7 +25,7 @@ const AddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data, isAdd ...@@ -25,7 +25,7 @@ const AddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data, isAdd
}, [ data, isAdd, onSuccess ]); }, [ data, isAdd, onSuccess ]);
return ( return (
<FormModal<TWatchlistItem> <FormModal<WatchlistAddress>
isOpen={ isOpen } isOpen={ isOpen }
onClose={ onClose } onClose={ onClose }
title={ title } title={ title }
......
import { Text } from '@chakra-ui/react'; import { Text } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { TWatchlistItem } from 'types/client/account'; import type { WatchlistAddress } from 'types/api/account';
import useApiFetch from 'lib/api/useApiFetch'; import useApiFetch from 'lib/api/useApiFetch';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
...@@ -11,7 +11,7 @@ type Props = { ...@@ -11,7 +11,7 @@ type Props = {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onSuccess: () => Promise<void>; onSuccess: () => Promise<void>;
data: Pick<TWatchlistItem, 'address_hash' | 'id'>; data: Pick<WatchlistAddress, 'address_hash' | 'id'>;
} }
const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data }) => { const DeleteAddressModal: React.FC<Props> = ({ isOpen, onClose, onSuccess, data }) => {
......
import { HStack, VStack, chakra, Flex, Skeleton } from '@chakra-ui/react'; import { HStack, VStack, Flex, Skeleton, Text } from '@chakra-ui/react';
import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { TWatchlistItem } from 'types/client/account'; import type { WatchlistAddress } from 'types/api/account';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import TokensIcon from 'icons/tokens.svg'; import TokensIcon from 'icons/tokens.svg';
// import WalletIcon from 'icons/wallet.svg'; import WalletIcon from 'icons/wallet.svg';
import getCurrencyValue from 'lib/getCurrencyValue';
import { nbsp } from 'lib/html-entities'; import { nbsp } from 'lib/html-entities';
import AddressSnippet from 'ui/shared/AddressSnippet'; import AddressSnippet from 'ui/shared/AddressSnippet';
import Icon from 'ui/shared/chakra/Icon'; import Icon from 'ui/shared/chakra/Icon';
import CurrencyValue from 'ui/shared/CurrencyValue'; import CurrencyValue from 'ui/shared/CurrencyValue';
import TokenLogo from 'ui/shared/TokenLogo'; import TokenLogo from 'ui/shared/TokenLogo';
const WatchListAddressItem = ({ item, isLoading }: { item: TWatchlistItem; isLoading?: boolean }) => { const WatchListAddressItem = ({ item, isLoading }: { item: WatchlistAddress; isLoading?: boolean }) => {
const infoItemsPaddingLeft = { base: 1, lg: 8 }; const infoItemsPaddingLeft = { base: 1, lg: 8 };
const nativeTokenData = React.useMemo(() => ({ const nativeTokenData = React.useMemo(() => ({
...@@ -21,6 +23,8 @@ const WatchListAddressItem = ({ item, isLoading }: { item: TWatchlistItem; isLoa ...@@ -21,6 +23,8 @@ const WatchListAddressItem = ({ item, isLoading }: { item: TWatchlistItem; isLoa
icon_url: '', icon_url: '',
}), [ ]); }), [ ]);
const { usdBn: usdNative } = getCurrencyValue({ value: item.address_balance, accuracy: 2, accuracyUsd: 2, exchangeRate: item.exchange_rate });
return ( return (
<VStack spacing={ 2 } align="stretch" fontWeight={ 500 }> <VStack spacing={ 2 } align="stretch" fontWeight={ 500 }>
<AddressSnippet address={ item.address } isLoading={ isLoading }/> <AddressSnippet address={ item.address } isLoading={ isLoading }/>
...@@ -49,21 +53,21 @@ const WatchListAddressItem = ({ item, isLoading }: { item: TWatchlistItem; isLoa ...@@ -49,21 +53,21 @@ const WatchListAddressItem = ({ item, isLoading }: { item: TWatchlistItem; isLoa
<HStack spacing={ 2 } fontSize="sm" pl={ infoItemsPaddingLeft }> <HStack spacing={ 2 } fontSize="sm" pl={ infoItemsPaddingLeft }>
<Icon as={ TokensIcon } boxSize={ 5 } isLoading={ isLoading } borderRadius="sm"/> <Icon as={ TokensIcon } boxSize={ 5 } isLoading={ isLoading } borderRadius="sm"/>
<Skeleton isLoaded={ !isLoading } display="inline-flex"> <Skeleton isLoaded={ !isLoading } display="inline-flex">
<span>{ `Tokens:${ nbsp }` + item.tokens_count }</span> <span>{ `Tokens:${ nbsp }` + item.tokens_count + (item.tokens_overflow ? '+' : '') }</span>
{ /* api does not provide token prices */ } <Text variant="secondary" fontWeight={ 400 }>{ `${ nbsp }($${ BigNumber(item.tokens_fiat_value).toFormat(2) })` }</Text>
{ /* <Text variant="secondary">{ `${ nbsp }($${ item.tokensUSD } USD)` }</Text> */ } </Skeleton>
<chakra.span color="text_secondary">{ `${ nbsp }(N/A)` }</chakra.span> </HStack>
) }
{ item.tokens_fiat_value && (
<HStack spacing={ 2 } fontSize="sm" pl={ infoItemsPaddingLeft }>
<Icon boxSize={ 5 } as={ WalletIcon } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } display="inline-flex">
<Text>{ `Net worth:${ nbsp }` }
{ `${ item.tokens_overflow ? '>' : '' }$${ BigNumber(item.tokens_fiat_value).plus((BigNumber(usdNative ? usdNative : '0'))).toFormat(2) }` }
</Text>
</Skeleton> </Skeleton>
</HStack> </HStack>
) } ) }
{ /* api does not provide token prices */ }
{ /* { item.address_balance && (
<HStack spacing={ 0 } fontSize="sm" h={ 6 } pl={ infoItemsPaddingLeft }>
<Icon as={ WalletIcon } mr={ 2 } w="16px" h="16px"/>
<Text>{ `Net worth:${ nbsp }` }</Text>
<Link href="#">{ `$${ item.totalUSD } USD` }</Link>
</HStack>
) } */ }
</VStack> </VStack>
); );
}; };
......
...@@ -2,7 +2,7 @@ import { Box, Switch, Text, HStack, Flex, Skeleton } from '@chakra-ui/react'; ...@@ -2,7 +2,7 @@ import { Box, Switch, Text, HStack, Flex, Skeleton } from '@chakra-ui/react';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import type { TWatchlistItem } from 'types/client/account'; import type { WatchlistAddress } from 'types/api/account';
import useApiFetch from 'lib/api/useApiFetch'; import useApiFetch from 'lib/api/useApiFetch';
import useToast from 'lib/hooks/useToast'; import useToast from 'lib/hooks/useToast';
...@@ -13,10 +13,10 @@ import TableItemActionButtons from 'ui/shared/TableItemActionButtons'; ...@@ -13,10 +13,10 @@ import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import WatchListAddressItem from './WatchListAddressItem'; import WatchListAddressItem from './WatchListAddressItem';
interface Props { interface Props {
item: TWatchlistItem; item: WatchlistAddress;
isLoading?: boolean; isLoading?: boolean;
onEditClick: (data: TWatchlistItem) => void; onEditClick: (data: WatchlistAddress) => void;
onDeleteClick: (data: TWatchlistItem) => void; onDeleteClick: (data: WatchlistAddress) => void;
} }
const WatchListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => { const WatchListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => {
......
...@@ -7,7 +7,7 @@ import { ...@@ -7,7 +7,7 @@ import {
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import type { TWatchlistItem } from 'types/client/account'; import type { WatchlistAddress } from 'types/api/account';
import useApiFetch from 'lib/api/useApiFetch'; import useApiFetch from 'lib/api/useApiFetch';
import useToast from 'lib/hooks/useToast'; import useToast from 'lib/hooks/useToast';
...@@ -17,10 +17,10 @@ import TableItemActionButtons from 'ui/shared/TableItemActionButtons'; ...@@ -17,10 +17,10 @@ import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import WatchListAddressItem from './WatchListAddressItem'; import WatchListAddressItem from './WatchListAddressItem';
interface Props { interface Props {
item: TWatchlistItem; item: WatchlistAddress;
isLoading?: boolean; isLoading?: boolean;
onEditClick: (data: TWatchlistItem) => void; onEditClick: (data: WatchlistAddress) => void;
onDeleteClick: (data: TWatchlistItem) => void; onDeleteClick: (data: WatchlistAddress) => void;
} }
const WatchlistTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => { const WatchlistTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) => {
......
...@@ -7,15 +7,15 @@ import { ...@@ -7,15 +7,15 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TWatchlist, TWatchlistItem } from 'types/client/account'; import type { WatchlistAddress } from 'types/api/account';
import WatchlistTableItem from './WatchListTableItem'; import WatchlistTableItem from './WatchListTableItem';
interface Props { interface Props {
data?: TWatchlist; data?: Array<WatchlistAddress>;
isLoading?: boolean; isLoading?: boolean;
onEditClick: (data: TWatchlistItem) => void; onEditClick: (data: WatchlistAddress) => void;
onDeleteClick: (data: TWatchlistItem) => void; onDeleteClick: (data: WatchlistAddress) => void;
} }
const WatchlistTable = ({ data, isLoading, onDeleteClick, onEditClick }: Props) => { const WatchlistTable = ({ data, isLoading, onDeleteClick, onEditClick }: Props) => {
......
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