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
23155089
Commit
23155089
authored
Oct 10, 2022
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
api for blocks
parent
24258d46
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
140 additions
and
104 deletions
+140
-104
block.ts
data/block.ts
+0
-33
blocks.ts
data/blocks.ts
+0
-35
index.ts
pages/api/blocks/index.ts
+11
-0
block.ts
types/api/block.ts
+4
-2
BlocksContent.tsx
ui/blocks/BlocksContent.tsx
+41
-4
BlocksList.tsx
ui/blocks/BlocksList.tsx
+8
-3
BlocksListItem.tsx
ui/blocks/BlocksListItem.tsx
+13
-11
BlocksSkeletonMobile.tsx
ui/blocks/BlocksSkeletonMobile.tsx
+37
-0
BlocksTable.tsx
ui/blocks/BlocksTable.tsx
+8
-3
BlocksTableItem.tsx
ui/blocks/BlocksTableItem.tsx
+16
-11
Blocks.tsx
ui/pages/Blocks.tsx
+2
-2
No files found.
data/block.ts
deleted
100644 → 0
View file @
24258d46
/* eslint-disable max-len */
export
const
block
=
{
height
:
15006918
,
size
:
1754
,
timestamp
:
1662623567695
,
transactionsNum
:
99
,
miner
:
{
name
:
'
Alex Emelyanov
'
,
address
:
'
0xdAd49e6CbDE849353ab27DeC6319E687BFc91A41
'
,
},
minedIn
:
20
,
reward
:
{
'
static
'
:
2
,
tx_fee
:
0.1550895290904872
,
},
burnt_fees
:
0.15116230256264004
,
gas_limit
:
30000000
,
gas_used
:
12866397
,
gas_target
:
14266397
,
base_fee_per_gas
:
11.748611718
,
data
:
{
hex
:
'
0x7370657468303367c18300
'
,
utf
:
'
speth03g��
'
,
},
difficulty
:
'
14,735,262,741,740,473
'
,
totalDifficulty
:
'
52,307,701,288,535,570,059,059
'
,
hash
:
'
0x1ea365d2144796f793883534aa51bf20d23292b19478994eede23dfc599e7c34
'
,
parent_hash
:
'
0x4585ac59fdfd84443d93c9216e5172f57ca204639d3e68d1908088b0ebd3e709
'
,
parent_height
:
29471346
,
sha3_uncles
:
'
0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
'
,
state_root
:
'
0x434fb3f234c8cffc1d915ad26ea360b0261d183ad37af89e31b839df4dd0b00f
'
,
nonce
:
'
0xde80e5b4dd984384
'
,
};
data/blocks.ts
deleted
100644 → 0
View file @
24258d46
/* eslint-disable max-len */
import
{
block
}
from
'
./block
'
;
export
const
blocks
=
[
{
...
block
,
timestamp
:
Date
.
now
()
-
25
_000
,
},
{
...
block
,
height
:
15006917
,
timestamp
:
Date
.
now
()
-
1
_000
*
60
*
2
,
miner
:
{
address
:
'
0xdAd49e6CbDE849353ab27DeC6319E687BFc91A41
'
,
name
:
undefined
,
},
transactionsNum
:
185
,
size
:
452
,
gas_limit
:
30000000
,
gas_used
:
15671326
,
gas_target
:
14671326
,
burnt_fees
:
0.3988042215537949
,
},
{
...
block
,
height
:
15006916
,
timestamp
:
Date
.
now
()
-
1
_000
*
60
*
60
*
17
,
transactionsNum
:
377
,
size
:
5222
,
gas_limit
:
30000000
,
gas_used
:
23856751
,
gas_target
:
28856751
,
burnt_fees
:
0.0000019660909367
,
},
];
pages/api/blocks/index.ts
0 → 100644
View file @
23155089
import
type
{
NextApiRequest
}
from
'
next
'
;
import
handler
from
'
lib/api/handler
'
;
const
getUrl
=
(
req
:
NextApiRequest
)
=>
{
return
`/v2/blocks?type=
${
req
.
query
.
type
}
`
;
};
const
requestHandler
=
handler
(
getUrl
,
[
'
GET
'
]);
export
default
requestHandler
;
types/api/block.ts
View file @
23155089
import
type
{
AddressParam
}
from
'
types/api/addressParams
'
;
import
type
{
Reward
}
from
'
types/api/reward
'
;
export
type
BlockType
=
'
block
'
|
'
reorg
'
|
'
uncle
'
;
export
interface
Block
{
height
:
number
;
timestamp
:
string
;
...
...
@@ -23,12 +25,12 @@ export interface Block {
gas_target_percentage
:
number
|
null
;
gas_used_percentage
:
number
|
null
;
burnt_fees_percentage
:
number
|
null
;
type
:
'
block
'
|
'
reorg
'
|
'
uncle
'
;
type
:
BlockType
;
tx_fees
:
string
|
null
;
uncles_hashes
:
Array
<
string
>
;
}
export
interface
BlockResponse
{
export
interface
Block
s
Response
{
items
:
Array
<
Block
>
;
next_page_params
:
{
block_number
:
number
;
...
...
ui/blocks/BlocksContent.tsx
View file @
23155089
import
{
Box
,
Text
,
Show
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Text
,
Show
,
Alert
}
from
'
@chakra-ui/react
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
type
{
BlockType
,
BlocksResponse
}
from
'
types/api/block
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
BlocksList
from
'
ui/blocks/BlocksList
'
;
import
BlocksSkeletonMobile
from
'
ui/blocks/BlocksSkeletonMobile
'
;
import
BlocksTable
from
'
ui/blocks/BlocksTable
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
Pagination
from
'
ui/shared/Pagination
'
;
import
SkeletonTable
from
'
ui/shared/SkeletonTable
'
;
interface
Props
{
type
?:
BlockType
;
}
const
BlocksContent
=
({
type
}:
Props
)
=>
{
const
fetch
=
useFetch
();
const
{
data
,
isLoading
,
isError
}
=
useQuery
<
unknown
,
unknown
,
BlocksResponse
>
(
[
'
blocks
'
,
type
],
async
()
=>
await
fetch
(
`/api/blocks?type=
${
type
}
`
),
);
if
(
isLoading
)
{
return
(
<>
<
Show
below=
"lg"
><
BlocksSkeletonMobile
/></
Show
>
<
Show
above=
"lg"
>
<
SkeletonTable
columns=
{
[
'
124px
'
,
'
112px
'
,
'
144px
'
,
'
64px
'
,
'
40%
'
,
'
30%
'
,
'
30%
'
]
}
/>
</
Show
>
</>
);
}
if
(
isError
)
{
return
<
DataFetchAlert
/>;
}
if
(
data
.
items
.
length
===
0
)
{
return
<
Alert
>
There are no blocks.
</
Alert
>;
}
const
BlocksContent
=
()
=>
{
return
(
<>
<
Text
>
Total of 15,044,883 blocks
</
Text
>
<
Show
below=
"lg"
><
BlocksList
/></
Show
>
<
Show
above=
"lg"
><
BlocksTable
/></
Show
>
<
Show
below=
"lg"
><
BlocksList
data=
{
data
.
items
}
/></
Show
>
<
Show
above=
"lg"
><
BlocksTable
data=
{
data
.
items
}
/></
Show
>
<
Box
mx=
{
{
base
:
0
,
lg
:
6
}
}
my=
{
{
base
:
6
,
lg
:
3
}
}
>
<
Pagination
currentPage=
{
1
}
/>
</
Box
>
...
...
ui/blocks/BlocksList.tsx
View file @
23155089
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
blocks
}
from
'
data/blocks
'
;
import
type
{
Block
}
from
'
types/api/block
'
;
import
BlocksListItem
from
'
ui/blocks/BlocksListItem
'
;
const
BlocksList
=
()
=>
{
interface
Props
{
data
:
Array
<
Block
>
;
}
const
BlocksList
=
({
data
}:
Props
)
=>
{
return
(
<
Box
mt=
{
8
}
>
{
blocks
.
map
((
item
,
index
)
=>
<
BlocksListItem
key=
{
item
.
height
}
data=
{
item
}
isPending=
{
index
===
0
}
/>)
}
{
data
.
map
((
item
,
index
)
=>
<
BlocksListItem
key=
{
item
.
height
}
data=
{
item
}
isPending=
{
index
===
0
}
/>)
}
</
Box
>
);
};
...
...
ui/blocks/BlocksListItem.tsx
View file @
23155089
import
{
Flex
,
Link
,
Spinner
,
Text
,
Box
,
Icon
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
utils
}
from
'
ethers
'
;
import
React
from
'
react
'
;
import
type
ArrayElement
from
'
types/utils/ArrayElement
'
;
import
type
{
Block
}
from
'
types/api/block
'
;
import
type
{
blocks
}
from
'
data/blocks
'
;
import
flameIcon
from
'
icons/flame.svg
'
;
import
getBlockReward
from
'
lib/block/getBlockReward
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
useNetwork
from
'
lib/hooks/useNetwork
'
;
import
useLink
from
'
lib/link/useLink
'
;
...
...
@@ -14,7 +15,7 @@ import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import
Utilization
from
'
ui/shared/Utilization
'
;
interface
Props
{
data
:
ArrayElement
<
typeof
blocks
>
;
data
:
Block
;
isPending
?:
boolean
;
}
...
...
@@ -22,6 +23,7 @@ const BlocksListItem = ({ data, isPending }: Props) => {
const
spinnerEmptyColor
=
useColorModeValue
(
'
blackAlpha.200
'
,
'
whiteAlpha.200
'
);
const
link
=
useLink
();
const
network
=
useNetwork
();
const
{
totalReward
,
burntFees
,
txFees
}
=
getBlockReward
(
data
);
return
(
<
AccountListItemMobile
rowGap=
{
3
}
>
...
...
@@ -43,29 +45,29 @@ const BlocksListItem = ({ data, isPending }: Props) => {
</
Flex
>
<
Flex
columnGap=
{
2
}
>
<
Text
fontWeight=
{
500
}
>
Miner
</
Text
>
<
AddressLink
alias=
{
data
.
miner
?.
name
}
hash=
{
data
.
miner
.
address
}
truncation=
"constant"
/>
<
AddressLink
alias=
{
data
.
miner
.
name
}
hash=
{
data
.
miner
.
hash
}
truncation=
"constant"
/>
</
Flex
>
<
Flex
columnGap=
{
2
}
>
<
Text
fontWeight=
{
500
}
>
Txn
</
Text
>
<
Text
variant=
"secondary"
>
{
data
.
t
ransactionsNum
}
</
Text
>
<
Text
variant=
"secondary"
>
{
data
.
t
x_count
}
</
Text
>
</
Flex
>
<
Box
>
<
Text
fontWeight=
{
500
}
>
Gas used
</
Text
>
<
Flex
columnGap=
{
4
}
>
<
Text
variant=
"secondary"
>
{
data
.
gas_used
.
toLocaleString
(
'
en
'
)
}
</
Text
>
<
Utilization
colorScheme=
"gray"
value=
{
data
.
gas_used
/
data
.
gas_limit
}
/>
<
GasUsedToTargetRatio
used=
{
data
.
gas_used
}
target=
{
data
.
gas_target
}
/>
<
Text
variant=
"secondary"
>
{
utils
.
commify
(
data
.
gas_used
)
}
</
Text
>
<
Utilization
colorScheme=
"gray"
value=
{
utils
.
parseUnits
(
data
.
gas_used
).
mul
(
10
_000
).
div
(
utils
.
parseUnits
(
data
.
gas_limit
)).
toNumber
()
/
10
_000
}
/>
<
GasUsedToTargetRatio
value=
{
data
.
gas_target_percentage
||
undefined
}
/>
</
Flex
>
</
Box
>
<
Flex
columnGap=
{
2
}
>
<
Text
fontWeight=
{
500
}
>
Reward
{
network
?.
currency
}
</
Text
>
<
Text
variant=
"secondary"
>
{
(
data
.
reward
.
static
+
data
.
reward
.
tx_fee
-
data
.
burnt_fees
).
toLocaleString
(
'
en
'
,
{
maximumFractionDigits
:
5
}
)
}
</
Text
>
<
Text
variant=
"secondary"
>
{
utils
.
formatUnits
(
totalReward
)
}
</
Text
>
</
Flex
>
<
Flex
>
<
Text
fontWeight=
{
500
}
>
Burnt fees
</
Text
>
<
Icon
as=
{
flameIcon
}
boxSize=
{
5
}
color=
"gray.500"
ml=
{
2
}
/>
<
Text
variant=
"secondary"
ml=
{
1
}
>
{
data
.
burnt_fees
.
toLocaleString
(
'
en
'
,
{
maximumFractionDigits
:
6
}
)
}
</
Text
>
<
Utilization
ml=
{
4
}
value=
{
data
.
burnt_fees
/
data
.
reward
.
tx_fee
}
/>
<
Text
variant=
"secondary"
ml=
{
1
}
>
{
utils
.
formatUnits
(
burntFees
)
}
</
Text
>
<
Utilization
ml=
{
4
}
value=
{
burntFees
.
mul
(
10
_000
).
div
(
txFees
).
toNumber
()
/
10
_000
}
/>
</
Flex
>
</
AccountListItemMobile
>
);
...
...
ui/blocks/BlocksSkeletonMobile.tsx
0 → 100644
View file @
23155089
import
{
Skeleton
,
Flex
,
Box
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
const
BlocksSkeletonMobile
=
()
=>
{
const
borderColor
=
useColorModeValue
(
'
blackAlpha.200
'
,
'
whiteAlpha.200
'
);
return
(
<
Box
>
{
Array
.
from
(
Array
(
2
)).
map
((
item
,
index
)
=>
(
<
Flex
key=
{
index
}
rowGap=
{
3
}
flexDirection=
"column"
paddingY=
{
6
}
borderTopWidth=
"1px"
borderColor=
{
borderColor
}
_last=
{
{
borderBottomWidth
:
'
1px
'
,
}
}
>
<
Flex
h=
{
6
}
justifyContent=
"space-between"
>
<
Skeleton
w=
"75px"
/>
<
Skeleton
w=
"90px"
/>
</
Flex
>
<
Skeleton
h=
{
6
}
w=
"130px"
/>
<
Skeleton
h=
{
6
}
w=
"180px"
/>
<
Skeleton
h=
{
6
}
w=
"60px"
/>
<
Skeleton
h=
{
6
}
w=
"100%"
/>
<
Skeleton
h=
{
6
}
w=
"170px"
/>
<
Skeleton
h=
{
6
}
w=
"100%"
/>
</
Flex
>
))
}
</
Box
>
);
};
export
default
BlocksSkeletonMobile
;
ui/blocks/BlocksTable.tsx
View file @
23155089
import
{
Table
,
Thead
,
Tbody
,
Tr
,
Th
,
TableContainer
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
blocks
}
from
'
data/blocks
'
;
import
type
{
Block
}
from
'
types/api/block
'
;
import
useNetwork
from
'
lib/hooks/useNetwork
'
;
import
BlocksTableItem
from
'
ui/blocks/BlocksTableItem
'
;
const
BlocksTable
=
()
=>
{
interface
Props
{
data
:
Array
<
Block
>
;
}
const
BlocksTable
=
({
data
}:
Props
)
=>
{
const
network
=
useNetwork
();
return
(
...
...
@@ -23,7 +28,7 @@ const BlocksTable = () => {
</
Tr
>
</
Thead
>
<
Tbody
>
{
blocks
.
map
((
item
,
index
)
=>
<
BlocksTableItem
key=
{
item
.
height
}
data=
{
item
}
isPending=
{
index
===
0
}
/>)
}
{
data
.
map
((
item
,
index
)
=>
<
BlocksTableItem
key=
{
item
.
height
}
data=
{
item
}
isPending=
{
index
===
0
}
/>)
}
</
Tbody
>
</
Table
>
</
TableContainer
>
...
...
ui/blocks/BlocksTableItem.tsx
View file @
23155089
import
{
Tr
,
Td
,
Text
,
Link
,
Flex
,
Box
,
Icon
,
Tooltip
,
Spinner
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
utils
}
from
'
ethers
'
;
import
React
from
'
react
'
;
import
type
ArrayElement
from
'
types/utils/ArrayElement
'
;
import
type
{
Block
}
from
'
types/api/block
'
;
import
type
{
blocks
}
from
'
data/blocks
'
;
import
flameIcon
from
'
icons/flame.svg
'
;
import
getBlockReward
from
'
lib/block/getBlockReward
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
useLink
from
'
lib/link/useLink
'
;
import
AddressLink
from
'
ui/shared/address/AddressLink
'
;
...
...
@@ -12,7 +13,7 @@ import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import
Utilization
from
'
ui/shared/Utilization
'
;
interface
Props
{
data
:
ArrayElement
<
typeof
blocks
>
;
data
:
Block
;
isPending
?:
boolean
;
}
...
...
@@ -20,6 +21,7 @@ const BlocksTableItem = ({ data, isPending }: Props) => {
const
link
=
useLink
();
const
spinnerEmptyColor
=
useColorModeValue
(
'
blackAlpha.200
'
,
'
whiteAlpha.200
'
);
const
{
totalReward
,
burntFees
,
txFees
}
=
getBlockReward
(
data
);
return
(
<
Tr
>
...
...
@@ -37,25 +39,28 @@ const BlocksTableItem = ({ data, isPending }: Props) => {
</
Td
>
<
Td
fontSize=
"sm"
>
{
data
.
size
.
toLocaleString
(
'
en
'
)
}
bytes
</
Td
>
<
Td
fontSize=
"sm"
>
<
AddressLink
alias=
{
data
.
miner
?.
name
}
hash=
{
data
.
miner
.
address
}
truncation=
"constant"
/>
<
AddressLink
alias=
{
data
.
miner
.
name
}
hash=
{
data
.
miner
.
hash
}
truncation=
"constant"
/>
</
Td
>
<
Td
isNumeric
fontSize=
"sm"
>
{
data
.
t
ransactionsNum
}
</
Td
>
<
Td
isNumeric
fontSize=
"sm"
>
{
data
.
t
x_count
}
</
Td
>
<
Td
fontSize=
"sm"
>
<
Box
>
{
data
.
gas_used
.
toLocaleString
(
'
en
'
)
}
</
Box
>
<
Box
>
{
utils
.
commify
(
data
.
gas_used
)
}
</
Box
>
<
Flex
mt=
{
2
}
>
<
Utilization
colorScheme=
"gray"
value=
{
data
.
gas_used
/
data
.
gas_limit
}
/>
<
GasUsedToTargetRatio
ml=
{
2
}
used=
{
data
.
gas_used
}
target=
{
data
.
gas_target
}
/>
<
Utilization
colorScheme=
"gray"
value=
{
utils
.
parseUnits
(
data
.
gas_used
).
mul
(
10
_000
).
div
(
utils
.
parseUnits
(
data
.
gas_limit
)).
toNumber
()
/
10
_000
}
/>
<
GasUsedToTargetRatio
ml=
{
2
}
value=
{
data
.
gas_target_percentage
||
undefined
}
/>
</
Flex
>
</
Td
>
<
Td
fontSize=
"sm"
>
{
(
data
.
reward
.
static
+
data
.
reward
.
tx_fee
-
data
.
burnt_fees
).
toLocaleString
(
'
en
'
,
{
maximumFractionDigits
:
5
}
)
}
</
Td
>
<
Td
fontSize=
"sm"
>
{
utils
.
formatUnits
(
totalReward
)
}
</
Td
>
<
Td
fontSize=
"sm"
>
<
Flex
alignItems=
"center"
columnGap=
{
1
}
>
<
Icon
as=
{
flameIcon
}
boxSize=
{
5
}
color=
{
useColorModeValue
(
'
gray.500
'
,
'
inherit
'
)
}
/>
{
data
.
burnt_fees
.
toLocaleString
(
'
en
'
,
{
maximumFractionDigits
:
6
}
)
}
{
utils
.
formatUnits
(
burntFees
)
}
</
Flex
>
<
Tooltip
label=
"Burnt fees / Txn fees * 100%"
>
<
Box
>
<
Utilization
mt=
{
2
}
value=
{
data
.
burnt_fees
/
data
.
reward
.
tx_fee
}
/>
<
Utilization
mt=
{
2
}
value=
{
burntFees
.
mul
(
10
_000
).
div
(
txFees
).
toNumber
()
/
10
_000
}
/>
</
Box
>
</
Tooltip
>
</
Td
>
...
...
ui/pages/Blocks.tsx
View file @
23155089
...
...
@@ -9,8 +9,8 @@ import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs';
const
TABS
:
Array
<
RoutedTab
>
=
[
{
routeName
:
'
blocks
'
,
title
:
'
All
'
,
component
:
<
BlocksContent
/>
},
{
routeName
:
'
blocks_reorgs
'
,
title
:
'
Forked
'
,
component
:
<
BlocksContent
/>
},
{
routeName
:
'
blocks_uncles
'
,
title
:
'
Uncles
'
,
component
:
<
BlocksContent
/>
},
{
routeName
:
'
blocks_reorgs
'
,
title
:
'
Forked
'
,
component
:
<
BlocksContent
type=
"reorg"
/>
},
{
routeName
:
'
blocks_uncles
'
,
title
:
'
Uncles
'
,
component
:
<
BlocksContent
type=
"uncle"
/>
},
];
export
interface
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