Commit e6e1639e authored by isstuev's avatar isstuev

get tokens info from watchlist responce

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