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
3c6224f8
Commit
3c6224f8
authored
Jan 05, 2023
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tokens table
parent
22fba855
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
225 additions
and
4 deletions
+225
-4
resources.ts
lib/api/resources.ts
+10
-1
address.ts
types/api/address.ts
+14
-0
AddressTokens.tsx
ui/address/AddressTokens.tsx
+47
-2
Tokens.tsx
ui/address/tokens/Tokens.tsx
+50
-0
TokensTable.tsx
ui/address/tokens/TokensTable.tsx
+36
-0
TokensTableItem.tsx
ui/address/tokens/TokensTableItem.tsx
+53
-0
Address.tsx
ui/pages/Address.tsx
+15
-1
No files found.
lib/api/resources.ts
View file @
3c6224f8
...
@@ -11,6 +11,8 @@ import type {
...
@@ -11,6 +11,8 @@ import type {
AddressInternalTxsResponse
,
AddressInternalTxsResponse
,
AddressTxsFilters
,
AddressTxsFilters
,
AddressTokenTransferFilters
,
AddressTokenTransferFilters
,
AddressTokensFilter
,
AddressTokensResponse
,
}
from
'
types/api/address
'
;
}
from
'
types/api/address
'
;
import
type
{
BlocksResponse
,
BlockTransactionsResponse
,
Block
,
BlockFilters
}
from
'
types/api/block
'
;
import
type
{
BlocksResponse
,
BlockTransactionsResponse
,
Block
,
BlockFilters
}
from
'
types/api/block
'
;
import
type
{
ChartMarketResponse
,
ChartTransactionResponse
}
from
'
types/api/charts
'
;
import
type
{
ChartMarketResponse
,
ChartTransactionResponse
}
from
'
types/api/charts
'
;
...
@@ -163,6 +165,11 @@ export const RESOURCES = {
...
@@ -163,6 +165,11 @@ export const RESOURCES = {
paginationFields
:
[
'
items_count
'
as
const
,
'
transaction_index
'
as
const
,
'
index
'
as
const
,
'
block_number
'
as
const
],
paginationFields
:
[
'
items_count
'
as
const
,
'
transaction_index
'
as
const
,
'
index
'
as
const
,
'
block_number
'
as
const
],
filterFields
:
[
],
filterFields
:
[
],
},
},
address_tokens
:
{
path
:
'
/api/v2/addresses/:id/tokens
'
,
paginationFields
:
[
'
items_count
'
as
const
,
'
token_name
'
as
const
,
'
token_type
'
as
const
,
'
value
'
as
const
],
filterFields
:
[
'
type
'
],
},
// CONTRACT
// CONTRACT
contract
:
{
contract
:
{
...
@@ -264,8 +271,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
...
@@ -264,8 +271,8 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'
txs_validated
'
|
'
txs_pending
'
|
'
txs_validated
'
|
'
txs_pending
'
|
'
tx_internal_txs
'
|
'
tx_logs
'
|
'
tx_token_transfers
'
|
'
tx_internal_txs
'
|
'
tx_logs
'
|
'
tx_token_transfers
'
|
'
address_txs
'
|
'
address_internal_txs
'
|
'
address_token_transfers
'
|
'
address_blocks_validated
'
|
'
address_coin_balance
'
|
'
address_txs
'
|
'
address_internal_txs
'
|
'
address_token_transfers
'
|
'
address_blocks_validated
'
|
'
address_coin_balance
'
|
'
address_logs
'
|
'
search
'
|
'
search
'
|
'
address_logs
'
|
'
address_tokens
'
|
'
token_holders
'
;
'
token_holders
'
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
...
@@ -307,6 +314,7 @@ Q extends 'address_blocks_validated' ? AddressBlocksValidatedResponse :
...
@@ -307,6 +314,7 @@ Q extends 'address_blocks_validated' ? AddressBlocksValidatedResponse :
Q
extends
'
address_coin_balance
'
?
AddressCoinBalanceHistoryResponse
:
Q
extends
'
address_coin_balance
'
?
AddressCoinBalanceHistoryResponse
:
Q
extends
'
address_coin_balance_chart
'
?
AddressCoinBalanceHistoryChart
:
Q
extends
'
address_coin_balance_chart
'
?
AddressCoinBalanceHistoryChart
:
Q
extends
'
address_logs
'
?
LogsResponseAddress
:
Q
extends
'
address_logs
'
?
LogsResponseAddress
:
Q
extends
'
address_tokens
'
?
AddressTokensResponse
:
Q
extends
'
token
'
?
TokenInfo
:
Q
extends
'
token
'
?
TokenInfo
:
Q
extends
'
token_counters
'
?
TokenCounters
:
Q
extends
'
token_counters
'
?
TokenCounters
:
Q
extends
'
token_holders
'
?
TokenHolders
:
Q
extends
'
token_holders
'
?
TokenHolders
:
...
@@ -326,6 +334,7 @@ Q extends 'txs_validated' | 'txs_pending' ? TTxsFilters :
...
@@ -326,6 +334,7 @@ Q extends 'txs_validated' | 'txs_pending' ? TTxsFilters :
Q
extends
'
tx_token_transfers
'
?
TokenTransferFilters
:
Q
extends
'
tx_token_transfers
'
?
TokenTransferFilters
:
Q
extends
'
address_txs
'
|
'
address_internal_txs
'
?
AddressTxsFilters
:
Q
extends
'
address_txs
'
|
'
address_internal_txs
'
?
AddressTxsFilters
:
Q
extends
'
address_token_transfers
'
?
AddressTokenTransferFilters
:
Q
extends
'
address_token_transfers
'
?
AddressTokenTransferFilters
:
Q
extends
'
address_tokens
'
?
AddressTokensFilter
:
Q
extends
'
search
'
?
SearchResultFilters
:
Q
extends
'
search
'
?
SearchResultFilters
:
never
;
never
;
/* eslint-enable @typescript-eslint/indent */
/* eslint-enable @typescript-eslint/indent */
types/api/address.ts
View file @
3c6224f8
...
@@ -48,6 +48,16 @@ export interface AddressTokenBalance {
...
@@ -48,6 +48,16 @@ export interface AddressTokenBalance {
value
:
string
;
value
:
string
;
}
}
export
interface
AddressTokensResponse
{
items
:
Array
<
AddressTokenBalance
>
;
next_page_params
:
{
items_count
:
number
;
token_name
:
'
string
'
|
null
;
token_type
:
TokenType
;
value
:
number
;
};
}
export
interface
AddressTransactionsResponse
{
export
interface
AddressTransactionsResponse
{
items
:
Array
<
Transaction
>
;
items
:
Array
<
Transaction
>
;
next_page_params
:
{
next_page_params
:
{
...
@@ -75,6 +85,10 @@ export type AddressTokenTransferFilters = {
...
@@ -75,6 +85,10 @@ export type AddressTokenTransferFilters = {
type
:
Array
<
TokenType
>
;
type
:
Array
<
TokenType
>
;
}
}
export
type
AddressTokensFilter
=
{
type
:
TokenType
;
}
export
interface
AddressCoinBalanceHistoryItem
{
export
interface
AddressCoinBalanceHistoryItem
{
block_number
:
number
;
block_number
:
number
;
block_timestamp
:
string
;
block_timestamp
:
string
;
...
...
ui/address/AddressTokens.tsx
View file @
3c6224f8
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
TokenType
}
from
'
types/api/tokenInfo
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/RoutedTabs/types
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useQueryWithPages
from
'
lib/hooks/useQueryWithPages
'
;
import
{
tokenTabsByType
}
from
'
ui/pages/Address
'
;
import
Pagination
from
'
ui/shared/Pagination
'
;
import
RoutedTabs
from
'
ui/shared/RoutedTabs/RoutedTabs
'
;
import
TokenBalances
from
'
./tokens/TokenBalances
'
;
import
TokenBalances
from
'
./tokens/TokenBalances
'
;
const
AddressTokens
=
()
=>
{
type
Props
=
{
return
<
TokenBalances
/>;
tabs
:
Array
<
RoutedTab
>
;
}
const
AddressTokens
=
({
tabs
}:
Props
)
=>
{
const
router
=
useRouter
();
const
isMobile
=
useIsMobile
();
const
tokenType
:
TokenType
=
(
Object
.
keys
(
tokenTabsByType
)
as
Array
<
TokenType
>
).
find
(
key
=>
tokenTabsByType
[
key
]
===
router
.
query
.
tab
)
||
'
ERC-20
'
;
const
{
pagination
,
isPaginationVisible
}
=
useQueryWithPages
({
resourceName
:
'
address_tokens
'
,
pathParams
:
{
id
:
router
.
query
.
id
?.
toString
()
},
filters
:
{
type
:
tokenType
},
});
const
TAB_LIST_PROPS
=
{
marginBottom
:
0
,
py
:
5
,
marginTop
:
3
,
columnGap
:
3
,
};
return
(
<>
<
TokenBalances
/>
<
RoutedTabs
tabs=
{
tabs
}
variant=
"outline"
colorScheme=
"gray"
size=
"sm"
tabListProps=
{
isMobile
?
{
mt
:
8
,
columnGap
:
3
}
:
TAB_LIST_PROPS
}
rightSlot=
{
isPaginationVisible
&&
!
isMobile
?
<
Pagination
{
...
pagination
}
/>
:
null
}
stickyEnabled=
{
!
isMobile
}
/>
</>
);
};
};
export
default
AddressTokens
;
export
default
AddressTokens
;
ui/address/tokens/Tokens.tsx
0 → 100644
View file @
3c6224f8
import
{
Skeleton
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
TokenType
}
from
'
types/api/tokenInfo
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useQueryWithPages
from
'
lib/hooks/useQueryWithPages
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
Pagination
from
'
ui/shared/Pagination
'
;
import
TokensTable
from
'
./TokensTable
'
;
type
Props
=
{
type
:
TokenType
;
}
const
TokensERC20
=
({
type
}:
Props
)
=>
{
const
router
=
useRouter
();
const
isMobile
=
useIsMobile
();
const
{
isError
,
isLoading
,
data
,
pagination
,
isPaginationVisible
}
=
useQueryWithPages
({
resourceName
:
'
address_tokens
'
,
pathParams
:
{
id
:
router
.
query
.
id
?.
toString
()
},
filters
:
{
type
},
});
if
(
isError
)
{
return
<
DataFetchAlert
/>;
}
if
(
isLoading
)
{
return
<
Skeleton
w=
"500px"
h=
"50px"
/>;
}
return
(
<>
{
isMobile
&&
isPaginationVisible
&&
(
<
ActionBar
mt=
{
-
6
}
>
<
Pagination
ml=
"auto"
{
...
pagination
}
/>
</
ActionBar
>
)
}
<
TokensTable
data=
{
data
.
items
}
top=
{
isPaginationVisible
?
72
:
0
}
/>
</>
);
};
export
default
TokensERC20
;
ui/address/tokens/TokensTable.tsx
0 → 100644
View file @
3c6224f8
import
{
Table
,
Tbody
,
Tr
,
Th
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
AddressTokenBalance
}
from
'
types/api/address
'
;
import
{
default
as
Thead
}
from
'
ui/shared/TheadSticky
'
;
import
TokensTableItem
from
'
./TokensTableItem
'
;
interface
Props
{
data
:
Array
<
AddressTokenBalance
>
;
top
:
number
;
}
const
TokensTable
=
({
data
,
top
}:
Props
)
=>
{
return
(
<
Table
variant=
"simple"
size=
"sm"
>
<
Thead
top=
{
top
}
>
<
Tr
>
<
Th
width=
"20%"
>
Asset
</
Th
>
<
Th
width=
"40%"
>
Contract address
</
Th
>
<
Th
width=
"10%"
isNumeric
>
Price
</
Th
>
<
Th
width=
"20%"
isNumeric
>
Quantity
</
Th
>
<
Th
width=
"10%"
isNumeric
>
Value
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
>
{
data
.
map
((
item
)
=>
(
<
TokensTableItem
key=
{
item
.
token
.
address
}
{
...
item
}
/>
))
}
</
Tbody
>
</
Table
>
);
};
export
default
TokensTable
;
ui/address/tokens/TokensTableItem.tsx
0 → 100644
View file @
3c6224f8
import
{
Tr
,
Td
,
Flex
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
AddressTokenBalance
}
from
'
types/api/address
'
;
import
getCurrencyValue
from
'
lib/getCurrencyValue
'
;
import
AddressLink
from
'
ui/shared/address/AddressLink
'
;
import
CopyToClipboard
from
'
ui/shared/CopyToClipboard
'
;
import
AddressAddToMetaMask
from
'
../details/AddressAddToMetaMask
'
;
type
Props
=
AddressTokenBalance
;
const
TokensTableItem
=
({
token
,
value
,
}:
Props
)
=>
{
const
tokenString
=
[
token
.
name
,
token
.
symbol
&&
`(
${
token
.
symbol
}
)`
].
filter
(
Boolean
).
join
(
'
'
);
const
{
valueStr
:
tokenQuantity
,
usd
:
tokenValue
,
}
=
getCurrencyValue
({
value
:
value
,
exchangeRate
:
token
.
exchange_rate
,
decimals
:
token
.
decimals
,
accuracy
:
8
,
accuracyUsd
:
2
});
return
(
<
Tr
>
<
Td
verticalAlign=
"middle"
>
<
AddressLink
fontWeight=
"700"
hash=
{
token
.
address
}
type=
"token"
alias=
{
tokenString
}
/>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
Flex
alignItems=
"center"
width=
"150px"
justifyContent=
"space-between"
>
<
Flex
alignItems=
"center"
>
<
AddressLink
hash=
{
token
.
address
}
type=
"address"
truncation=
"constant"
/>
<
CopyToClipboard
text=
{
token
.
address
}
ml=
{
1
}
/>
</
Flex
>
<
AddressAddToMetaMask
token=
{
token
}
ml=
{
4
}
/>
</
Flex
>
</
Td
>
<
Td
isNumeric
verticalAlign=
"middle"
>
{
token
.
exchange_rate
?
`$${ token.exchange_rate }`
:
'
-
'
}
</
Td
>
<
Td
isNumeric
verticalAlign=
"middle"
>
{
tokenQuantity
}
</
Td
>
<
Td
isNumeric
verticalAlign=
"middle"
>
{
tokenValue
?
`$${ tokenValue }`
:
'
-
'
}
</
Td
>
</
Tr
>
);
};
export
default
React
.
memo
(
TokensTableItem
);
ui/pages/Address.tsx
View file @
3c6224f8
...
@@ -2,6 +2,7 @@ import { Flex, Skeleton, Tag, Box } from '@chakra-ui/react';
...
@@ -2,6 +2,7 @@ import { Flex, Skeleton, Tag, Box } from '@chakra-ui/react';
import
{
useRouter
}
from
'
next/router
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
TokenType
}
from
'
types/api/tokenInfo
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/RoutedTabs/types
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/RoutedTabs/types
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
...
@@ -18,12 +19,25 @@ import AddressTxs from 'ui/address/AddressTxs';
...
@@ -18,12 +19,25 @@ import AddressTxs from 'ui/address/AddressTxs';
import
ContractCode
from
'
ui/address/contract/ContractCode
'
;
import
ContractCode
from
'
ui/address/contract/ContractCode
'
;
import
ContractRead
from
'
ui/address/contract/ContractRead
'
;
import
ContractRead
from
'
ui/address/contract/ContractRead
'
;
import
ContractWrite
from
'
ui/address/contract/ContractWrite
'
;
import
ContractWrite
from
'
ui/address/contract/ContractWrite
'
;
import
Tokens
from
'
ui/address/tokens/Tokens
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
RoutedTabs
from
'
ui/shared/RoutedTabs/RoutedTabs
'
;
import
RoutedTabs
from
'
ui/shared/RoutedTabs/RoutedTabs
'
;
import
SkeletonTabs
from
'
ui/shared/skeletons/SkeletonTabs
'
;
import
SkeletonTabs
from
'
ui/shared/skeletons/SkeletonTabs
'
;
export
const
tokenTabsByType
:
Record
<
TokenType
,
string
>
=
{
'
ERC-20
'
:
'
tokens_erc20
'
,
'
ERC-721
'
:
'
tokens_erc721
'
,
'
ERC-1155
'
:
'
tokens_erc1155
'
,
}
as
const
;
const
TOKENS_TABS
=
[
{
id
:
tokenTabsByType
[
'
ERC-20
'
],
title
:
'
ERC-20
'
,
component
:
<
Tokens
type=
"ERC-20"
/>
},
{
id
:
tokenTabsByType
[
'
ERC-721
'
],
title
:
'
ERC-721
'
,
component
:
null
},
{
id
:
tokenTabsByType
[
'
ERC-1155
'
],
title
:
'
ERC-1155
'
,
component
:
null
},
];
const
AddressPageContent
=
()
=>
{
const
AddressPageContent
=
()
=>
{
const
router
=
useRouter
();
const
router
=
useRouter
();
...
@@ -73,7 +87,7 @@ const AddressPageContent = () => {
...
@@ -73,7 +87,7 @@ const AddressPageContent = () => {
addressQuery
.
data
?.
has_token_transfers
?
addressQuery
.
data
?.
has_token_transfers
?
{
id
:
'
token_transfers
'
,
title
:
'
Token transfers
'
,
component
:
<
AddressTokenTransfers
scrollRef=
{
tabsScrollRef
}
/>
}
:
{
id
:
'
token_transfers
'
,
title
:
'
Token transfers
'
,
component
:
<
AddressTokenTransfers
scrollRef=
{
tabsScrollRef
}
/>
}
:
undefined
,
undefined
,
addressQuery
.
data
?.
has_tokens
?
{
id
:
'
tokens
'
,
title
:
'
Tokens
'
,
component
:
<
AddressTokens
/>
}
:
undefined
,
addressQuery
.
data
?.
has_tokens
?
{
id
:
'
tokens
'
,
title
:
'
Tokens
'
,
component
:
<
AddressTokens
tabs=
{
TOKENS_TABS
}
/>,
subTabs
:
TOKENS_TABS
}
:
undefined
,
{
id
:
'
internal_txns
'
,
title
:
'
Internal txns
'
,
component
:
<
AddressInternalTxs
scrollRef=
{
tabsScrollRef
}
/>
},
{
id
:
'
internal_txns
'
,
title
:
'
Internal txns
'
,
component
:
<
AddressInternalTxs
scrollRef=
{
tabsScrollRef
}
/>
},
{
id
:
'
coin_balance_history
'
,
title
:
'
Coin balance history
'
,
component
:
<
AddressCoinBalance
/>
},
{
id
:
'
coin_balance_history
'
,
title
:
'
Coin balance history
'
,
component
:
<
AddressCoinBalance
/>
},
addressQuery
.
data
?.
has_validated_blocks
?
addressQuery
.
data
?.
has_validated_blocks
?
...
...
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