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
7ad5a392
Commit
7ad5a392
authored
Oct 01, 2023
by
isstuev
Committed by
isstuev
Oct 23, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
batch page and latest batch
parent
b9230bfe
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
740 additions
and
20 deletions
+740
-20
.env.zkevm
configs/envs/.env.zkevm
+1
-1
resources.ts
lib/api/resources.ts
+12
-2
zkevmL2txnBatches.ts
mocks/zkevmL2txnBatches/zkevmL2txnBatches.ts
+26
-0
getServerSideProps.ts
nextjs/getServerSideProps.ts
+2
-0
nextjs-routes.d.ts
nextjs/nextjs-routes.d.ts
+1
-0
[number].tsx
pages/zkevm-l2-txn-batch/[number].tsx
+20
-0
zkEvmL2.ts
stubs/zkEvmL2.ts
+13
-1
transaction.ts
types/api/transaction.ts
+5
-0
zkEvml2TxnBatches.ts
types/api/zkEvml2TxnBatches.ts
+14
-2
LatestZkevmBatches.pw.tsx
ui/home/LatestZkevmBatches.pw.tsx
+156
-0
LatestZkevmBatches.tsx
ui/home/LatestZkevmBatches.tsx
+115
-0
Stats.tsx
ui/home/Stats.tsx
+26
-8
ZkEvmL2TxnBatch.tsx
ui/pages/ZkEvmL2TxnBatch.tsx
+116
-0
DetailsInfoItem.tsx
ui/shared/DetailsInfoItem.tsx
+2
-2
TxDetails.tsx
ui/tx/TxDetails.tsx
+44
-0
ZkEvmL2TxnBatchDetails.tsx
ui/zkEvmL2TxnBatches/ZkEvmL2TxnBatchDetails.tsx
+183
-0
ZkEvmTxnBatchesListItem.tsx
ui/zkEvmL2TxnBatches/ZkEvmTxnBatchesListItem.tsx
+2
-3
ZkEvmTxnBatchesTableItem.tsx
ui/zkEvmL2TxnBatches/ZkEvmTxnBatchesTableItem.tsx
+2
-1
No files found.
configs/envs/.env.zkevm
View file @
7ad5a392
...
@@ -44,4 +44,4 @@ NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.co
...
@@ -44,4 +44,4 @@ NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.co
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
# rollup
# rollup
NEXT_PUBLIC_IS_ZKEVM_L2_NETWORK=true
NEXT_PUBLIC_IS_ZKEVM_L2_NETWORK=true
NEXT_PUBLIC_L1_BASE_URL=http://65.109.173.70:81
/
NEXT_PUBLIC_L1_BASE_URL=http://65.109.173.70:81
lib/api/resources.ts
View file @
7ad5a392
...
@@ -59,7 +59,7 @@ import type { TTxsFilters } from 'types/api/txsFilters';
...
@@ -59,7 +59,7 @@ import type { TTxsFilters } from 'types/api/txsFilters';
import
type
{
TxStateChanges
}
from
'
types/api/txStateChanges
'
;
import
type
{
TxStateChanges
}
from
'
types/api/txStateChanges
'
;
import
type
{
VisualizedContract
}
from
'
types/api/visualization
'
;
import
type
{
VisualizedContract
}
from
'
types/api/visualization
'
;
import
type
{
WithdrawalsResponse
,
WithdrawalsCounters
}
from
'
types/api/withdrawals
'
;
import
type
{
WithdrawalsResponse
,
WithdrawalsCounters
}
from
'
types/api/withdrawals
'
;
import
type
{
ZkEvmL2TxnBatchesResponse
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
type
{
ZkEvmL2TxnBatch
,
ZkEvmL2TxnBatch
esResponse
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
type
{
ArrayElement
}
from
'
types/utils
'
;
import
type
{
ArrayElement
}
from
'
types/utils
'
;
import
config
from
'
configs/app
'
;
import
config
from
'
configs/app
'
;
...
@@ -433,6 +433,9 @@ export const RESOURCES = {
...
@@ -433,6 +433,9 @@ export const RESOURCES = {
homepage_indexing_status
:
{
homepage_indexing_status
:
{
path
:
'
/api/v2/main-page/indexing-status
'
,
path
:
'
/api/v2/main-page/indexing-status
'
,
},
},
homepage_zkevm_latest_batch
:
{
path
:
'
/api/v2/main-page/zkevm/batches/latest-number
'
,
},
// SEARCH
// SEARCH
quick_search
:
{
quick_search
:
{
...
@@ -493,6 +496,11 @@ export const RESOURCES = {
...
@@ -493,6 +496,11 @@ export const RESOURCES = {
path
:
'
/api/v2/zkevm/batches/count
'
,
path
:
'
/api/v2/zkevm/batches/count
'
,
},
},
zkevm_l2_txn_batch
:
{
path
:
'
/api/v2/zkevm/batches/:number
'
,
pathParams
:
[
'
number
'
as
const
],
},
// CONFIGS
// CONFIGS
config_backend_version
:
{
config_backend_version
:
{
path
:
'
/api/v2/config/backend-version
'
,
path
:
'
/api/v2/config/backend-version
'
,
...
@@ -562,7 +570,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
...
@@ -562,7 +570,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'
token_instance_transfers
'
|
'
token_instance_holders
'
|
'
token_instance_transfers
'
|
'
token_instance_holders
'
|
'
verified_contracts
'
|
'
verified_contracts
'
|
'
l2_output_roots
'
|
'
l2_withdrawals
'
|
'
l2_txn_batches
'
|
'
l2_deposits
'
|
'
l2_output_roots
'
|
'
l2_withdrawals
'
|
'
l2_txn_batches
'
|
'
l2_deposits
'
|
'
zkevm_l2_txn_batches
'
|
'
zkevm_l2_txn_batches
'
|
'
zkevm_l2_txn_batch_txs
'
|
'
withdrawals
'
|
'
address_withdrawals
'
|
'
block_withdrawals
'
;
'
withdrawals
'
|
'
address_withdrawals
'
|
'
block_withdrawals
'
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
export
type
PaginatedResponse
<
Q
extends
PaginatedResources
>
=
ResourcePayload
<
Q
>
;
...
@@ -587,6 +595,7 @@ Q extends 'homepage_txs' ? Array<Transaction> :
...
@@ -587,6 +595,7 @@ Q extends 'homepage_txs' ? Array<Transaction> :
Q
extends
'
homepage_txs_watchlist
'
?
Array
<
Transaction
>
:
Q
extends
'
homepage_txs_watchlist
'
?
Array
<
Transaction
>
:
Q
extends
'
homepage_deposits
'
?
Array
<
L2DepositsItem
>
:
Q
extends
'
homepage_deposits
'
?
Array
<
L2DepositsItem
>
:
Q
extends
'
homepage_indexing_status
'
?
IndexingStatus
:
Q
extends
'
homepage_indexing_status
'
?
IndexingStatus
:
Q
extends
'
homepage_zkevm_latest_batch
'
?
number
:
Q
extends
'
stats_counters
'
?
Counters
:
Q
extends
'
stats_counters
'
?
Counters
:
Q
extends
'
stats_lines
'
?
StatsCharts
:
Q
extends
'
stats_lines
'
?
StatsCharts
:
Q
extends
'
stats_line
'
?
StatsChart
:
Q
extends
'
stats_line
'
?
StatsChart
:
...
@@ -653,6 +662,7 @@ Q extends 'l2_deposits_count' ? number :
...
@@ -653,6 +662,7 @@ Q extends 'l2_deposits_count' ? number :
Q
extends
'
l2_txn_batches_count
'
?
number
:
Q
extends
'
l2_txn_batches_count
'
?
number
:
Q
extends
'
zkevm_l2_txn_batches
'
?
ZkEvmL2TxnBatchesResponse
:
Q
extends
'
zkevm_l2_txn_batches
'
?
ZkEvmL2TxnBatchesResponse
:
Q
extends
'
zkevm_l2_txn_batches_count
'
?
number
:
Q
extends
'
zkevm_l2_txn_batches_count
'
?
number
:
Q
extends
'
zkevm_l2_txn_batch
'
?
ZkEvmL2TxnBatch
:
Q
extends
'
config_backend_version
'
?
BackendVersionConfig
:
Q
extends
'
config_backend_version
'
?
BackendVersionConfig
:
never
;
never
;
/* eslint-enable @typescript-eslint/indent */
/* eslint-enable @typescript-eslint/indent */
...
...
mocks/zkevmL2txnBatches/zkevmL2txnBatches.ts
0 → 100644
View file @
7ad5a392
import
type
{
ZkEvmL2TxnBatchesResponse
}
from
'
types/api/zkEvml2TxnBatches
'
;
export
const
txnBatchesData
:
ZkEvmL2TxnBatchesResponse
=
{
items
:
[
{
timestamp
:
'
2023-06-01T14:46:48.000000Z
'
,
status
:
'
Finalized
'
,
verify_tx_hash
:
'
0x48139721f792d3a68c3781b4cf50e66e8fc7dbb38adff778e09066ea5be9adb8
'
,
sequence_tx_hash
:
'
0x6aa081e8e33a085e4ec7124fcd8a5f7d36aac0828f176e80d4b70e313a11695b
'
,
number
:
5218590
,
tx_count
:
9
,
},
{
timestamp
:
'
2023-06-01T14:46:48.000000Z
'
,
status
:
'
Unfinalized
'
,
verify_tx_hash
:
null
,
sequence_tx_hash
:
null
,
number
:
5218590
,
tx_count
:
9
,
},
],
next_page_params
:
{
number
:
5902834
,
items_count
:
50
,
},
};
nextjs/getServerSideProps.ts
View file @
7ad5a392
...
@@ -8,6 +8,7 @@ export type Props = {
...
@@ -8,6 +8,7 @@ export type Props = {
id
:
string
;
id
:
string
;
height_or_hash
:
string
;
height_or_hash
:
string
;
hash
:
string
;
hash
:
string
;
number
:
string
;
q
:
string
;
q
:
string
;
}
}
...
@@ -19,6 +20,7 @@ export const base: GetServerSideProps<Props> = async({ req, query }) => {
...
@@ -19,6 +20,7 @@ export const base: GetServerSideProps<Props> = async({ req, query }) => {
id
:
query
.
id
?.
toString
()
||
''
,
id
:
query
.
id
?.
toString
()
||
''
,
hash
:
query
.
hash
?.
toString
()
||
''
,
hash
:
query
.
hash
?.
toString
()
||
''
,
height_or_hash
:
query
.
height_or_hash
?.
toString
()
||
''
,
height_or_hash
:
query
.
height_or_hash
?.
toString
()
||
''
,
number
:
query
.
number
?.
toString
()
||
''
,
q
:
query
.
q
?.
toString
()
||
''
,
q
:
query
.
q
?.
toString
()
||
''
,
},
},
};
};
...
...
nextjs/nextjs-routes.d.ts
View file @
7ad5a392
...
@@ -47,6 +47,7 @@ declare module "nextjs-routes" {
...
@@ -47,6 +47,7 @@ declare module "nextjs-routes" {
|
StaticRoute
<
"
/verified-contracts
"
>
|
StaticRoute
<
"
/verified-contracts
"
>
|
StaticRoute
<
"
/visualize/sol2uml
"
>
|
StaticRoute
<
"
/visualize/sol2uml
"
>
|
StaticRoute
<
"
/withdrawals
"
>
|
StaticRoute
<
"
/withdrawals
"
>
|
DynamicRoute
<
"
/zkevm-l2-txn-batch/[number]
"
,
{
"
number
"
:
string
}
>
|
StaticRoute
<
"
/zkevm-l2-txn-batches
"
>
;
|
StaticRoute
<
"
/zkevm-l2-txn-batches
"
>
;
interface
StaticRoute
<
Pathname
>
{
interface
StaticRoute
<
Pathname
>
{
...
...
pages/zkevm-l2-txn-batch/[number].tsx
0 → 100644
View file @
7ad5a392
import
type
{
NextPage
}
from
'
next
'
;
import
dynamic
from
'
next/dynamic
'
;
import
React
from
'
react
'
;
import
type
{
Props
}
from
'
nextjs/getServerSideProps
'
;
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
const
ZkEvmL2TxnBatch
=
dynamic
(()
=>
import
(
'
ui/pages/ZkEvmL2TxnBatch
'
),
{
ssr
:
false
});
const
Page
:
NextPage
<
Props
>
=
(
props
:
Props
)
=>
{
return
(
<
PageNextJs
pathname=
"/zkevm-l2-txn-batch/[number]"
query=
{
props
}
>
<
ZkEvmL2TxnBatch
/>
</
PageNextJs
>
);
};
export
default
Page
;
export
{
zkEvmL2
as
getServerSideProps
}
from
'
nextjs/getServerSideProps
'
;
stubs/zkEvmL2.ts
View file @
7ad5a392
import
type
{
ZkEvmL2TxnBatchesItem
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
type
{
ZkEvmL2TxnBatch
,
ZkEvmL2TxnBatch
esItem
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
{
TX_HASH
}
from
'
./tx
'
;
import
{
TX_HASH
}
from
'
./tx
'
;
...
@@ -10,3 +10,15 @@ export const ZKEVM_L2_TXN_BATCHES_ITEM: ZkEvmL2TxnBatchesItem = {
...
@@ -10,3 +10,15 @@ export const ZKEVM_L2_TXN_BATCHES_ITEM: ZkEvmL2TxnBatchesItem = {
number
:
5218590
,
number
:
5218590
,
tx_count
:
9
,
tx_count
:
9
,
};
};
export
const
ZKEVM_L2_TXN_BATCH
:
ZkEvmL2TxnBatch
=
{
acc_input_hash
:
'
0xb815fe2832977f1324ad0124a019b938f189f7b470292f40a21284f15774b3b3
'
,
global_exit_root
:
'
0x0000000000000000000000000000000000000000000000000000000000000000
'
,
number
:
1
,
sequence_tx_hash
:
'
0x57b9b95db5f94f125710bdc8fbb3fabaac10125b44b0cb61dbc69daddf06d0cd
'
,
state_root
:
'
0xb9a589d6b3ae44d3b250a9993caa5e3721568197f56e4743989ecb2285d80ec4
'
,
status
:
'
Finalized
'
,
timestamp
:
'
2023-09-15T06:22:48.000000Z
'
,
transactions
:
[
'
0xff99dd67646b8f3d657cc6f19eb33abc346de2dbaccd03e45e7726cc28e3e186
'
],
verify_tx_hash
:
'
0x093276fa65c67d7b12dd96f4fefafba9d9ad2f1c23c6e53f96583971ce75352d
'
,
};
types/api/transaction.ts
View file @
7ad5a392
...
@@ -65,6 +65,11 @@ export type Transaction = {
...
@@ -65,6 +65,11 @@ export type Transaction = {
validator_address
:
AddressParam
;
validator_address
:
AddressParam
;
validator_fee
:
string
;
validator_fee
:
string
;
};
};
// zkEvm fields
zkevm_verify_hash
?:
string
;
zkevm_batch_number
?:
number
;
zkevm_status
?:
string
;
zkevm_sequence_hash
?:
string
;
}
}
export
type
TransactionsResponse
=
TransactionsResponseValidated
|
TransactionsResponsePending
;
export
type
TransactionsResponse
=
TransactionsResponseValidated
|
TransactionsResponsePending
;
...
...
types/api/zkEvml2TxnBatches.ts
View file @
7ad5a392
export
type
ZkEvmL2TxnBatchesItem
=
{
export
type
ZkEvmL2TxnBatchesItem
=
{
number
:
number
;
number
:
number
;
verify_tx_hash
:
string
;
verify_tx_hash
:
string
|
null
;
sequence_tx_hash
:
string
;
sequence_tx_hash
:
string
|
null
;
status
:
string
;
status
:
string
;
timestamp
:
string
;
timestamp
:
string
;
tx_count
:
number
;
tx_count
:
number
;
...
@@ -14,3 +14,15 @@ export type ZkEvmL2TxnBatchesResponse = {
...
@@ -14,3 +14,15 @@ export type ZkEvmL2TxnBatchesResponse = {
items_count
:
number
;
items_count
:
number
;
}
|
null
;
}
|
null
;
}
}
export
type
ZkEvmL2TxnBatch
=
{
acc_input_hash
:
string
;
global_exit_root
:
string
;
number
:
number
;
sequence_tx_hash
:
string
;
state_root
:
string
;
status
:
string
;
timestamp
:
string
;
transactions
:
Array
<
string
>
;
verify_tx_hash
:
string
;
}
ui/home/LatestZkevmBatches.pw.tsx
0 → 100644
View file @
7ad5a392
import
{
test
as
base
,
expect
}
from
'
@playwright/experimental-ct-react
'
;
import
React
from
'
react
'
;
import
*
as
blockMock
from
'
mocks/blocks/block
'
;
import
*
as
statsMock
from
'
mocks/stats/index
'
;
import
contextWithEnvs
from
'
playwright/fixtures/contextWithEnvs
'
;
import
*
as
socketServer
from
'
playwright/fixtures/socketServer
'
;
import
TestApp
from
'
playwright/TestApp
'
;
import
buildApiUrl
from
'
playwright/utils/buildApiUrl
'
;
import
*
as
configs
from
'
playwright/utils/configs
'
;
import
LatestBlocks
from
'
./LatestBlocks
'
;
const
STATS_API_URL
=
buildApiUrl
(
'
homepage_stats
'
);
const
BLOCKS_API_URL
=
buildApiUrl
(
'
homepage_blocks
'
);
export
const
test
=
base
.
extend
<
socketServer
.
SocketServerFixture
>
({
createSocket
:
socketServer
.
createSocket
,
});
test
(
'
default view +@mobile +@dark-mode
'
,
async
({
mount
,
page
})
=>
{
await
page
.
route
(
STATS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
(
statsMock
.
base
),
}));
await
page
.
route
(
BLOCKS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
([
blockMock
.
base
,
blockMock
.
base2
,
]),
}));
const
component
=
await
mount
(
<
TestApp
>
<
LatestBlocks
/>
</
TestApp
>,
);
await
expect
(
component
).
toHaveScreenshot
();
});
const
testL2
=
test
.
extend
({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context
:
contextWithEnvs
(
configs
.
featureEnvs
.
rollup
)
as
any
,
});
testL2
(
'
L2 view
'
,
async
({
mount
,
page
})
=>
{
await
page
.
route
(
STATS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
(
statsMock
.
base
),
}));
await
page
.
route
(
BLOCKS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
([
blockMock
.
base
,
blockMock
.
base2
,
]),
}));
const
component
=
await
mount
(
<
TestApp
>
<
LatestBlocks
/>
</
TestApp
>,
);
await
expect
(
component
).
toHaveScreenshot
();
});
const
testNoReward
=
test
.
extend
({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context
:
contextWithEnvs
(
configs
.
viewsEnvs
.
block
.
hiddenFields
)
as
any
,
});
testNoReward
(
'
no reward view
'
,
async
({
mount
,
page
})
=>
{
await
page
.
route
(
STATS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
(
statsMock
.
base
),
}));
await
page
.
route
(
BLOCKS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
([
blockMock
.
base
,
blockMock
.
base2
,
]),
}));
const
component
=
await
mount
(
<
TestApp
>
<
LatestBlocks
/>
</
TestApp
>,
);
await
expect
(
component
).
toHaveScreenshot
();
});
test
(
'
with long block height
'
,
async
({
mount
,
page
})
=>
{
await
page
.
route
(
STATS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
(
statsMock
.
base
),
}));
await
page
.
route
(
BLOCKS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
([
{
...
blockMock
.
base
,
height
:
123456789012345
,
},
]),
}));
const
component
=
await
mount
(
<
TestApp
>
<
LatestBlocks
/>
</
TestApp
>,
);
await
expect
(
component
).
toHaveScreenshot
();
});
test
.
describe
(
'
socket
'
,
()
=>
{
test
.
describe
.
configure
({
mode
:
'
serial
'
});
test
(
'
new item
'
,
async
({
mount
,
page
,
createSocket
})
=>
{
await
page
.
route
(
STATS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
(
statsMock
.
base
),
}));
await
page
.
route
(
BLOCKS_API_URL
,
(
route
)
=>
route
.
fulfill
({
status
:
200
,
body
:
JSON
.
stringify
([
blockMock
.
base
,
blockMock
.
base2
,
]),
}));
const
component
=
await
mount
(
<
TestApp
withSocket
>
<
LatestBlocks
/>
</
TestApp
>,
);
const
socket
=
await
createSocket
();
const
channel
=
await
socketServer
.
joinChannel
(
socket
,
'
blocks:new_block
'
);
socketServer
.
sendMessage
(
socket
,
channel
,
'
new_block
'
,
{
average_block_time
:
'
6212.0
'
,
block
:
{
...
blockMock
.
base
,
height
:
blockMock
.
base
.
height
+
1
,
timestamp
:
'
2022-11-11T11:59:58Z
'
,
},
});
await
expect
(
component
).
toHaveScreenshot
();
});
});
ui/home/LatestZkevmBatches.tsx
0 → 100644
View file @
7ad5a392
import
{
Box
,
Heading
,
Flex
,
Text
,
VStack
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
{
useQueryClient
}
from
'
@tanstack/react-query
'
;
import
{
AnimatePresence
}
from
'
framer-motion
'
;
import
React
from
'
react
'
;
import
type
{
SocketMessage
}
from
'
lib/socket/types
'
;
import
type
{
Block
}
from
'
types/api/block
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
config
from
'
configs/app
'
;
import
useApiQuery
,
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
{
nbsp
}
from
'
lib/html-entities
'
;
import
useSocketChannel
from
'
lib/socket/useSocketChannel
'
;
import
useSocketMessage
from
'
lib/socket/useSocketMessage
'
;
import
{
BLOCK
}
from
'
stubs/block
'
;
import
{
HOMEPAGE_STATS
}
from
'
stubs/stats
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
import
LatestBlocksItem
from
'
./LatestBlocksItem
'
;
const
LatestBlocks
=
()
=>
{
const
isMobile
=
useIsMobile
();
// const blocksMaxCount = isMobile ? 2 : 3;
let
blocksMaxCount
:
number
;
if
(
config
.
features
.
rollup
.
isEnabled
||
config
.
UI
.
views
.
block
.
hiddenFields
?.
total_reward
)
{
blocksMaxCount
=
isMobile
?
4
:
5
;
}
else
{
blocksMaxCount
=
isMobile
?
2
:
3
;
}
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
homepage_blocks
'
,
{
queryOptions
:
{
placeholderData
:
Array
(
blocksMaxCount
).
fill
(
BLOCK
),
},
});
const
queryClient
=
useQueryClient
();
const
statsQueryResult
=
useApiQuery
(
'
homepage_stats
'
,
{
queryOptions
:
{
placeholderData
:
HOMEPAGE_STATS
,
},
});
const
handleNewBlockMessage
:
SocketMessage
.
NewBlock
[
'
handler
'
]
=
React
.
useCallback
((
payload
)
=>
{
queryClient
.
setQueryData
(
getResourceKey
(
'
homepage_blocks
'
),
(
prevData
:
Array
<
Block
>
|
undefined
)
=>
{
const
newData
=
prevData
?
[
...
prevData
]
:
[];
if
(
newData
.
some
((
block
=>
block
.
height
===
payload
.
block
.
height
)))
{
return
newData
;
}
return
[
payload
.
block
,
...
newData
].
sort
((
b1
,
b2
)
=>
b2
.
height
-
b1
.
height
).
slice
(
0
,
blocksMaxCount
);
});
},
[
queryClient
,
blocksMaxCount
]);
const
channel
=
useSocketChannel
({
topic
:
'
blocks:new_block
'
,
isDisabled
:
isPlaceholderData
||
isError
,
});
useSocketMessage
({
channel
,
event
:
'
new_block
'
,
handler
:
handleNewBlockMessage
,
});
let
content
;
if
(
isError
)
{
content
=
<
Text
>
No data. Please reload page.
</
Text
>;
}
if
(
data
)
{
const
dataToShow
=
data
.
slice
(
0
,
blocksMaxCount
);
content
=
(
<>
{
statsQueryResult
.
data
?.
network_utilization_percentage
!==
undefined
&&
(
<
Skeleton
isLoaded=
{
!
statsQueryResult
.
isPlaceholderData
}
mb=
{
{
base
:
6
,
lg
:
3
}
}
display=
"inline-block"
>
<
Text
as=
"span"
fontSize=
"sm"
>
Network utilization:
{
nbsp
}
</
Text
>
<
Text
as=
"span"
fontSize=
"sm"
color=
"blue.400"
fontWeight=
{
700
}
>
{
statsQueryResult
.
data
?.
network_utilization_percentage
.
toFixed
(
2
)
}
%
</
Text
>
</
Skeleton
>
)
}
<
VStack
spacing=
{
3
}
mb=
{
4
}
overflow=
"hidden"
alignItems=
"stretch"
>
<
AnimatePresence
initial=
{
false
}
>
{
dataToShow
.
map
(((
block
,
index
)
=>
(
<
LatestBlocksItem
key=
{
block
.
height
+
(
isPlaceholderData
?
String
(
index
)
:
''
)
}
block=
{
block
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
AnimatePresence
>
</
VStack
>
<
Flex
justifyContent=
"center"
>
<
LinkInternal
fontSize=
"sm"
href=
{
route
({
pathname
:
'
/blocks
'
})
}
>
View all blocks
</
LinkInternal
>
</
Flex
>
</>
);
}
return
(
<
Box
width=
{
{
base
:
'
100%
'
,
lg
:
'
280px
'
}
}
flexShrink=
{
0
}
>
<
Heading
as=
"h4"
size=
"sm"
mb=
{
4
}
>
Latest blocks
</
Heading
>
{
content
}
</
Box
>
);
};
export
default
LatestBlocks
;
ui/home/Stats.tsx
View file @
7ad5a392
...
@@ -10,6 +10,7 @@ import clockIcon from 'icons/clock-light.svg';
...
@@ -10,6 +10,7 @@ import clockIcon from 'icons/clock-light.svg';
import
bitcoinIcon
from
'
icons/coins/bitcoin.svg
'
;
import
bitcoinIcon
from
'
icons/coins/bitcoin.svg
'
;
import
gasIcon
from
'
icons/gas.svg
'
;
import
gasIcon
from
'
icons/gas.svg
'
;
import
txIcon
from
'
icons/transactions.svg
'
;
import
txIcon
from
'
icons/transactions.svg
'
;
import
batchesIcon
from
'
icons/txn_batches.svg
'
;
import
walletIcon
from
'
icons/wallet.svg
'
;
import
walletIcon
from
'
icons/wallet.svg
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
WEI
}
from
'
lib/consts
'
;
import
{
WEI
}
from
'
lib/consts
'
;
...
@@ -28,7 +29,14 @@ const Stats = () => {
...
@@ -28,7 +29,14 @@ const Stats = () => {
},
},
});
});
if
(
isError
)
{
const
zkEvmLatestBatchQuery
=
useApiQuery
(
'
homepage_zkevm_latest_batch
'
,
{
queryOptions
:
{
placeholderData
:
12345
,
enabled
:
config
.
features
.
zkEvmRollup
.
isEnabled
,
},
});
if
(
isError
||
zkEvmLatestBatchQuery
.
isError
)
{
return
null
;
return
null
;
}
}
...
@@ -48,13 +56,23 @@ const Stats = () => {
...
@@ -48,13 +56,23 @@ const Stats = () => {
content
=
(
content
=
(
<>
<>
<
StatsItem
{
config
.
features
.
zkEvmRollup
.
isEnabled
?
(
icon=
{
blockIcon
}
<
StatsItem
title=
"Total blocks"
icon=
{
batchesIcon
}
value=
{
Number
(
data
.
total_blocks
).
toLocaleString
()
}
title=
"Latest batch "
url=
{
route
({
pathname
:
'
/blocks
'
})
}
value=
{
(
zkEvmLatestBatchQuery
.
data
||
0
).
toLocaleString
()
}
isLoading=
{
isPlaceholderData
}
url=
{
route
({
pathname
:
'
/zkevm-l2-txn-batches
'
})
}
/>
isLoading=
{
zkEvmLatestBatchQuery
.
isPlaceholderData
}
/>
)
:
(
<
StatsItem
icon=
{
blockIcon
}
title=
"Total blocks"
value=
{
Number
(
data
.
total_blocks
).
toLocaleString
()
}
url=
{
route
({
pathname
:
'
/blocks
'
})
}
isLoading=
{
isPlaceholderData
}
/>
)
}
{
hasAvgBlockTime
&&
(
{
hasAvgBlockTime
&&
(
<
StatsItem
<
StatsItem
icon=
{
clockIcon
}
icon=
{
clockIcon
}
...
...
ui/pages/ZkEvmL2TxnBatch.tsx
0 → 100644
View file @
7ad5a392
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
// import type { PaginationParams } from 'ui/shared/pagination/types';
// import type { RoutedTab } from 'ui/shared/Tabs/types';
// import config from 'configs/app';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/contexts/app
'
;
// import useIsMobile from 'lib/hooks/useIsMobile';
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
ZKEVM_L2_TXN_BATCH
}
from
'
stubs/zkEvmL2
'
;
// import { TX } from 'stubs/tx';
// import { generateListStub } from 'stubs/utils';
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
ZkEvmL2TxnBatchDetails
from
'
ui/zkEvmL2TxnBatches/ZkEvmL2TxnBatchDetails
'
;
// import Pagination from 'ui/shared/pagination/Pagination';
// import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
// import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
// import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
// import TxsContent from 'ui/txs/TxsContent';
// const TAB_LIST_PROPS = {
// marginBottom: 0,
// py: 5,
// marginTop: -5,
// };
const
ZkEvmL2TxnBatch
=
()
=>
{
const
router
=
useRouter
();
// const isMobile = useIsMobile();
const
appProps
=
useAppContext
();
const
number
=
getQueryParamString
(
router
.
query
.
number
);
// const tab = getQueryParamString(router.query.tab);
const
batchQuery
=
useApiQuery
(
'
zkevm_l2_txn_batch
'
,
{
pathParams
:
{
number
},
queryOptions
:
{
enabled
:
Boolean
(
number
),
placeholderData
:
ZKEVM_L2_TXN_BATCH
,
},
});
// const blockTxsQuery = useQueryWithPages({
// resourceName: 'batch_txs',
// pathParams: { height_or_hash: heightOrHash },
// options: {
// enabled: Boolean(!blockQuery.isPlaceholderData && blockQuery.data?.height && tab === 'txs'),
// placeholderData: generateListStub<'block_txs'>(TX, 50, { next_page_params: {
// block_number: 9004925,
// index: 49,
// items_count: 50,
// } }),
// },
// });
if
(
!
number
)
{
throw
new
Error
(
'
Tx batch not found
'
,
{
cause
:
{
status
:
404
}
});
}
if
(
batchQuery
.
isError
)
{
throw
new
Error
(
undefined
,
{
cause
:
batchQuery
.
error
});
}
// const tabs: Array<RoutedTab> = React.useMemo(() => ([
// { id: 'index', title: 'Details', component: <BlockDetails query={ blockQuery }/> },
// { id: 'txs', title: 'Transactions', component: <TxsContent query={ blockTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> },
// ].filter(Boolean)), [ blockQuery, blockTxsQuery, blockWithdrawalsQuery ]);
// const hasPagination = !isMobile && (
// (tab === 'txs' && blockTxsQuery.pagination.isVisible) ||
// (tab === 'withdrawals' && blockWithdrawalsQuery.pagination.isVisible)
// );
// let pagination;
// if (tab === 'txs') {
// pagination = blockTxsQuery.pagination;
// } else if (tab === 'withdrawals') {
// pagination = blockWithdrawalsQuery.pagination;
// }
const
backLink
=
React
.
useMemo
(()
=>
{
const
hasGoBackLink
=
appProps
.
referrer
&&
appProps
.
referrer
.
includes
(
'
/zkevm_l2_txn_batches
'
);
if
(
!
hasGoBackLink
)
{
return
;
}
return
{
label
:
'
Back to tx batches list
'
,
url
:
appProps
.
referrer
,
};
},
[
appProps
.
referrer
]);
return
(
<>
<
TextAd
mb=
{
6
}
/>
<
PageTitle
title=
{
`Tx batch #${ number }`
}
backLink=
{
backLink
}
/>
{
/* { batchQuery.isPlaceholderData ? <TabsSkeleton tabs={ tabs }/> : (
<RoutedTabs
tabs={ tabs }
tabListProps={ isMobile ? undefined : TAB_LIST_PROPS }
rightSlot={ hasPagination ? <Pagination { ...(pagination as PaginationParams) }/> : null }
stickyEnabled={ hasPagination }
/>
) } */
}
<
ZkEvmL2TxnBatchDetails
query=
{
batchQuery
}
/>
</>
);
};
export
default
ZkEvmL2TxnBatch
;
ui/shared/DetailsInfoItem.tsx
View file @
7ad5a392
...
@@ -6,7 +6,7 @@ import Hint from 'ui/shared/Hint';
...
@@ -6,7 +6,7 @@ import Hint from 'ui/shared/Hint';
interface
Props
extends
Omit
<
HTMLChakraProps
<
'
div
'
>
,
'
title
'
>
{
interface
Props
extends
Omit
<
HTMLChakraProps
<
'
div
'
>
,
'
title
'
>
{
title
:
React
.
ReactNode
;
title
:
React
.
ReactNode
;
hint
:
string
;
hint
?
:
string
;
children
:
React
.
ReactNode
;
children
:
React
.
ReactNode
;
note
?:
string
;
note
?:
string
;
isLoading
?:
boolean
;
isLoading
?:
boolean
;
...
@@ -17,7 +17,7 @@ const DetailsInfoItem = ({ title, hint, note, children, id, isLoading, ...styles
...
@@ -17,7 +17,7 @@ const DetailsInfoItem = ({ title, hint, note, children, id, isLoading, ...styles
<>
<>
<
GridItem
py=
{
{
base
:
1
,
lg
:
2
}
}
id=
{
id
}
lineHeight=
{
5
}
{
...
styles
}
_notFirst=
{
{
mt
:
{
base
:
3
,
lg
:
0
}
}
}
>
<
GridItem
py=
{
{
base
:
1
,
lg
:
2
}
}
id=
{
id
}
lineHeight=
{
5
}
{
...
styles
}
_notFirst=
{
{
mt
:
{
base
:
3
,
lg
:
0
}
}
}
>
<
Flex
columnGap=
{
2
}
alignItems=
"flex-start"
>
<
Flex
columnGap=
{
2
}
alignItems=
"flex-start"
>
<
Hint
label=
{
hint
}
isLoading=
{
isLoading
}
/>
{
hint
&&
<
Hint
label=
{
hint
}
isLoading=
{
isLoading
}
/>
}
<
Skeleton
isLoaded=
{
!
isLoading
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
>
<
Text
fontWeight=
{
{
base
:
700
,
lg
:
500
}
}
>
<
Text
fontWeight=
{
{
base
:
700
,
lg
:
500
}
}
>
{
title
}
{
title
}
...
...
ui/tx/TxDetails.tsx
View file @
7ad5a392
...
@@ -38,6 +38,7 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
...
@@ -38,6 +38,7 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
import
DetailsSponsoredItem
from
'
ui/shared/DetailsSponsoredItem
'
;
import
DetailsSponsoredItem
from
'
ui/shared/DetailsSponsoredItem
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
BlockEntity
from
'
ui/shared/entities/block/BlockEntity
'
;
import
BlockEntity
from
'
ui/shared/entities/block/BlockEntity
'
;
import
BlockEntityL2
from
'
ui/shared/entities/block/BlockEntityL2
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
LogDecodedInputData
from
'
ui/shared/logs/LogDecodedInputData
'
;
import
LogDecodedInputData
from
'
ui/shared/logs/LogDecodedInputData
'
;
import
RawInputData
from
'
ui/shared/RawInputData
'
;
import
RawInputData
from
'
ui/shared/RawInputData
'
;
...
@@ -152,6 +153,15 @@ const TxDetails = () => {
...
@@ -152,6 +153,15 @@ const TxDetails = () => {
</
Tag
>
</
Tag
>
)
}
)
}
</
DetailsInfoItem
>
</
DetailsInfoItem
>
{
data
.
zkevm_status
&&
(
<
DetailsInfoItem
title=
"ZkEVM status"
// hint="Current transaction state: Success, Failed (Error), or Pending (In Process)"
isLoading=
{
isPlaceholderData
}
>
{
data
.
zkevm_status
}
</
DetailsInfoItem
>
)
}
{
data
.
revert_reason
&&
(
{
data
.
revert_reason
&&
(
<
DetailsInfoItem
<
DetailsInfoItem
title=
"Revert reason"
title=
"Revert reason"
...
@@ -182,6 +192,19 @@ const TxDetails = () => {
...
@@ -182,6 +192,19 @@ const TxDetails = () => {
</>
</>
)
}
)
}
</
DetailsInfoItem
>
</
DetailsInfoItem
>
{
data
.
zkevm_batch_number
&&
(
<
DetailsInfoItem
title=
"Tx batch"
// hint="Block number containing the transaction"
isLoading=
{
isPlaceholderData
}
>
<
BlockEntityL2
isLoading=
{
isPlaceholderData
}
number=
{
data
.
zkevm_batch_number
}
href=
{
route
({
pathname
:
'
/zkevm-l2-txn-batch/[number]
'
,
query
:
{
number
:
data
.
zkevm_batch_number
.
toString
()
}
})
}
/>
</
DetailsInfoItem
>
)
}
{
data
.
timestamp
&&
(
{
data
.
timestamp
&&
(
<
DetailsInfoItem
<
DetailsInfoItem
title=
"Timestamp"
title=
"Timestamp"
...
@@ -286,6 +309,27 @@ const TxDetails = () => {
...
@@ -286,6 +309,27 @@ const TxDetails = () => {
<
DetailsInfoItemDivider
/>
<
DetailsInfoItemDivider
/>
{
data
.
zkevm_batch_number
&&
(
<
DetailsInfoItem
title=
"Sequence tx hash"
// hint="Value sent in the native token (and USD) if applicable"
isLoading=
{
isPlaceholderData
}
>
{
data
.
zkevm_sequence_hash
}
</
DetailsInfoItem
>
)
}
{
data
.
zkevm_verify_hash
&&
(
<
DetailsInfoItem
title=
"Verify tx hash"
// hint="Value sent in the native token (and USD) if applicable"
isLoading=
{
isPlaceholderData
}
>
{
data
.
zkevm_verify_hash
}
</
DetailsInfoItem
>
)
}
{
(
data
.
zkevm_batch_number
||
data
.
zkevm_verify_hash
)
&&
<
DetailsInfoItemDivider
/>
}
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
value
&&
(
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
value
&&
(
<
DetailsInfoItem
<
DetailsInfoItem
title=
"Value"
title=
"Value"
...
...
ui/zkEvmL2TxnBatches/ZkEvmL2TxnBatchDetails.tsx
0 → 100644
View file @
7ad5a392
import
{
Grid
,
GridItem
,
Text
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
ZkEvmL2TxnBatch
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
clockIcon
from
'
icons/clock.svg
'
;
import
type
{
ResourceError
}
from
'
lib/api/resources
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
Icon
from
'
ui/shared/chakra/Icon
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
DetailsInfoItem
from
'
ui/shared/DetailsInfoItem
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
PrevNext
from
'
ui/shared/PrevNext
'
;
import
TextSeparator
from
'
ui/shared/TextSeparator
'
;
interface
Props
{
query
:
UseQueryResult
<
ZkEvmL2TxnBatch
,
ResourceError
>
;
}
const
ZkEvmL2TxnBatchDetails
=
({
query
}:
Props
)
=>
{
const
router
=
useRouter
();
const
{
data
,
isPlaceholderData
,
isError
,
error
}
=
query
;
const
handlePrevNextClick
=
React
.
useCallback
((
direction
:
'
prev
'
|
'
next
'
)
=>
{
if
(
!
data
)
{
return
;
}
const
increment
=
direction
===
'
next
'
?
+
1
:
-
1
;
const
nextId
=
String
(
data
.
number
+
increment
);
router
.
push
({
pathname
:
'
/zkevm-l2-txn-batch/[number]
'
,
query
:
{
number
:
nextId
}
},
undefined
);
},
[
data
,
router
]);
if
(
isError
)
{
if
(
error
?.
status
===
404
)
{
throw
Error
(
'
Tx Batch not found
'
,
{
cause
:
error
as
unknown
as
Error
});
}
if
(
error
?.
status
===
422
)
{
throw
Error
(
'
Invalid tx batch number
'
,
{
cause
:
error
as
unknown
as
Error
});
}
return
<
DataFetchAlert
/>;
}
if
(
!
data
)
{
return
null
;
}
const
sectionGap
=
(
<
GridItem
colSpan=
{
{
base
:
undefined
,
lg
:
2
}
}
mt=
{
{
base
:
2
,
lg
:
3
}
}
mb=
{
{
base
:
0
,
lg
:
3
}
}
borderBottom=
"1px solid"
borderColor=
"divider"
/>
);
return
(
<
Grid
columnGap=
{
8
}
rowGap=
{
{
base
:
3
,
lg
:
3
}
}
templateColumns=
{
{
base
:
'
minmax(0, 1fr)
'
,
lg
:
'
minmax(min-content, 200px) minmax(0, 1fr)
'
}
}
overflow=
"hidden"
>
<
DetailsInfoItem
title=
"Tx batch number"
// hint="The block height of a particular block is defined as the number of blocks preceding it in the blockchain"
isLoading=
{
isPlaceholderData
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
{
data
.
number
}
</
Skeleton
>
<
PrevNext
ml=
{
6
}
onClick=
{
handlePrevNextClick
}
prevLabel=
"View previous tx batch"
nextLabel=
"View next tx batch"
isPrevDisabled=
{
data
.
number
===
0
}
isLoading=
{
isPlaceholderData
}
/>
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"Status"
// hint="Size of the block in bytes"
isLoading=
{
isPlaceholderData
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
{
data
.
status
}
</
Skeleton
>
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"Verify timestamp"
// hint="Date & time at which block was produced."
isLoading=
{
isPlaceholderData
}
>
<
Icon
as=
{
clockIcon
}
boxSize=
{
5
}
color=
"gray.500"
isLoading=
{
isPlaceholderData
}
/>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
ml=
{
1
}
>
{
dayjs
(
data
.
timestamp
).
fromNow
()
}
</
Skeleton
>
<
TextSeparator
/>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
whiteSpace=
"normal"
>
{
dayjs
(
data
.
timestamp
).
format
(
'
llll
'
)
}
</
Skeleton
>
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"Verify tx hash"
// hint="Date & time at which block was produced."
isLoading=
{
isPlaceholderData
}
>
{
data
.
verify_tx_hash
?
(
<
TxEntityL1
isLoading=
{
isPlaceholderData
}
hash=
{
data
.
verify_tx_hash
}
maxW=
"100%"
/>
)
:
<
Text
>
pending
</
Text
>
}
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"Transactions"
hint=
"The number of transactions in the batch"
isLoading=
{
isPlaceholderData
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
{
/* <LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: heightOrHash, tab: 'txs' } }) }> */
}
{
data
.
transactions
.
length
}
transaction
{
data
.
transactions
.
length
===
1
?
''
:
'
s
'
}
{
/* </LinkInternal> */
}
</
Skeleton
>
</
DetailsInfoItem
>
{
sectionGap
}
<
DetailsInfoItem
title=
"Global exit root"
// hint=''
isLoading=
{
isPlaceholderData
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
{
data
.
global_exit_root
}
</
Skeleton
>
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"Acc input hash"
// hint=''
isLoading=
{
isPlaceholderData
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
{
data
.
acc_input_hash
}
</
Skeleton
>
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"Sequence tx hash"
// hint=''
isLoading=
{
isPlaceholderData
}
>
{
data
.
sequence_tx_hash
?
(
<
TxEntityL1
isLoading=
{
isPlaceholderData
}
hash=
{
data
.
sequence_tx_hash
}
maxW=
"100%"
/>
)
:
<
Text
>
pending
</
Text
>
}
{
/* Not sertain how to display pending state */
}
</
DetailsInfoItem
>
<
DetailsInfoItem
title=
"State root"
// hint=''
isLoading=
{
isPlaceholderData
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
{
data
.
state_root
}
</
Skeleton
>
</
DetailsInfoItem
>
</
Grid
>
);
};
export
default
ZkEvmL2TxnBatchDetails
;
ui/zkEvmL2TxnBatches/ZkEvmTxnBatchesListItem.tsx
View file @
7ad5a392
...
@@ -3,7 +3,7 @@ import React from 'react';
...
@@ -3,7 +3,7 @@ import React from 'react';
import
type
{
ZkEvmL2TxnBatchesItem
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
type
{
ZkEvmL2TxnBatchesItem
}
from
'
types/api/zkEvml2TxnBatches
'
;
//
import { route } from 'nextjs-routes';
import
{
route
}
from
'
nextjs-routes
'
;
import
config
from
'
configs/app
'
;
import
config
from
'
configs/app
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
...
@@ -34,8 +34,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => {
...
@@ -34,8 +34,7 @@ const ZkEvmTxnBatchesListItem = ({ item, isLoading }: Props) => {
fontSize=
"sm"
fontSize=
"sm"
lineHeight=
{
5
}
lineHeight=
{
5
}
fontWeight=
{
600
}
fontWeight=
{
600
}
// fix after implementing batch page
href=
{
route
({
pathname
:
'
/zkevm-l2-txn-batch/[number]
'
,
query
:
{
number
:
item
.
number
.
toString
()
}
})
}
href=
"#"
/>
/>
</
ListItemMobileGrid
.
Value
>
</
ListItemMobileGrid
.
Value
>
...
...
ui/zkEvmL2TxnBatches/ZkEvmTxnBatchesTableItem.tsx
View file @
7ad5a392
...
@@ -3,7 +3,7 @@ import React from 'react';
...
@@ -3,7 +3,7 @@ import React from 'react';
import
type
{
ZkEvmL2TxnBatchesItem
}
from
'
types/api/zkEvml2TxnBatches
'
;
import
type
{
ZkEvmL2TxnBatchesItem
}
from
'
types/api/zkEvml2TxnBatches
'
;
//
import { route } from 'nextjs-routes';
import
{
route
}
from
'
nextjs-routes
'
;
import
config
from
'
configs/app
'
;
import
config
from
'
configs/app
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
...
@@ -31,6 +31,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
...
@@ -31,6 +31,7 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
fontSize=
"sm"
fontSize=
"sm"
lineHeight=
{
5
}
lineHeight=
{
5
}
fontWeight=
{
600
}
fontWeight=
{
600
}
href=
{
route
({
pathname
:
'
/zkevm-l2-txn-batch/[number]
'
,
query
:
{
number
:
item
.
number
.
toString
()
}
})
}
/>
/>
</
Td
>
</
Td
>
<
Td
>
<
Td
>
...
...
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