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
1cec1447
Unverified
Commit
1cec1447
authored
Oct 28, 2022
by
tom goriunov
Committed by
GitHub
Oct 28, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #264 from blockscout/tx-api-update
tx api update
parents
37c11d04
43f1e0dd
Changes
26
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
223 additions
and
129 deletions
+223
-129
addressParams.ts
types/api/addressParams.ts
+15
-1
internalTransaction.ts
types/api/internalTransaction.ts
+2
-1
reward.ts
types/api/reward.ts
+1
-1
tokenInfo.ts
types/api/tokenInfo.ts
+13
-0
tokenTransfer.ts
types/api/tokenTransfer.ts
+19
-15
transaction.ts
types/api/transaction.ts
+1
-0
BlockDetails.tsx
ui/block/BlockDetails.tsx
+13
-12
BlocksListItem.tsx
ui/blocks/BlocksListItem.tsx
+8
-6
BlocksTableItem.tsx
ui/blocks/BlocksTableItem.tsx
+6
-3
Transaction.tsx
ui/pages/Transaction.tsx
+23
-7
CurrencyValue.tsx
ui/shared/CurrencyValue.tsx
+3
-7
TokenLogo.tsx
ui/shared/TokenLogo.tsx
+1
-1
TokenSnippet.tsx
ui/shared/TokenSnippet.tsx
+3
-3
AddressLink.tsx
ui/shared/address/AddressLink.tsx
+5
-3
NftTokenTransferSnippet.tsx
ui/tx/NftTokenTransferSnippet.tsx
+12
-6
TokenTransfer.tsx
ui/tx/TokenTransfer.tsx
+19
-15
TokenTransferList.tsx
ui/tx/TokenTransferList.tsx
+2
-2
TxDetails.tsx
ui/tx/TxDetails.tsx
+46
-19
TxInternals.tsx
ui/tx/TxInternals.tsx
+9
-10
TxInternalsListItem.tsx
ui/tx/internals/TxInternalsListItem.tsx
+5
-5
TxInternalsSkeletonDesktop.tsx
ui/tx/internals/TxInternalsSkeletonDesktop.tsx
+1
-1
TxInternalsSkeletonMobile.tsx
ui/tx/internals/TxInternalsSkeletonMobile.tsx
+4
-0
TxInternalsTable.tsx
ui/tx/internals/TxInternalsTable.tsx
+5
-6
TxInternalsTableItem.tsx
ui/tx/internals/TxInternalsTableItem.tsx
+5
-5
TxsListItem.tsx
ui/txs/TxsListItem.tsx
+1
-0
TxsTableItem.tsx
ui/txs/TxsTableItem.tsx
+1
-0
No files found.
types/api/addressParams.ts
View file @
1cec1447
export
interface
AddressTag
{
label
:
string
;
display_name
:
string
;
address_hash
:
string
;
}
export
interface
WatchlistName
{
label
:
string
;
display_name
:
string
;
}
export
interface
AddressParam
{
hash
:
string
;
implementation_name
:
string
;
name
:
string
;
name
:
string
|
null
;
is_contract
:
boolean
;
private_tags
:
Array
<
AddressTag
>
|
null
;
watchlist_names
:
Array
<
WatchlistName
>
|
null
;
public_tags
:
Array
<
AddressTag
>
|
null
;
}
types/api/internalTransaction.ts
View file @
1cec1447
...
...
@@ -10,10 +10,11 @@ export interface InternalTransaction {
from
:
AddressParam
;
to
:
AddressParam
;
created_contract
:
AddressParam
;
value
:
number
;
value
:
string
;
index
:
number
;
block
:
number
;
timestamp
:
string
;
gas_limit
:
string
;
}
export
interface
InternalTransactionsResponse
{
...
...
types/api/reward.ts
View file @
1cec1447
export
interface
Reward
{
reward
:
number
;
reward
:
string
;
type
:
'
Miner Reward
'
|
'
Validator Reward
'
|
'
Emission Reward
'
|
'
Chore Reward
'
|
'
Uncle Reward
'
;
}
types/api/tokenInfo.ts
0 → 100644
View file @
1cec1447
export
type
TokenType
=
'
ERC-20
'
|
'
ERC-721
'
|
'
ERC-1155
'
;
export
interface
TokenInfo
{
address
:
string
;
type
:
TokenType
;
symbol
:
string
|
null
;
name
:
string
|
null
;
decimals
:
string
|
null
;
holders
:
string
|
null
;
exchange_rate
:
string
|
null
;
}
export
type
TokenInfoGeneric
<
Type
extends
TokenType
>
=
Omit
<
TokenInfo
,
'
type
'
>
&
{
type
:
Type
};
types/api/tokenTransfer.ts
View file @
1cec1447
import
type
{
AddressParam
}
from
'
./addressParams
'
;
import
type
{
TokenInfoGeneric
}
from
'
./tokenInfo
'
;
export
type
ERC1155TotalPayload
=
{
export
type
Erc20TotalPayload
=
{
decimals
:
string
|
null
;
value
:
string
;
}
export
type
Erc721TotalPayload
=
{
token_id
:
string
;
}
export
type
Erc1155TotalPayload
=
{
decimals
:
string
|
null
;
value
:
string
;
token_id
:
string
;
}
export
type
TokenTransfer
=
(
{
token_type
:
'
ERC-20
'
;
total
:
{
value
:
string
;
};
token
:
TokenInfoGeneric
<
'
ERC-20
'
>
;
total
:
Erc20TotalPayload
;
}
|
{
token_type
:
'
ERC-721
'
;
total
:
{
token_id
:
string
;
};
token
:
TokenInfoGeneric
<
'
ERC-721
'
>
;
total
:
Erc721TotalPayload
;
}
|
{
token
_type
:
'
ERC-1155
'
;
total
:
E
RC1155TotalPayload
|
Array
<
ERC
1155TotalPayload
>
;
token
:
TokenInfoGeneric
<
'
ERC-1155
'
>
;
total
:
E
rc1155TotalPayload
|
Array
<
Erc
1155TotalPayload
>
;
}
)
&
TokenTransferBase
interface
TokenTransferBase
{
type
:
'
token_transfer
'
|
'
token_burning
'
|
'
token_spawning
'
|
'
token_minting
'
;
tx
H
ash
:
string
;
tx
_h
ash
:
string
;
from
:
AddressParam
;
to
:
AddressParam
;
token_address
:
string
;
token_symbol
:
string
;
exchange_rate
:
string
;
}
types/api/transaction.ts
View file @
1cec1447
...
...
@@ -38,6 +38,7 @@ export interface Transaction {
token_transfers
:
Array
<
TokenTransfer
>
|
null
;
token_transfers_overflow
:
boolean
;
exchange_rate
:
string
;
tx_tag
:
string
|
null
;
}
export
interface
TransactionsResponse
{
...
...
ui/block/BlockDetails.tsx
View file @
1cec1447
...
...
@@ -158,6 +158,19 @@ const BlockDetails = () => {
)
}
</
DetailsInfoItem
>
)
}
{
data
.
rewards
?.
filter
(({
type
})
=>
type
!==
'
Validator Reward
'
&&
type
!==
'
Miner Reward
'
)
.
map
(({
type
,
reward
})
=>
(
<
DetailsInfoItem
key=
{
type
}
title=
{
type
}
// is this text correct for validators?
hint=
{
`Amount of distributed reward. ${ capitalize(validatorTitle) }s receive a static block reward + Tx fees + uncle fees.`
}
>
{
BigNumber
(
reward
).
dividedBy
(
WEI
).
toFixed
()
}
{
appConfig
.
network
.
currency
.
symbol
}
</
DetailsInfoItem
>
))
}
{
sectionGap
}
...
...
@@ -298,18 +311,6 @@ const BlockDetails = () => {
>
{
data
.
nonce
}
</
DetailsInfoItem
>
{
data
.
rewards
?.
filter
(({
type
})
=>
type
!==
'
Validator Reward
'
&&
type
!==
'
Miner Reward
'
)
.
map
(({
type
,
reward
})
=>
(
<
DetailsInfoItem
key=
{
type
}
title=
{
type
}
// is this text correct for validators?
hint=
{
`Amount of distributed reward. ${ capitalize(validatorTitle) }s receive a static block reward + Tx fees + uncle fees.`
}
>
{
BigNumber
(
reward
).
dividedBy
(
WEI
).
toFixed
()
}
{
appConfig
.
network
.
currency
.
symbol
}
</
DetailsInfoItem
>
))
}
</>
)
}
</
Grid
>
...
...
ui/blocks/BlocksListItem.tsx
View file @
1cec1447
import
{
Flex
,
Link
,
Spinner
,
Text
,
Box
,
Icon
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
Link
,
Spinner
,
Text
,
Box
,
Icon
}
from
'
@chakra-ui/react
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
capitalize
from
'
lodash/capitalize
'
;
import
React
from
'
react
'
;
...
...
@@ -7,8 +7,7 @@ import type { Block } from 'types/api/block';
import
appConfig
from
'
configs/app/config
'
;
import
flameIcon
from
'
icons/flame.svg
'
;
import
getBlockReward
from
'
lib/block/getBlockReward
'
;
import
{
WEI
}
from
'
lib/consts
'
;
import
{
WEI
,
ZERO
}
from
'
lib/consts
'
;
import
link
from
'
lib/link/link
'
;
import
getNetworkValidatorTitle
from
'
lib/networks/getNetworkValidatorTitle
'
;
import
BlockTimestamp
from
'
ui/blocks/BlockTimestamp
'
;
...
...
@@ -24,14 +23,17 @@ interface Props {
}
const
BlocksListItem
=
({
data
,
isPending
,
enableTimeIncrement
}:
Props
)
=>
{
const
spinnerEmptyColor
=
useColorModeValue
(
'
blackAlpha.200
'
,
'
whiteAlpha.200
'
);
const
{
totalReward
,
burntFees
,
txFees
}
=
getBlockReward
(
data
);
const
totalReward
=
data
.
rewards
?.
map
(({
reward
})
=>
BigNumber
(
reward
))
.
reduce
((
result
,
item
)
=>
result
.
plus
(
item
),
ZERO
)
||
ZERO
;
const
burntFees
=
BigNumber
(
data
.
burnt_fees
||
0
);
const
txFees
=
BigNumber
(
data
.
tx_fees
||
0
);
return
(
<
AccountListItemMobile
rowGap=
{
3
}
>
<
Flex
justifyContent=
"space-between"
w=
"100%"
>
<
Flex
columnGap=
{
2
}
alignItems=
"center"
>
{
isPending
&&
<
Spinner
size=
"sm"
color=
"blue.500"
emptyColor=
{
spinnerEmptyColor
}
/>
}
{
isPending
&&
<
Spinner
size=
"sm"
/>
}
<
Link
fontWeight=
{
600
}
href=
{
link
(
'
block
'
,
{
id
:
String
(
data
.
height
)
})
}
...
...
ui/blocks/BlocksTableItem.tsx
View file @
1cec1447
...
...
@@ -5,8 +5,7 @@ import React from 'react';
import
type
{
Block
}
from
'
types/api/block
'
;
import
flameIcon
from
'
icons/flame.svg
'
;
import
getBlockReward
from
'
lib/block/getBlockReward
'
;
import
{
WEI
}
from
'
lib/consts
'
;
import
{
WEI
,
ZERO
}
from
'
lib/consts
'
;
import
link
from
'
lib/link/link
'
;
import
BlockTimestamp
from
'
ui/blocks/BlockTimestamp
'
;
import
AddressLink
from
'
ui/shared/address/AddressLink
'
;
...
...
@@ -20,7 +19,11 @@ interface Props {
}
const
BlocksTableItem
=
({
data
,
isPending
,
enableTimeIncrement
}:
Props
)
=>
{
const
{
totalReward
,
burntFees
,
txFees
}
=
getBlockReward
(
data
);
const
totalReward
=
data
.
rewards
?.
map
(({
reward
})
=>
BigNumber
(
reward
))
.
reduce
((
result
,
item
)
=>
result
.
plus
(
item
),
ZERO
)
||
ZERO
;
const
burntFees
=
BigNumber
(
data
.
burnt_fees
||
0
);
const
txFees
=
BigNumber
(
data
.
tx_fees
||
0
);
return
(
<
Tr
>
...
...
ui/pages/Transaction.tsx
View file @
1cec1447
import
{
Flex
,
Link
,
Icon
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
Link
,
Icon
,
Tag
}
from
'
@chakra-ui/react
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/RoutedTabs/types
'
;
import
eastArrowIcon
from
'
icons/arrows/east.svg
'
;
import
link
from
'
lib/link/link
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
isBrowser
from
'
lib/isBrowser
'
;
import
networkExplorers
from
'
lib/networks/networkExplorers
'
;
import
ExternalLink
from
'
ui/shared/ExternalLink
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
...
...
@@ -28,6 +31,15 @@ const TABS: Array<RoutedTab> = [
const
TransactionPageContent
=
()
=>
{
const
router
=
useRouter
();
const
fetch
=
useFetch
();
const
{
data
}
=
useQuery
<
unknown
,
unknown
,
Transaction
>
(
[
'
tx
'
,
router
.
query
.
id
],
async
()
=>
await
fetch
(
`/api/transactions/
${
router
.
query
.
id
}
`
),
{
enabled
:
Boolean
(
router
.
query
.
id
),
},
);
const
explorersLinks
=
networkExplorers
.
filter
((
explorer
)
=>
explorer
.
paths
.
tx
)
...
...
@@ -36,15 +48,19 @@ const TransactionPageContent = () => {
return
<
ExternalLink
key=
{
explorer
.
baseUrl
}
title=
{
`Open in ${ explorer.title }`
}
href=
{
url
.
toString
()
}
/>;
});
const
hasGoBackLink
=
isBrowser
()
&&
window
.
document
.
referrer
.
includes
(
'
/txs
'
);
return
(
<
Page
>
{
/* TODO should be shown only when navigating from txs list */
}
<
Link
mb=
{
6
}
display=
"inline-flex"
href=
{
link
(
'
txs
'
)
}
>
<
Icon
as=
{
eastArrowIcon
}
boxSize=
{
6
}
mr=
{
2
}
transform=
"rotate(180deg)"
/>
Transactions
</
Link
>
{
hasGoBackLink
&&
(
<
Link
mb=
{
6
}
display=
"inline-flex"
href=
{
window
.
document
.
referrer
}
>
<
Icon
as=
{
eastArrowIcon
}
boxSize=
{
6
}
mr=
{
2
}
transform=
"rotate(180deg)"
/>
Transactions
</
Link
>
)
}
<
Flex
alignItems=
"flex-start"
flexDir=
{
{
base
:
'
column
'
,
lg
:
'
row
'
}
}
>
<
PageTitle
text=
"Transaction details"
/>
{
data
?.
tx_tag
&&
<
Tag
my=
{
2
}
ml=
{
3
}
>
{
data
.
tx_tag
}
</
Tag
>
}
{
explorersLinks
.
length
>
0
&&
(
<
Flex
alignItems=
"center"
...
...
ui/shared/CurrencyValue.tsx
View file @
1cec1447
...
...
@@ -2,22 +2,18 @@ import { Box, Text, chakra } from '@chakra-ui/react';
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
import
type
{
Unit
}
from
'
types/unit
'
;
import
getValueWithUnit
from
'
lib/getValueWithUnit
'
;
interface
Props
{
value
:
string
;
unit
?:
Unit
;
currency
?:
string
;
exchangeRate
?:
string
|
null
;
className
?:
string
;
accuracy
?:
number
;
accuracyUsd
?:
number
;
decimals
?:
string
|
null
;
}
const
CurrencyValue
=
({
value
,
currency
=
''
,
unit
,
exchangeRate
,
className
,
accuracy
,
accuracyUsd
}:
Props
)
=>
{
const
valueCurr
=
getValueWithUnit
(
value
,
unit
);
const
CurrencyValue
=
({
value
,
currency
=
''
,
decimals
,
exchangeRate
,
className
,
accuracy
,
accuracyUsd
}:
Props
)
=>
{
const
valueCurr
=
BigNumber
(
value
).
div
(
BigNumber
(
10
**
Number
(
decimals
||
'
18
'
))
);
const
valueResult
=
accuracy
?
valueCurr
.
dp
(
accuracy
).
toFormat
()
:
valueCurr
.
toFormat
();
let
usdContent
;
...
...
ui/shared/TokenLogo.tsx
View file @
1cec1447
...
...
@@ -7,7 +7,7 @@ const EmptyElement = () => null;
interface
Props
{
hash
:
string
;
name
?:
string
;
name
?:
string
|
null
;
className
?:
string
;
}
...
...
ui/shared/TokenSnippet.tsx
View file @
1cec1447
...
...
@@ -5,9 +5,9 @@ import link from 'lib/link/link';
import
TokenLogo
from
'
ui/shared/TokenLogo
'
;
interface
Props
{
symbol
:
string
;
symbol
?:
string
|
null
;
hash
:
string
;
name
:
string
;
name
?:
string
|
null
;
className
?:
string
;
}
...
...
@@ -20,7 +20,7 @@ const TokenSnippet = ({ symbol, hash, name, className }: Props) => {
<
Link
href=
{
url
}
target=
"_blank"
>
{
name
}
</
Link
>
<
Text
variant=
"secondary"
>
(
{
symbol
}
)
</
Text
>
{
symbol
&&
<
Text
variant=
"secondary"
>
(
{
symbol
}
)
</
Text
>
}
</
Center
>
);
};
...
...
ui/shared/address/AddressLink.tsx
View file @
1cec1447
import
{
Link
,
chakra
,
shouldForwardProp
,
Tooltip
,
Box
}
from
'
@chakra-ui/react
'
;
import
type
{
HTMLAttributeAnchorTarget
}
from
'
react
'
;
import
React
from
'
react
'
;
import
link
from
'
lib/link/link
'
;
...
...
@@ -7,15 +8,16 @@ import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
interface
Props
{
type
?:
'
address
'
|
'
transaction
'
|
'
token
'
|
'
block
'
;
alias
?:
string
;
alias
?:
string
|
null
;
className
?:
string
;
hash
:
string
;
truncation
?:
'
constant
'
|
'
dynamic
'
|
'
none
'
;
fontWeight
?:
string
;
id
?:
string
;
target
?:
HTMLAttributeAnchorTarget
;
}
const
AddressLink
=
({
alias
,
type
,
className
,
truncation
=
'
dynamic
'
,
hash
,
id
,
fontWeight
}:
Props
)
=>
{
const
AddressLink
=
({
alias
,
type
,
className
,
truncation
=
'
dynamic
'
,
hash
,
id
,
fontWeight
,
target
}:
Props
)
=>
{
let
url
;
if
(
type
===
'
transaction
'
)
{
url
=
link
(
'
tx
'
,
{
id
:
id
||
hash
});
...
...
@@ -49,7 +51,7 @@ const AddressLink = ({ alias, type, className, truncation = 'dynamic', hash, id,
<
Link
className=
{
className
}
href=
{
url
}
target=
"_blank"
target=
{
target
||
'
_blank
'
}
overflow=
"hidden"
whiteSpace=
"nowrap"
>
...
...
ui/tx/NftTokenTransferSnippet.tsx
View file @
1cec1447
...
...
@@ -3,27 +3,33 @@ import React from 'react';
import
nftIcon
from
'
icons/nft_shield.svg
'
;
import
link
from
'
lib/link/link
'
;
import
AddressLink
from
'
ui/shared/address/AddressLink
'
;
import
TokenSnippet
from
'
ui/shared/TokenSnippet
'
;
interface
Props
{
value
:
string
;
tokenId
:
string
;
hash
:
string
;
symbol
:
string
;
name
?:
string
|
null
;
symbol
?:
string
|
null
;
}
const
NftTokenTransferSnippet
=
(
props
:
Props
)
=>
{
const
num
=
props
.
value
===
'
1
'
?
''
:
props
.
value
;
const
url
=
link
(
'
token_instance_item
'
,
{
hash
:
props
.
hash
,
id
:
props
.
tokenId
});
const
NftTokenTransferSnippet
=
(
{
value
,
name
,
hash
,
symbol
,
tokenId
}
:
Props
)
=>
{
const
num
=
value
===
'
1
'
?
''
:
value
;
const
url
=
link
(
'
token_instance_item
'
,
{
hash
:
hash
,
id
:
tokenId
});
return
(
<
Flex
alignItems=
"center"
columnGap=
{
3
}
rowGap=
{
2
}
flexWrap=
"wrap"
>
<
Text
fontWeight=
{
500
}
as=
"span"
>
For
{
num
}
token ID:
</
Text
>
<
Box
display=
"inline-flex"
alignItems=
"center"
>
<
Icon
as=
{
nftIcon
}
boxSize=
{
6
}
mr=
{
1
}
/>
<
Link
href=
{
url
}
fontWeight=
{
600
}
>
{
props
.
tokenId
}
</
Link
>
<
Link
href=
{
url
}
fontWeight=
{
600
}
>
{
tokenId
}
</
Link
>
</
Box
>
<
TokenSnippet
symbol=
{
props
.
symbol
}
hash=
{
props
.
hash
}
name=
"Foo"
/>
{
name
?
(
<
TokenSnippet
symbol=
{
symbol
}
hash=
{
hash
}
name=
{
name
}
/>
)
:
(
<
AddressLink
hash=
{
hash
}
truncation=
"constant"
type=
"token"
/>
)
}
</
Flex
>
);
};
...
...
ui/tx/TokenTransfer.tsx
View file @
1cec1447
import
{
Flex
,
Icon
,
Text
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokenTransfer
as
TTokenTransfer
}
from
'
types/api/tokenTransfer
'
;
import
type
{
TokenTransfer
as
TTokenTransfer
,
Erc20TotalPayload
,
Erc721TotalPayload
,
Erc1155TotalPayload
}
from
'
types/api/tokenTransfer
'
;
import
rightArrowIcon
from
'
icons/arrows/east.svg
'
;
import
{
space
}
from
'
lib/html-entities
'
;
...
...
@@ -12,43 +12,47 @@ import NftTokenTransferSnippet from 'ui/tx/NftTokenTransferSnippet';
type
Props
=
TTokenTransfer
;
const
TokenTransfer
=
(
props
:
Props
)
=>
{
const
TokenTransfer
=
(
{
token
,
total
,
to
,
from
}
:
Props
)
=>
{
const
isColumnLayout
=
props
.
token_type
===
'
ERC-1155
'
&&
Array
.
isArray
(
props
.
total
);
const
tokenSnippet
=
<
TokenSnippet
symbol=
{
props
.
token_symbol
}
hash=
{
props
.
token_address
}
name=
"Foo"
ml=
{
3
}
/>;
const
isColumnLayout
=
token
.
type
===
'
ERC-1155
'
&&
Array
.
isArray
(
total
);
const
tokenSnippet
=
<
TokenSnippet
symbol=
{
token
.
symbol
}
hash=
{
token
.
address
}
name=
{
token
.
name
}
ml=
{
3
}
/>;
const
content
=
(()
=>
{
switch
(
props
.
token_type
)
{
case
'
ERC-20
'
:
switch
(
token
.
type
)
{
case
'
ERC-20
'
:
{
const
payload
=
total
as
Erc20TotalPayload
;
return
(
<
Flex
>
<
Text
fontWeight=
{
500
}
as=
"span"
>
For:
{
space
}
<
CurrencyValue
value=
{
p
rops
.
total
.
value
}
unit=
"ether"
exchangeRate=
{
props
.
exchange_rate
}
fontWeight=
{
600
}
/>
<
CurrencyValue
value=
{
p
ayload
.
value
}
exchangeRate=
{
token
.
exchange_rate
}
fontWeight=
{
600
}
/>
</
Text
>
{
tokenSnippet
}
</
Flex
>
);
}
case
'
ERC-721
'
:
{
const
payload
=
total
as
Erc721TotalPayload
;
return
(
<
NftTokenTransferSnippet
tokenId=
{
p
rops
.
total
.
token_id
}
tokenId=
{
p
ayload
.
token_id
}
value=
"1"
hash=
{
props
.
token_
address
}
symbol=
{
props
.
token_
symbol
}
hash=
{
token
.
address
}
symbol=
{
token
.
symbol
}
/>
);
}
case
'
ERC-1155
'
:
{
const
items
=
Array
.
isArray
(
props
.
total
)
?
props
.
total
:
[
props
.
total
];
const
payload
=
total
as
Erc1155TotalPayload
|
Array
<
Erc1155TotalPayload
>
;
const
items
=
Array
.
isArray
(
payload
)
?
payload
:
[
payload
];
return
items
.
map
((
item
)
=>
(
<
NftTokenTransferSnippet
key=
{
item
.
token_id
}
tokenId=
{
item
.
token_id
}
value=
{
item
.
value
}
hash=
{
props
.
token_
address
}
symbol=
{
props
.
token_
symbol
}
hash=
{
token
.
address
}
symbol=
{
token
.
symbol
}
/>
));
}
...
...
@@ -64,9 +68,9 @@ const TokenTransfer = (props: Props) => {
flexDir=
{
isColumnLayout
?
'
column
'
:
'
row
'
}
>
<
Flex
alignItems=
"center"
>
<
AddressLink
fontWeight=
"500"
hash=
{
props
.
from
.
hash
}
truncation=
"constant"
/>
<
AddressLink
fontWeight=
"500"
hash=
{
from
.
hash
}
truncation=
"constant"
/>
<
Icon
as=
{
rightArrowIcon
}
boxSize=
{
6
}
mx=
{
2
}
color=
"gray.500"
/>
<
AddressLink
fontWeight=
"500"
hash=
{
props
.
to
.
hash
}
truncation=
"constant"
/>
<
AddressLink
fontWeight=
"500"
hash=
{
to
.
hash
}
truncation=
"constant"
/>
</
Flex
>
<
Flex
flexDir=
"column"
rowGap=
{
5
}
>
{
content
}
...
...
ui/tx/TokenTransferList.tsx
View file @
1cec1447
...
...
@@ -10,9 +10,9 @@ interface Props {
}
function
getItemsNum
(
items
:
Array
<
TTokenTransfer
>
)
{
const
nonErc1155items
=
items
.
filter
((
item
)
=>
item
.
token
_
type
!==
'
ERC-1155
'
).
length
;
const
nonErc1155items
=
items
.
filter
((
item
)
=>
item
.
token
.
type
!==
'
ERC-1155
'
).
length
;
const
erc1155items
=
items
.
filter
((
item
)
=>
item
.
token
_
type
===
'
ERC-1155
'
)
.
filter
((
item
)
=>
item
.
token
.
type
===
'
ERC-1155
'
)
.
map
((
item
)
=>
{
if
(
Array
.
isArray
(
item
.
total
))
{
return
item
.
total
.
length
;
...
...
ui/tx/TxDetails.tsx
View file @
1cec1447
import
{
Grid
,
GridItem
,
Text
,
Box
,
Icon
,
Link
,
Spinner
}
from
'
@chakra-ui/react
'
;
import
{
Grid
,
GridItem
,
Text
,
Box
,
Icon
,
Link
,
Spinner
,
Tag
,
Flex
,
Tooltip
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
{
useRouter
}
from
'
next/router
'
;
...
...
@@ -11,9 +11,9 @@ import { QueryKeys } from 'types/client/queries';
import
appConfig
from
'
configs/app/config
'
;
import
clockIcon
from
'
icons/clock.svg
'
;
import
flameIcon
from
'
icons/flame.svg
'
;
import
errorIcon
from
'
icons/status/error.svg
'
;
import
successIcon
from
'
icons/status/success.svg
'
;
import
{
WEI
,
WEI_IN_GWEI
}
from
'
lib/consts
'
;
// import errorIcon from 'icons/status/error.svg';
// import successIcon from 'icons/status/success.svg';
import
dayjs
from
'
lib/date/dayjs
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
getConfirmationDuration
from
'
lib/tx/getConfirmationDuration
'
;
...
...
@@ -73,6 +73,18 @@ const TxDetails = () => {
return
<
DataFetchAlert
/>;
}
const
addressFromTags
=
[
...
data
.
from
.
private_tags
||
[],
...
data
.
from
.
public_tags
||
[],
...
data
.
from
.
watchlist_names
||
[],
].
map
((
tag
)
=>
<
Tag
key=
{
tag
.
label
}
>
{
tag
.
display_name
}
</
Tag
>);
const
addressToTags
=
[
...
data
.
to
.
private_tags
||
[],
...
data
.
to
.
public_tags
||
[],
...
data
.
to
.
watchlist_names
||
[],
].
map
((
tag
)
=>
<
Tag
key=
{
tag
.
label
}
>
{
tag
.
display_name
}
</
Tag
>);
return
(
<
Grid
columnGap=
{
8
}
rowGap=
{
{
base
:
3
,
lg
:
3
}
}
templateColumns=
{
{
base
:
'
minmax(0, 1fr)
'
,
lg
:
'
auto minmax(0, 1fr)
'
}
}
>
<
DetailsInfoItem
...
...
@@ -132,36 +144,51 @@ const TxDetails = () => {
<
DetailsInfoItem
title=
"From"
hint=
"Address (external or contract) sending the transaction."
columnGap=
{
3
}
>
<
Address
>
<
AddressIcon
hash=
{
data
.
from
.
hash
}
/>
<
AddressLink
ml=
{
2
}
hash=
{
data
.
from
.
hash
}
alias=
{
data
.
from
.
name
}
/>
<
AddressLink
ml=
{
2
}
hash=
{
data
.
from
.
hash
}
/>
<
CopyToClipboard
text=
{
data
.
from
.
hash
}
/>
</
Address
>
{
data
.
from
.
name
&&
<
Text
>
{
data
.
from
.
name
}
</
Text
>
}
{
addressFromTags
.
length
>
0
&&
(
<
Flex
columnGap=
{
3
}
>
{
addressFromTags
}
</
Flex
>
)
}
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
{
data
.
to
.
is_contract
?
'
Interacted with contract
'
:
'
To
'
}
hint=
"Address (external or contract) receiving the transaction."
flexWrap=
{
{
base
:
'
wrap
'
,
lg
:
'
nowrap
'
}
}
columnGap=
{
3
}
>
<
Address
mr=
{
3
}
>
<
Address
>
<
AddressIcon
hash=
{
data
.
to
.
hash
}
/>
<
AddressLink
ml=
{
2
}
hash=
{
data
.
to
.
hash
}
alias=
{
data
.
to
.
name
}
/>
<
AddressLink
ml=
{
2
}
hash=
{
data
.
to
.
hash
}
/>
<
CopyToClipboard
text=
{
data
.
to
.
hash
}
/>
</
Address
>
{
/* todo_tom Nikita should add to api later */
}
{
/* <Tag colorScheme="orange" variant="solid" flexShrink={ 0 }>SANA</Tag> */
}
{
/* <Tooltip label="Contract execution completed">
<chakra.span display="inline-flex">
<Icon as={ successIcon } boxSize={ 4 } ml={ 2 } color="green.500" cursor="pointer"/>
</chakra.span>
</Tooltip> */
}
{
/* <Tooltip label="Error occured during contract execution">
<chakra.span display="inline-flex">
<Icon as={ errorIcon } boxSize={ 4 } ml={ 2 } color="red.500" cursor="pointer"/>
</chakra.span>
</Tooltip> */
}
{
/* <TokenSnippet symbol="UP" name="User Pay" hash="0xA17ed5dFc62D0a3E74D69a0503AE9FdA65d9f212" ml={ 3 }/> */
}
{
data
.
to
.
name
&&
<
Text
>
{
data
.
to
.
name
}
</
Text
>
}
{
data
.
to
.
is_contract
&&
data
.
result
===
'
success
'
&&
(
<
Tooltip
label=
"Contract execution completed"
>
<
chakra
.
span
display=
"inline-flex"
>
<
Icon
as=
{
successIcon
}
boxSize=
{
4
}
color=
"green.500"
cursor=
"pointer"
/>
</
chakra
.
span
>
</
Tooltip
>
)
}
{
data
.
to
.
is_contract
&&
Boolean
(
data
.
status
)
&&
data
.
result
!==
'
success
'
&&
(
<
Tooltip
label=
"Error occured during contract execution"
>
<
chakra
.
span
display=
"inline-flex"
>
<
Icon
as=
{
errorIcon
}
boxSize=
{
4
}
color=
"red.500"
cursor=
"pointer"
/>
</
chakra
.
span
>
</
Tooltip
>
)
}
{
addressToTags
.
length
>
0
&&
(
<
Flex
columnGap=
{
3
}
>
{
addressToTags
}
</
Flex
>
)
}
</
DetailsInfoItem
>
{
TOKEN_TRANSFERS
.
map
(({
title
,
hint
,
type
})
=>
{
const
items
=
data
.
token_transfers
?.
filter
((
token
)
=>
token
.
type
===
type
)
||
[];
...
...
ui/tx/TxInternals.tsx
View file @
1cec1447
...
...
@@ -43,16 +43,15 @@ const sortFn = (sort: Sort | undefined) => (a: InternalTransaction, b: InternalT
return
a
.
value
===
b
.
value
?
0
:
result
;
}
// no gas limit in api yet
// case 'gas-limit-desc': {
// const result = a.gasLimit > b.gasLimit ? -1 : 1;
// return a.gasLimit === b.gasLimit ? 0 : result;
// }
// case 'gas-limit-asc': {
// const result = a.gasLimit > b.gasLimit ? 1 : -1;
// return a.gasLimit === b.gasLimit ? 0 : result;
// }
case
'
gas-limit-desc
'
:
{
const
result
=
a
.
gas_limit
>
b
.
gas_limit
?
-
1
:
1
;
return
a
.
gas_limit
===
b
.
gas_limit
?
0
:
result
;
}
case
'
gas-limit-asc
'
:
{
const
result
=
a
.
gas_limit
>
b
.
gas_limit
?
1
:
-
1
;
return
a
.
gas_limit
===
b
.
gas_limit
?
0
:
result
;
}
default
:
return
0
;
...
...
ui/tx/internals/TxInternalsListItem.tsx
View file @
1cec1447
import
{
Flex
,
Tag
,
Icon
,
Box
,
HStack
,
Text
}
from
'
@chakra-ui/react
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
import
type
{
InternalTransaction
}
from
'
types/api/internalTransaction
'
;
...
...
@@ -14,7 +15,7 @@ import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
type
Props
=
InternalTransaction
;
const
TxInternalsListItem
=
({
type
,
from
,
to
,
value
,
success
,
error
}:
Props
)
=>
{
const
TxInternalsListItem
=
({
type
,
from
,
to
,
value
,
success
,
error
,
gas_limit
:
gasLimit
}:
Props
)
=>
{
const
typeTitle
=
TX_INTERNALS_ITEMS
.
find
(({
id
})
=>
id
===
type
)?.
title
;
return
(
...
...
@@ -38,11 +39,10 @@ const TxInternalsListItem = ({ type, from, to, value, success, error }: Props) =
<
Text
fontSize=
"sm"
fontWeight=
{
500
}
>
Value
{
appConfig
.
network
.
currency
.
symbol
}
</
Text
>
<
Text
fontSize=
"sm"
variant=
"secondary"
>
{
value
}
</
Text
>
</
HStack
>
{
/* no gas limit in api yet */
}
{
/* <HStack spacing={ 3 }>
<
HStack
spacing=
{
3
}
>
<
Text
fontSize=
"sm"
fontWeight=
{
500
}
>
Gas limit
</
Text
>
<Text fontSize="sm" variant="secondary">{
gasLimit.toLocaleString('en'
) }</Text>
</HStack>
*/
}
<
Text
fontSize=
"sm"
variant=
"secondary"
>
{
BigNumber
(
gasLimit
).
toFormat
(
)
}
</
Text
>
</
HStack
>
</
AccountListItemMobile
>
);
};
...
...
ui/tx/internals/TxInternalsSkeletonDesktop.tsx
View file @
1cec1447
...
...
@@ -10,7 +10,7 @@ const TxInternalsSkeletonDesktop = () => {
<
Skeleton
w=
"78px"
/>
<
Skeleton
w=
"360px"
/>
</
Flex
>
<
SkeletonTable
columns=
{
[
'
28%
'
,
'
2
8%
'
,
'
24px
'
,
'
28
%
'
,
'
16%
'
]
}
/>
<
SkeletonTable
columns=
{
[
'
28%
'
,
'
2
0%
'
,
'
24px
'
,
'
20%
'
,
'
16
%
'
,
'
16%
'
]
}
/>
</>
);
};
...
...
ui/tx/internals/TxInternalsSkeletonMobile.tsx
View file @
1cec1447
...
...
@@ -38,6 +38,10 @@ const TxInternalsSkeletonMobile = () => {
<
Skeleton
w=
"70px"
mr=
{
2
}
/>
<
Skeleton
w=
"30px"
/>
</
Flex
>
<
Flex
h=
{
6
}
>
<
Skeleton
w=
"70px"
mr=
{
2
}
/>
<
Skeleton
w=
"60px"
/>
</
Flex
>
</
Flex
>
))
}
</
Box
>
...
...
ui/tx/internals/TxInternalsTable.tsx
View file @
1cec1447
...
...
@@ -23,22 +23,21 @@ const TxInternalsTable = ({ data, sort, onSortToggle }: Props) => {
<
Thead
>
<
Tr
>
<
Th
width=
"28%"
>
Type
</
Th
>
<
Th
width=
"2
8
%"
>
From
</
Th
>
<
Th
width=
"2
0
%"
>
From
</
Th
>
<
Th
width=
"24px"
px=
{
0
}
/>
<
Th
width=
"2
8
%"
>
To
</
Th
>
<
Th
width=
"2
0
%"
>
To
</
Th
>
<
Th
width=
"16%"
isNumeric
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-end"
onClick=
{
onSortToggle
(
'
value
'
)
}
columnGap=
{
1
}
>
{
sort
?.
includes
(
'
value
'
)
&&
<
Icon
as=
{
arrowIcon
}
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Value
{
appConfig
.
network
.
currency
.
symbol
}
</
Link
>
</
Th
>
{
/* no gas limit in api yet */
}
{
/* <Th width="16%" isNumeric>
<
Th
width=
"16%"
isNumeric
>
<
Link
display=
"flex"
alignItems=
"center"
justifyContent=
"flex-end"
onClick=
{
onSortToggle
(
'
gas-limit
'
)
}
columnGap=
{
1
}
>
{
sort
?.
includes
(
'
gas-limit
'
)
&&
<
Icon
as=
{
arrowIcon
}
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Gas limit
Gas limit
{
appConfig
.
network
.
currency
.
symbol
}
</
Link
>
</Th>
*/
}
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
>
...
...
ui/tx/internals/TxInternalsTableItem.tsx
View file @
1cec1447
import
{
Tr
,
Td
,
Tag
,
Icon
,
Box
}
from
'
@chakra-ui/react
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
import
type
{
InternalTransaction
}
from
'
types/api/internalTransaction
'
;
...
...
@@ -12,7 +13,7 @@ import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
type
Props
=
InternalTransaction
const
TxInternalTableItem
=
({
type
,
from
,
to
,
value
,
success
,
error
}:
Props
)
=>
{
const
TxInternalTableItem
=
({
type
,
from
,
to
,
value
,
success
,
error
,
gas_limit
:
gasLimit
}:
Props
)
=>
{
const
typeTitle
=
TX_INTERNALS_ITEMS
.
find
(({
id
})
=>
id
===
type
)?.
title
;
return
(
...
...
@@ -43,10 +44,9 @@ const TxInternalTableItem = ({ type, from, to, value, success, error }: Props) =
<
Td
isNumeric
verticalAlign=
"middle"
>
{
value
}
</
Td
>
{
/* no gas limit in api yet */
}
{
/* <Td isNumeric verticalAlign='middle'>
{ gasLimit.toLocaleString('en') }
</Td> */
}
<
Td
isNumeric
verticalAlign=
"middle"
>
{
BigNumber
(
gasLimit
).
toFormat
()
}
</
Td
>
</
Tr
>
);
};
...
...
ui/txs/TxsListItem.tsx
View file @
1cec1447
...
...
@@ -60,6 +60,7 @@ const TxsListItem = ({ tx }: {tx: Transaction}) => {
type=
"transaction"
fontWeight=
"700"
truncation=
"constant"
target=
"_self"
/>
</
Address
>
</
Flex
>
...
...
ui/txs/TxsTableItem.tsx
View file @
1cec1447
...
...
@@ -86,6 +86,7 @@ const TxsTableItem = ({ tx }: {tx: Transaction}) => {
hash=
{
tx
.
hash
}
type=
"transaction"
fontWeight=
"700"
target=
"_self"
/>
</
Address
>
<
Text
color=
"gray.500"
fontWeight=
"400"
>
{
dayjs
(
tx
.
timestamp
).
fromNow
()
}
</
Text
>
...
...
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