Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
e6e1639e
Commit
e6e1639e
authored
Aug 07, 2023
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
get tokens info from watchlist responce
parent
7fee6df6
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
57 additions
and
91 deletions
+57
-91
resources.ts
lib/api/resources.ts
+0
-3
account.ts
stubs/account.ts
+4
-3
account.ts
types/api/account.ts
+3
-6
account.ts
types/client/account.ts
+0
-6
Watchlist.tsx
ui/pages/Watchlist.tsx
+11
-37
AddressForm.tsx
ui/watchlist/AddressModal/AddressForm.tsx
+2
-3
AddressModal.tsx
ui/watchlist/AddressModal/AddressModal.tsx
+3
-3
DeleteAddressModal.tsx
ui/watchlist/DeleteAddressModal.tsx
+2
-2
WatchListAddressItem.tsx
ui/watchlist/WatchlistTable/WatchListAddressItem.tsx
+20
-16
WatchListItem.tsx
ui/watchlist/WatchlistTable/WatchListItem.tsx
+4
-4
WatchListTableItem.tsx
ui/watchlist/WatchlistTable/WatchListTableItem.tsx
+4
-4
WatchlistTable.tsx
ui/watchlist/WatchlistTable/WatchlistTable.tsx
+4
-4
No files found.
lib/api/resources.ts
View file @
e6e1639e
...
...
@@ -480,9 +480,6 @@ export const RESOURCES = {
},
// DEPRECATED
old_api
:
{
path
:
'
/api
'
,
},
csv_export_txs
:
{
path
:
'
/transactions-csv
'
,
},
...
...
stubs/account.ts
View file @
e6e1639e
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
=
{
...
...
types/api/account.ts
View file @
e6e1639e
...
...
@@ -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
{
...
...
types/client/account.ts
View file @
e6e1639e
import
type
{
WatchlistAddress
}
from
'
../api/account
'
;
export
type
TWatchlistItem
=
WatchlistAddress
&
{
tokens_count
:
number
};
export
type
TWatchlist
=
Array
<
TWatchlistItem
>
;
export
interface
CsrfData
{
token
:
string
;
}
ui/pages/Watchlist.tsx
View file @
e6e1639e
import
{
Box
,
Button
,
Skeleton
,
useDisclosure
}
from
'
@chakra-ui/react
'
;
import
{
useQuery
,
useQuery
Client
}
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
useApi
Fetch
from
'
lib/api/useApiFetch
'
;
import
useApi
Query
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
]);
...
...
ui/watchlist/AddressModal/AddressForm.tsx
View file @
e6e1639e
...
...
@@ -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
;
...
...
ui/watchlist/AddressModal/AddressModal.tsx
View file @
e6e1639e
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
}
...
...
ui/watchlist/DeleteAddressModal.tsx
View file @
e6e1639e
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
})
=>
{
...
...
ui/watchlist/WatchlistTable/WatchListAddressItem.tsx
View file @
e6e1639e
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
>
);
};
...
...
ui/watchlist/WatchlistTable/WatchListItem.tsx
View file @
e6e1639e
...
...
@@ -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
)
=>
{
...
...
ui/watchlist/WatchlistTable/WatchListTableItem.tsx
View file @
e6e1639e
...
...
@@ -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
)
=>
{
...
...
ui/watchlist/WatchlistTable/WatchlistTable.tsx
View file @
e6e1639e
...
...
@@ -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
)
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment