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
baf47a66
Commit
baf47a66
authored
Jun 13, 2024
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
arbitrum
parent
f5500773
Changes
39
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
1557 additions
and
33 deletions
+1557
-33
deploy-review.yml
.github/workflows/deploy-review.yml
+1
-0
.env.arbitrum
configs/envs/.env.arbitrum
+39
-0
ENVS.md
docs/ENVS.md
+1
-1
resources.ts
lib/api/resources.ts
+53
-0
getArbitrumVerificationStepStatus.ts
lib/getArbitrumVerificationStepStatus.ts
+25
-0
useNavItems.tsx
lib/hooks/useNavItems.tsx
+1
-1
getServerSideProps.ts
nextjs/getServerSideProps.ts
+7
-3
[number].tsx
pages/batches/[number].tsx
+2
-0
index.tsx
pages/batches/index.tsx
+2
-0
index.tsx
pages/deposits/index.tsx
+4
-0
index.tsx
pages/withdrawals/index.tsx
+4
-0
mockEnvs.ts
playwright/fixtures/mockEnvs.ts
+4
-0
arbitrumL2.ts
stubs/arbitrumL2.ts
+34
-0
arbitrumL2.ts
types/api/arbitrumL2.ts
+86
-0
block.ts
types/api/block.ts
+13
-0
transaction.ts
types/api/transaction.ts
+14
-0
rollup.ts
types/client/rollup.ts
+1
-0
BlockDetails.tsx
ui/block/BlockDetails.tsx
+69
-2
BlocksContent.tsx
ui/blocks/BlocksContent.tsx
+7
-5
ArbitrumL2Messages.tsx
ui/messages/ArbitrumL2Messages.tsx
+102
-0
ArbitrumL2MessagesListItem.tsx
ui/messages/ArbitrumL2MessagesListItem.tsx
+120
-0
ArbitrumL2MessagesTable.tsx
ui/messages/ArbitrumL2MessagesTable.tsx
+46
-0
ArbitrumL2MessagesTableItem.tsx
ui/messages/ArbitrumL2MessagesTableItem.tsx
+105
-0
ArbitrumL2Deposits.tsx
ui/pages/ArbitrumL2Deposits.tsx
+9
-0
ArbitrumL2TxnBatch.tsx
ui/pages/ArbitrumL2TxnBatch.tsx
+136
-0
ArbitrumL2TxnBatches.tsx
ui/pages/ArbitrumL2TxnBatches.tsx
+87
-0
ArbitrumL2Withdrawals.tsx
ui/pages/ArbitrumL2Withdrawals.tsx
+9
-0
Block.tsx
ui/pages/Block.tsx
+7
-7
ZkSyncL2TxnBatch.tsx
ui/pages/ZkSyncL2TxnBatch.tsx
+10
-4
ArbitrumL2MessageStatus.tsx
ui/shared/statusTag/ArbitrumL2MessageStatus.tsx
+29
-0
ArbitrumL2TxnBatchStatus.tsx
ui/shared/statusTag/ArbitrumL2TxnBatchStatus.tsx
+28
-0
StatusTag.tsx
ui/shared/statusTag/StatusTag.tsx
+5
-4
VerificationStep.tsx
ui/shared/verificationSteps/VerificationStep.tsx
+8
-2
VerificationSteps.tsx
ui/shared/verificationSteps/VerificationSteps.tsx
+3
-1
TxInfo.tsx
ui/tx/details/TxInfo.tsx
+82
-3
ArbitrumL2TxnBatchDetails.tsx
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchDetails.tsx
+181
-0
ArbitrumL2TxnBatchesListItem.tsx
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesListItem.tsx
+99
-0
ArbitrumL2TxnBatchesTable.tsx
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesTable.tsx
+43
-0
ArbitrumL2TxnBatchesTableItem.tsx
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesTableItem.tsx
+81
-0
No files found.
.github/workflows/deploy-review.yml
View file @
baf47a66
...
@@ -10,6 +10,7 @@ on:
...
@@ -10,6 +10,7 @@ on:
type
:
choice
type
:
choice
options
:
options
:
-
none
-
none
-
arbitrum
-
base
-
base
-
gnosis
-
gnosis
-
eth
-
eth
...
...
configs/envs/.env.arbitrum
0 → 100644
View file @
baf47a66
# Set of ENVs for Optimism (dev only)
# https://optimism.blockscout.com/
# app configuration
NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_APP_HOST=localhost
NEXT_PUBLIC_APP_PORT=3000
# blockchain parameters
NEXT_PUBLIC_NETWORK_NAME=Arbitrum One Nitro
NEXT_PUBLIC_NETWORK_SHORT_NAME=Arbitrum One Nitro
NEXT_PUBLIC_NETWORK_ID=42161
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
# api configuration
NEXT_PUBLIC_API_HOST=arbitrum.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/
# ui config
## homepage
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
## views
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
# app features
NEXT_PUBLIC_APP_INSTANCE=local
NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_AUTH_URL=http://localhost:3000/login
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
NEXT_PUBLIC_LOGOUT_URL=https://blockscoutcom.us.auth0.com/v2/logout
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
# rollup
NEXT_PUBLIC_ROLLUP_TYPE=arbitrum
NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com
NEXT_PUBLIC_AD_BANNER_PROVIDER=hype
\ No newline at end of file
docs/ENVS.md
View file @
baf47a66
...
@@ -399,7 +399,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
...
@@ -399,7 +399,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| Variable | Type| Description | Compulsoriness | Default value | Example value | Version |
| --- | --- | --- | --- | --- | --- | --- |
| --- | --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_ROLLUP_TYPE |
`'optimistic' \| 'shibarium' \| 'zkEvm' \| 'zkSync' `
| Rollup chain type | Required | - |
`'optimistic'`
| v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_TYPE |
`'optimistic' \| '
arbitrum' \| '
shibarium' \| 'zkEvm' \| 'zkSync' `
| Rollup chain type | Required | - |
`'optimistic'`
| v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_L1_BASE_URL |
`string`
| Blockscout base URL for L1 network | Required | - |
`'http://eth-goerli.blockscout.com'`
| v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_L1_BASE_URL |
`string`
| Blockscout base URL for L1 network | Required | - |
`'http://eth-goerli.blockscout.com'`
| v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL |
`string`
| URL for L2 -> L1 withdrawals | Required only for
`optimistic`
rollups | - |
`https://app.optimism.io/bridge/withdraw`
| v1.24.0+ |
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL |
`string`
| URL for L2 -> L1 withdrawals | Required only for
`optimistic`
rollups | - |
`https://app.optimism.io/bridge/withdraw`
| v1.24.0+ |
| NEXT_PUBLIC_FAULT_PROOF_ENABLED |
`boolean`
| Set to
`true`
for chains with fault proof system enabled (OP stack only) | - | - |
`true`
| v1.31.0+ |
| NEXT_PUBLIC_FAULT_PROOF_ENABLED |
`boolean`
| Set to
`true`
for chains with fault proof system enabled (OP stack only) | - | - |
`true`
| v1.31.0+ |
...
...
lib/api/resources.ts
View file @
baf47a66
...
@@ -32,6 +32,13 @@ import type {
...
@@ -32,6 +32,13 @@ import type {
}
from
'
types/api/address
'
;
}
from
'
types/api/address
'
;
import
type
{
AddressesResponse
}
from
'
types/api/addresses
'
;
import
type
{
AddressesResponse
}
from
'
types/api/addresses
'
;
import
type
{
AddressMetadataInfo
,
PublicTagTypesResponse
}
from
'
types/api/addressMetadata
'
;
import
type
{
AddressMetadataInfo
,
PublicTagTypesResponse
}
from
'
types/api/addressMetadata
'
;
import
type
{
ArbitrumL2MessagesResponse
,
ArbitrumL2TxnBatch
,
ArbitrumL2TxnBatchesResponse
,
ArbitrumL2BatchTxs
,
ArbitrumL2BatchBlocks
,
}
from
'
types/api/arbitrumL2
'
;
import
type
{
TxBlobs
,
Blob
}
from
'
types/api/blobs
'
;
import
type
{
TxBlobs
,
Blob
}
from
'
types/api/blobs
'
;
import
type
{
BlocksResponse
,
BlockTransactionsResponse
,
Block
,
BlockFilters
,
BlockWithdrawalsResponse
}
from
'
types/api/block
'
;
import
type
{
BlocksResponse
,
BlockTransactionsResponse
,
Block
,
BlockFilters
,
BlockWithdrawalsResponse
}
from
'
types/api/block
'
;
import
type
{
ChartMarketResponse
,
ChartSecondaryCoinPriceResponse
,
ChartTransactionResponse
}
from
'
types/api/charts
'
;
import
type
{
ChartMarketResponse
,
ChartSecondaryCoinPriceResponse
,
ChartTransactionResponse
}
from
'
types/api/charts
'
;
...
@@ -660,6 +667,44 @@ export const RESOURCES = {
...
@@ -660,6 +667,44 @@ export const RESOURCES = {
path
:
'
/api/v2/optimism/games/count
'
,
path
:
'
/api/v2/optimism/games/count
'
,
},
},
// arbitrum L2
arbitrum_l2_messages
:
{
path
:
'
/api/v2/arbitrum/messages/:direction
'
,
pathParams
:
[
'
direction
'
as
const
],
filterFields
:
[],
},
arbitrum_l2_messages_count
:
{
path
:
'
/api/v2/arbitrum/messages/:direction/count
'
,
pathParams
:
[
'
direction
'
as
const
],
},
arbitrum_l2_txn_batches
:
{
path
:
'
/api/v2/arbitrum/batches
'
,
filterFields
:
[],
},
arbitrum_l2_txn_batches_count
:
{
path
:
'
/api/v2/arbitrum/batches/count
'
,
},
arbitrum_l2_txn_batch
:
{
path
:
'
/api/v2/arbitrum/batches/:number
'
,
pathParams
:
[
'
number
'
as
const
],
},
arbitrum_l2_txn_batch_txs
:
{
path
:
'
/api/v2/transactions/arbitrum-batch/:number
'
,
pathParams
:
[
'
number
'
as
const
],
filterFields
:
[],
},
arbitrum_l2_txn_batch_blocks
:
{
path
:
'
/api/v2/blocks/arbitrum-batch/:number
'
,
pathParams
:
[
'
number
'
as
const
],
filterFields
:
[],
},
// zkEvm L2
// zkEvm L2
zkevm_l2_deposits
:
{
zkevm_l2_deposits
:
{
path
:
'
/api/v2/zkevm/deposits
'
,
path
:
'
/api/v2/zkevm/deposits
'
,
...
@@ -865,6 +910,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
...
@@ -865,6 +910,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'
optimistic_l2_output_roots
'
|
'
optimistic_l2_withdrawals
'
|
'
optimistic_l2_txn_batches
'
|
'
optimistic_l2_deposits
'
|
'
optimistic_l2_output_roots
'
|
'
optimistic_l2_withdrawals
'
|
'
optimistic_l2_txn_batches
'
|
'
optimistic_l2_deposits
'
|
'
optimistic_l2_dispute_games
'
|
'
optimistic_l2_dispute_games
'
|
'
shibarium_deposits
'
|
'
shibarium_withdrawals
'
|
'
shibarium_deposits
'
|
'
shibarium_withdrawals
'
|
'
arbitrum_l2_messages
'
|
'
arbitrum_l2_txn_batches
'
|
'
arbitrum_l2_txn_batch_txs
'
|
'
arbitrum_l2_txn_batch_blocks
'
|
'
zkevm_l2_deposits
'
|
'
zkevm_l2_withdrawals
'
|
'
zkevm_l2_txn_batches
'
|
'
zkevm_l2_txn_batch_txs
'
|
'
zkevm_l2_deposits
'
|
'
zkevm_l2_withdrawals
'
|
'
zkevm_l2_txn_batches
'
|
'
zkevm_l2_txn_batch_txs
'
|
'
zksync_l2_txn_batches
'
|
'
zksync_l2_txn_batch_txs
'
|
'
zksync_l2_txn_batches
'
|
'
zksync_l2_txn_batch_txs
'
|
'
withdrawals
'
|
'
address_withdrawals
'
|
'
block_withdrawals
'
|
'
withdrawals
'
|
'
address_withdrawals
'
|
'
block_withdrawals
'
|
...
@@ -991,6 +1037,13 @@ Q extends 'shibarium_withdrawals' ? ShibariumWithdrawalsResponse :
...
@@ -991,6 +1037,13 @@ Q extends 'shibarium_withdrawals' ? ShibariumWithdrawalsResponse :
Q
extends
'
shibarium_deposits
'
?
ShibariumDepositsResponse
:
Q
extends
'
shibarium_deposits
'
?
ShibariumDepositsResponse
:
Q
extends
'
shibarium_withdrawals_count
'
?
number
:
Q
extends
'
shibarium_withdrawals_count
'
?
number
:
Q
extends
'
shibarium_deposits_count
'
?
number
:
Q
extends
'
shibarium_deposits_count
'
?
number
:
Q
extends
'
arbitrum_l2_messages
'
?
ArbitrumL2MessagesResponse
:
Q
extends
'
arbitrum_l2_messages_count
'
?
number
:
Q
extends
'
arbitrum_l2_txn_batches
'
?
ArbitrumL2TxnBatchesResponse
:
Q
extends
'
arbitrum_l2_txn_batches_count
'
?
number
:
Q
extends
'
arbitrum_l2_txn_batch
'
?
ArbitrumL2TxnBatch
:
Q
extends
'
arbitrum_l2_txn_batch_txs
'
?
ArbitrumL2BatchTxs
:
Q
extends
'
arbitrum_l2_txn_batch_blocks
'
?
ArbitrumL2BatchBlocks
:
Q
extends
'
zkevm_l2_deposits
'
?
ZkEvmL2DepositsResponse
:
Q
extends
'
zkevm_l2_deposits
'
?
ZkEvmL2DepositsResponse
:
Q
extends
'
zkevm_l2_deposits_count
'
?
number
:
Q
extends
'
zkevm_l2_deposits_count
'
?
number
:
Q
extends
'
zkevm_l2_withdrawals
'
?
ZkEvmL2WithdrawalsResponse
:
Q
extends
'
zkevm_l2_withdrawals
'
?
ZkEvmL2WithdrawalsResponse
:
...
...
lib/getArbitrumVerificationStepStatus.ts
0 → 100644
View file @
baf47a66
import
type
{
ArbitrumBatchStatus
,
ArbitrumL2TxData
}
from
'
types/api/arbitrumL2
'
;
type
Args
=
{
status
:
ArbitrumBatchStatus
;
commitment_transaction
:
ArbitrumL2TxData
;
confirmation_transaction
:
ArbitrumL2TxData
;
}
export
default
function
getArbitrumVerificationStepStatus
({
status
,
commitment_transaction
:
commitTx
,
confirmation_transaction
:
confirmTx
,
}:
Args
)
{
if
(
status
===
'
Sent to base
'
)
{
if
(
commitTx
.
status
===
'
unfinalized
'
)
{
return
'
pending
'
;
}
}
if
(
status
===
'
Confirmed on base
'
)
{
if
(
confirmTx
.
status
===
'
unfinalized
'
)
{
return
'
pending
'
;
}
}
return
'
finalized
'
;
}
lib/hooks/useNavItems.tsx
View file @
baf47a66
...
@@ -105,7 +105,7 @@ export default function useNavItems(): ReturnType {
...
@@ -105,7 +105,7 @@ export default function useNavItems(): ReturnType {
const
rollupFeature
=
config
.
features
.
rollup
;
const
rollupFeature
=
config
.
features
.
rollup
;
if
(
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
optimistic
'
||
rollupFeature
.
type
===
'
zkEvm
'
))
{
if
(
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
optimistic
'
||
rollupFeature
.
type
===
'
arbitrum
'
||
rollupFeature
.
type
===
'
zkEvm
'
))
{
blockchainNavItems
=
[
blockchainNavItems
=
[
[
[
txs
,
txs
,
...
...
nextjs/getServerSideProps.ts
View file @
baf47a66
import
type
{
GetServerSideProps
,
GetServerSidePropsContext
,
GetServerSidePropsResult
}
from
'
next
'
;
import
type
{
GetServerSideProps
,
GetServerSidePropsContext
,
GetServerSidePropsResult
}
from
'
next
'
;
import
type
{
AdBannerProviders
}
from
'
types/client/adProviders
'
;
import
type
{
AdBannerProviders
}
from
'
types/client/adProviders
'
;
import
type
{
RollupType
}
from
'
types/client/rollup
'
;
import
type
{
Route
}
from
'
nextjs-routes
'
;
import
type
{
Route
}
from
'
nextjs-routes
'
;
...
@@ -66,8 +67,9 @@ export const verifiedAddresses: GetServerSideProps<Props> = async(context) => {
...
@@ -66,8 +67,9 @@ export const verifiedAddresses: GetServerSideProps<Props> = async(context) => {
return
account
(
context
);
return
account
(
context
);
};
};
const
DEPOSITS_ROLLUP_TYPES
:
Array
<
RollupType
>
=
[
'
optimistic
'
,
'
shibarium
'
,
'
zkEvm
'
,
'
arbitrum
'
];
export
const
deposits
:
GetServerSideProps
<
Props
>
=
async
(
context
)
=>
{
export
const
deposits
:
GetServerSideProps
<
Props
>
=
async
(
context
)
=>
{
if
(
!
(
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
optimistic
'
||
rollupFeature
.
type
===
'
shibarium
'
||
rollupFeature
.
type
===
'
zkEvm
'
)))
{
if
(
!
(
rollupFeature
.
isEnabled
&&
DEPOSITS_ROLLUP_TYPES
.
includes
(
rollupFeature
.
type
)))
{
return
{
return
{
notFound
:
true
,
notFound
:
true
,
};
};
...
@@ -76,10 +78,11 @@ export const deposits: GetServerSideProps<Props> = async(context) => {
...
@@ -76,10 +78,11 @@ export const deposits: GetServerSideProps<Props> = async(context) => {
return
base
(
context
);
return
base
(
context
);
};
};
const
WITHDRAWALS_ROLLUP_TYPES
:
Array
<
RollupType
>
=
[
'
optimistic
'
,
'
shibarium
'
,
'
zkEvm
'
,
'
arbitrum
'
];
export
const
withdrawals
:
GetServerSideProps
<
Props
>
=
async
(
context
)
=>
{
export
const
withdrawals
:
GetServerSideProps
<
Props
>
=
async
(
context
)
=>
{
if
(
if
(
!
config
.
features
.
beaconChain
.
isEnabled
&&
!
config
.
features
.
beaconChain
.
isEnabled
&&
!
(
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
optimistic
'
||
rollupFeature
.
type
===
'
shibarium
'
||
rollupFeature
.
type
===
'
zkEvm
'
))
!
(
rollupFeature
.
isEnabled
&&
WITHDRAWALS_ROLLUP_TYPES
.
includes
(
rollupFeature
.
type
))
)
{
)
{
return
{
return
{
notFound
:
true
,
notFound
:
true
,
...
@@ -109,8 +112,9 @@ export const optimisticRollup: GetServerSideProps<Props> = async(context) => {
...
@@ -109,8 +112,9 @@ export const optimisticRollup: GetServerSideProps<Props> = async(context) => {
return
base
(
context
);
return
base
(
context
);
};
};
const
BATCH_ROLLUP_TYPES
:
Array
<
RollupType
>
=
[
'
zkEvm
'
,
'
zkSync
'
,
'
arbitrum
'
];
export
const
batch
:
GetServerSideProps
<
Props
>
=
async
(
context
)
=>
{
export
const
batch
:
GetServerSideProps
<
Props
>
=
async
(
context
)
=>
{
if
(
!
(
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
zkEvm
'
||
rollupFeature
.
type
===
'
zkSync
'
)))
{
if
(
!
(
rollupFeature
.
isEnabled
&&
BATCH_ROLLUP_TYPES
.
includes
(
rollupFeature
.
type
)))
{
return
{
return
{
notFound
:
true
,
notFound
:
true
,
};
};
...
...
pages/batches/[number].tsx
View file @
baf47a66
...
@@ -15,6 +15,8 @@ const Batch = dynamic(() => {
...
@@ -15,6 +15,8 @@ const Batch = dynamic(() => {
}
}
switch
(
rollupFeature
.
type
)
{
switch
(
rollupFeature
.
type
)
{
case
'
arbitrum
'
:
return
import
(
'
ui/pages/ArbitrumL2TxnBatch
'
);
case
'
zkEvm
'
:
case
'
zkEvm
'
:
return
import
(
'
ui/pages/ZkEvmL2TxnBatch
'
);
return
import
(
'
ui/pages/ZkEvmL2TxnBatch
'
);
case
'
zkSync
'
:
case
'
zkSync
'
:
...
...
pages/batches/index.tsx
View file @
baf47a66
...
@@ -19,6 +19,8 @@ const Batches = dynamic(() => {
...
@@ -19,6 +19,8 @@ const Batches = dynamic(() => {
return
import
(
'
ui/pages/ZkSyncL2TxnBatches
'
);
return
import
(
'
ui/pages/ZkSyncL2TxnBatches
'
);
case
'
optimistic
'
:
case
'
optimistic
'
:
return
import
(
'
ui/pages/OptimisticL2TxnBatches
'
);
return
import
(
'
ui/pages/OptimisticL2TxnBatches
'
);
case
'
arbitrum
'
:
return
import
(
'
ui/pages/ArbitrumL2TxnBatches
'
);
}
}
throw
new
Error
(
'
Txn batches feature is not enabled.
'
);
throw
new
Error
(
'
Txn batches feature is not enabled.
'
);
},
{
ssr
:
false
});
},
{
ssr
:
false
});
...
...
pages/deposits/index.tsx
View file @
baf47a66
...
@@ -12,6 +12,10 @@ const Deposits = dynamic(() => {
...
@@ -12,6 +12,10 @@ const Deposits = dynamic(() => {
return
import
(
'
ui/pages/OptimisticL2Deposits
'
);
return
import
(
'
ui/pages/OptimisticL2Deposits
'
);
}
}
if
(
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
arbitrum
'
)
{
return
import
(
'
ui/pages/ArbitrumL2Deposits
'
);
}
if
(
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
shibarium
'
)
{
if
(
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
shibarium
'
)
{
return
import
(
'
ui/pages/ShibariumDeposits
'
);
return
import
(
'
ui/pages/ShibariumDeposits
'
);
}
}
...
...
pages/withdrawals/index.tsx
View file @
baf47a66
...
@@ -13,6 +13,10 @@ const Withdrawals = dynamic(() => {
...
@@ -13,6 +13,10 @@ const Withdrawals = dynamic(() => {
return
import
(
'
ui/pages/OptimisticL2Withdrawals
'
);
return
import
(
'
ui/pages/OptimisticL2Withdrawals
'
);
}
}
if
(
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
arbitrum
'
)
{
return
import
(
'
ui/pages/ArbitrumL2Withdrawals
'
);
}
if
(
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
shibarium
'
)
{
if
(
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
shibarium
'
)
{
return
import
(
'
ui/pages/ShibariumWithdrawals
'
);
return
import
(
'
ui/pages/ShibariumWithdrawals
'
);
}
}
...
...
playwright/fixtures/mockEnvs.ts
View file @
baf47a66
...
@@ -22,6 +22,10 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = {
...
@@ -22,6 +22,10 @@ export const ENVS_MAP: Record<string, Array<[string, string]>> = {
[
'
NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL
'
,
'
https://localhost:3102
'
],
[
'
NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL
'
,
'
https://localhost:3102
'
],
[
'
NEXT_PUBLIC_FAULT_PROOF_ENABLED
'
,
'
true
'
],
[
'
NEXT_PUBLIC_FAULT_PROOF_ENABLED
'
,
'
true
'
],
],
],
arbitrumRollup
:
[
[
'
NEXT_PUBLIC_ROLLUP_TYPE
'
,
'
arbitrum
'
],
[
'
NEXT_PUBLIC_ROLLUP_L1_BASE_URL
'
,
'
https://localhost:3101
'
],
],
shibariumRollup
:
[
shibariumRollup
:
[
[
'
NEXT_PUBLIC_ROLLUP_TYPE
'
,
'
shibarium
'
],
[
'
NEXT_PUBLIC_ROLLUP_TYPE
'
,
'
shibarium
'
],
[
'
NEXT_PUBLIC_ROLLUP_L1_BASE_URL
'
,
'
https://localhost:3101
'
],
[
'
NEXT_PUBLIC_ROLLUP_L1_BASE_URL
'
,
'
https://localhost:3101
'
],
...
...
stubs/arbitrumL2.ts
0 → 100644
View file @
baf47a66
import
type
{
ArbitrumL2TxnBatchesItem
,
ArbitrumL2TxnBatch
,
ArbitrumL2MessagesItem
}
from
'
types/api/arbitrumL2
'
;
import
{
ADDRESS_HASH
}
from
'
./addressParams
'
;
import
{
TX_HASH
}
from
'
./tx
'
;
export
const
ARBITRUM_MESSAGES_ITEM
:
ArbitrumL2MessagesItem
=
{
completion_transaction_hash
:
TX_HASH
,
id
:
181920
,
origination_address
:
ADDRESS_HASH
,
origination_transaction_block_number
:
123456
,
origination_transaction_hash
:
TX_HASH
,
origination_timestamp
:
'
2023-06-01T14:46:48.000000Z
'
,
status
:
'
relayed
'
,
};
export
const
ARBITRUM_L2_TXN_BATCHES_ITEM
:
ArbitrumL2TxnBatchesItem
=
{
number
:
12345
,
block_count
:
12345
,
transactions_count
:
10000
,
commitment_transaction
:
{
block_number
:
12345
,
timestamp
:
'
2024-04-17T08:51:58.000000Z
'
,
hash
:
TX_HASH
,
status
:
'
finalized
'
,
},
};
export
const
ARBITRUM_L2_TXN_BATCH
:
ArbitrumL2TxnBatch
=
{
...
ARBITRUM_L2_TXN_BATCHES_ITEM
,
after_acc
:
'
0xcd064f3409015e8e6407e492e5275a185e492c6b43ccf127f22092d8057a9ffb
'
,
before_acc
:
'
0x2ed7c4985eb778d76ec400a43805e7feecc8c2afcdb492dbe5caf227de6d37bc
'
,
start_block
:
1245209
,
end_block
:
1245490
,
};
types/api/arbitrumL2.ts
0 → 100644
View file @
baf47a66
import
type
{
Block
}
from
'
./block
'
;
import
type
{
Transaction
}
from
'
./transaction
'
;
export
type
ArbitrumL2MessagesItem
=
{
completion_transaction_hash
:
string
|
null
;
id
:
number
;
origination_address
:
string
;
origination_timestamp
:
string
|
null
;
origination_transaction_block_number
:
number
;
origination_transaction_hash
:
string
;
status
:
string
;
}
export
type
ArbitrumL2MessagesResponse
=
{
items
:
Array
<
ArbitrumL2MessagesItem
>
;
next_page_params
:
{
direction
:
string
;
id
:
number
;
items_count
:
number
;
};
}
export
type
ArbitrumL2TxData
=
{
hash
:
string
|
null
;
status
:
string
|
null
;
timestamp
:
string
|
null
;
}
type
ArbitrumL2BatchCommitmentTx
=
{
block_number
:
number
;
hash
:
string
;
status
:
string
;
timestamp
:
string
;
}
export
type
ArbitrumL2TxnBatchesItem
=
{
block_count
:
number
;
commitment_transaction
:
ArbitrumL2BatchCommitmentTx
;
number
:
number
;
transactions_count
:
number
;
}
export
type
ArbitrumL2TxnBatchesResponse
=
{
items
:
Array
<
ArbitrumL2TxnBatchesItem
>
;
next_page_params
:
{
number
:
number
;
items_count
:
number
;
}
|
null
;
}
export
type
ArbitrumL2TxnBatch
=
{
after_acc
:
string
;
before_acc
:
string
;
commitment_transaction
:
ArbitrumL2BatchCommitmentTx
;
end_block
:
number
;
start_block
:
number
;
number
:
number
;
transactions_count
:
number
;
}
export
type
ArbitrumL2BatchTxs
=
{
items
:
Array
<
Transaction
>
;
next_page_params
:
{
batch_number
:
string
;
block_number
:
number
;
index
:
number
;
items_count
:
number
;
}
|
null
;
}
export
type
ArbitrumL2BatchBlocks
=
{
items
:
Array
<
Block
>
;
next_page_params
:
{
batch_number
:
string
;
block_number
:
number
;
items_count
:
number
;
}
|
null
;
}
export
const
ARBITRUM_L2_TX_BATCH_STATUSES
=
[
'
Processed on rollup
'
as
const
,
'
Sent to base
'
as
const
,
'
Confirmed on base
'
as
const
,
];
export
type
ArbitrumBatchStatus
=
typeof
ARBITRUM_L2_TX_BATCH_STATUSES
[
number
];
types/api/block.ts
View file @
baf47a66
...
@@ -2,6 +2,7 @@ import type { AddressParam } from 'types/api/addressParams';
...
@@ -2,6 +2,7 @@ import type { AddressParam } from 'types/api/addressParams';
import
type
{
Reward
}
from
'
types/api/reward
'
;
import
type
{
Reward
}
from
'
types/api/reward
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
type
{
ArbitrumBatchStatus
,
ArbitrumL2TxData
}
from
'
./arbitrumL2
'
;
import
type
{
ZkSyncBatchesItem
}
from
'
./zkSyncL2
'
;
import
type
{
ZkSyncBatchesItem
}
from
'
./zkSyncL2
'
;
export
type
BlockType
=
'
block
'
|
'
reorg
'
|
'
uncle
'
;
export
type
BlockType
=
'
block
'
|
'
reorg
'
|
'
uncle
'
;
...
@@ -48,6 +49,18 @@ export interface Block {
...
@@ -48,6 +49,18 @@ export interface Block {
zksync
?:
Omit
<
ZkSyncBatchesItem
,
'
number
'
|
'
tx_count
'
|
'
timestamp
'
>
&
{
zksync
?:
Omit
<
ZkSyncBatchesItem
,
'
number
'
|
'
tx_count
'
|
'
timestamp
'
>
&
{
'
batch_number
'
:
number
|
null
;
'
batch_number
'
:
number
|
null
;
};
};
arbitrum
?:
ArbitrumBlockData
;
}
type
ArbitrumBlockData
=
{
'
batch_number
'
:
number
;
'
commitment_transaction
'
:
ArbitrumL2TxData
;
'
confirmation_transaction
'
:
ArbitrumL2TxData
;
'
delayed_messages
'
:
number
;
'
l1_block_height
'
:
number
;
'
send_count
'
:
number
;
'
send_root
'
:
string
;
'
status
'
:
ArbitrumBatchStatus
;
}
}
export
interface
BlocksResponse
{
export
interface
BlocksResponse
{
...
...
types/api/transaction.ts
View file @
baf47a66
import
type
{
AddressParam
}
from
'
./addressParams
'
;
import
type
{
AddressParam
}
from
'
./addressParams
'
;
import
type
{
ArbitrumBatchStatus
,
ArbitrumL2TxData
}
from
'
./arbitrumL2
'
;
import
type
{
BlockTransactionsResponse
}
from
'
./block
'
;
import
type
{
BlockTransactionsResponse
}
from
'
./block
'
;
import
type
{
DecodedInput
}
from
'
./decodedInput
'
;
import
type
{
DecodedInput
}
from
'
./decodedInput
'
;
import
type
{
Fee
}
from
'
./fee
'
;
import
type
{
Fee
}
from
'
./fee
'
;
...
@@ -93,6 +94,19 @@ export type Transaction = {
...
@@ -93,6 +94,19 @@ export type Transaction = {
max_fee_per_blob_gas
?:
string
;
max_fee_per_blob_gas
?:
string
;
// Noves-fi
// Noves-fi
translation
?:
NovesTxTranslation
;
translation
?:
NovesTxTranslation
;
arbitrum
?:
ArbitrumTransactionData
;
}
type
ArbitrumTransactionData
=
{
batch_number
:
number
;
commitment_transaction
:
ArbitrumL2TxData
;
confirmation_transaction
:
ArbitrumL2TxData
;
contains_message
:
'
incoming
'
|
'
outcoming
'
|
null
;
gas_used_for_l1
:
string
;
gas_used_for_l2
:
string
;
network_fee
:
string
;
poster_fee
:
string
;
status
:
ArbitrumBatchStatus
;
}
}
export
const
ZKEVM_L2_TX_STATUSES
=
[
'
Confirmed by Sequencer
'
,
'
L1 Confirmed
'
];
export
const
ZKEVM_L2_TX_STATUSES
=
[
'
Confirmed by Sequencer
'
,
'
L1 Confirmed
'
];
...
...
types/client/rollup.ts
View file @
baf47a66
...
@@ -2,6 +2,7 @@ import type { ArrayElement } from 'types/utils';
...
@@ -2,6 +2,7 @@ import type { ArrayElement } from 'types/utils';
export
const
ROLLUP_TYPES
=
[
export
const
ROLLUP_TYPES
=
[
'
optimistic
'
,
'
optimistic
'
,
'
arbitrum
'
,
'
shibarium
'
,
'
shibarium
'
,
'
zkEvm
'
,
'
zkEvm
'
,
'
zkSync
'
,
'
zkSync
'
,
...
...
ui/block/BlockDetails.tsx
View file @
baf47a66
...
@@ -5,6 +5,7 @@ import { useRouter } from 'next/router';
...
@@ -5,6 +5,7 @@ import { useRouter } from 'next/router';
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
scroller
,
Element
}
from
'
react-scroll
'
;
import
{
scroller
,
Element
}
from
'
react-scroll
'
;
import
{
ARBITRUM_L2_TX_BATCH_STATUSES
}
from
'
types/api/arbitrumL2
'
;
import
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
from
'
types/api/zkSyncL2
'
;
import
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
from
'
types/api/zkSyncL2
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
{
route
}
from
'
nextjs-routes
'
;
...
@@ -12,6 +13,7 @@ import { route } from 'nextjs-routes';
...
@@ -12,6 +13,7 @@ import { route } from 'nextjs-routes';
import
config
from
'
configs/app
'
;
import
config
from
'
configs/app
'
;
import
getBlockReward
from
'
lib/block/getBlockReward
'
;
import
getBlockReward
from
'
lib/block/getBlockReward
'
;
import
{
GWEI
,
WEI
,
WEI_IN_GWEI
,
ZERO
}
from
'
lib/consts
'
;
import
{
GWEI
,
WEI
,
WEI_IN_GWEI
,
ZERO
}
from
'
lib/consts
'
;
import
getArbitrumVerificationStepStatus
from
'
lib/getArbitrumVerificationStepStatus
'
;
import
{
space
}
from
'
lib/html-entities
'
;
import
{
space
}
from
'
lib/html-entities
'
;
import
getNetworkValidatorTitle
from
'
lib/networks/getNetworkValidatorTitle
'
;
import
getNetworkValidatorTitle
from
'
lib/networks/getNetworkValidatorTitle
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
...
@@ -22,12 +24,14 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
...
@@ -22,12 +24,14 @@ import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
import
DetailsTimestamp
from
'
ui/shared/DetailsTimestamp
'
;
import
DetailsTimestamp
from
'
ui/shared/DetailsTimestamp
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
BatchEntityL2
from
'
ui/shared/entities/block/BatchEntityL2
'
;
import
BatchEntityL2
from
'
ui/shared/entities/block/BatchEntityL2
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
GasUsedToTargetRatio
from
'
ui/shared/GasUsedToTargetRatio
'
;
import
GasUsedToTargetRatio
from
'
ui/shared/GasUsedToTargetRatio
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
PrevNext
from
'
ui/shared/PrevNext
'
;
import
PrevNext
from
'
ui/shared/PrevNext
'
;
import
RawDataSnippet
from
'
ui/shared/RawDataSnippet
'
;
import
RawDataSnippet
from
'
ui/shared/RawDataSnippet
'
;
import
StatusTag
from
'
ui/shared/statusTag/StatusTag
'
;
import
TextSeparator
from
'
ui/shared/TextSeparator
'
;
import
TextSeparator
from
'
ui/shared/TextSeparator
'
;
import
Utilization
from
'
ui/shared/Utilization/Utilization
'
;
import
Utilization
from
'
ui/shared/Utilization/Utilization
'
;
import
VerificationSteps
from
'
ui/shared/verificationSteps/VerificationSteps
'
;
import
VerificationSteps
from
'
ui/shared/verificationSteps/VerificationSteps
'
;
...
@@ -184,6 +188,22 @@ const BlockDetails = ({ query }: Props) => {
...
@@ -184,6 +188,22 @@ const BlockDetails = ({ query }: Props) => {
/>
/>
</
DetailsInfoItem
.
Value
>
</
DetailsInfoItem
.
Value
>
{
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
arbitrum
'
&&
data
.
arbitrum
&&
!
config
.
UI
.
views
.
block
.
hiddenFields
?.
batch
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"Batch number"
isLoading=
{
isPlaceholderData
}
>
Batch
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
{
data
.
arbitrum
.
batch_number
?
<
BatchEntityL2
isLoading=
{
isPlaceholderData
}
number=
{
data
.
arbitrum
.
batch_number
}
/>
:
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
Pending
</
Skeleton
>
}
</
DetailsInfoItem
.
Value
>
</>
)
}
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
hint=
"Size of the block in bytes"
hint=
"Size of the block in bytes"
isLoading=
{
isPlaceholderData
}
isLoading=
{
isPlaceholderData
}
...
@@ -251,7 +271,9 @@ const BlockDetails = ({ query }: Props) => {
...
@@ -251,7 +271,9 @@ const BlockDetails = ({ query }: Props) => {
</
DetailsInfoItem
.
Value
>
</
DetailsInfoItem
.
Value
>
</>
</>
)
}
)
}
{
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
zkSync
'
&&
data
.
zksync
&&
!
config
.
UI
.
views
.
block
.
hiddenFields
?.
L1_status
&&
(
{
!
config
.
UI
.
views
.
block
.
hiddenFields
?.
L1_status
&&
rollupFeature
.
isEnabled
&&
((
rollupFeature
.
type
===
'
zkSync
'
&&
data
.
zksync
)
||
(
rollupFeature
.
type
===
'
arbitrum
'
&&
data
.
arbitrum
))
&&
(
<>
<>
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
hint=
"Status is the short interpretation of the batch lifecycle"
hint=
"Status is the short interpretation of the batch lifecycle"
...
@@ -260,7 +282,16 @@ const BlockDetails = ({ query }: Props) => {
...
@@ -260,7 +282,16 @@ const BlockDetails = ({ query }: Props) => {
Status
Status
</
DetailsInfoItem
.
Label
>
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Value
>
<
VerificationSteps
steps=
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
currentStep=
{
data
.
zksync
.
status
}
isLoading=
{
isPlaceholderData
}
/>
{
rollupFeature
.
type
===
'
zkSync
'
&&
data
.
zksync
&&
<
VerificationSteps
steps=
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
currentStep=
{
data
.
zksync
.
status
}
isLoading=
{
isPlaceholderData
}
/>
}
{
rollupFeature
.
type
===
'
arbitrum
'
&&
data
.
arbitrum
&&
(
<
VerificationSteps
steps=
{
ARBITRUM_L2_TX_BATCH_STATUSES
}
currentStep=
{
data
.
arbitrum
.
status
}
currentStepPending=
{
getArbitrumVerificationStepStatus
(
data
.
arbitrum
)
===
'
pending
'
}
isLoading=
{
isPlaceholderData
}
/>
)
}
</
DetailsInfoItem
.
Value
>
</
DetailsInfoItem
.
Value
>
</>
</>
)
}
)
}
...
@@ -282,6 +313,42 @@ const BlockDetails = ({ query }: Props) => {
...
@@ -282,6 +313,42 @@ const BlockDetails = ({ query }: Props) => {
</>
</>
)
}
)
}
{
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
arbitrum
'
&&
(
data
.
arbitrum
?.
commitment_transaction
.
hash
||
data
.
arbitrum
?.
confirmation_transaction
.
hash
)
&&
(
<>
<
DetailsInfoItemDivider
/>
{
data
.
arbitrum
?.
commitment_transaction
.
hash
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"L1 transaction containing this batch commitment"
isLoading=
{
isPlaceholderData
}
>
Commitment tx
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
TxEntityL1
hash=
{
data
.
arbitrum
?.
commitment_transaction
.
hash
}
isLoading=
{
isPlaceholderData
}
/>
{
data
.
arbitrum
?.
commitment_transaction
.
status
===
'
finalized
'
&&
<
StatusTag
type=
"ok"
text=
"Finalized"
ml=
{
2
}
/>
}
</
DetailsInfoItem
.
Value
>
</>
)
}
{
data
.
arbitrum
?.
confirmation_transaction
.
hash
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"L1 transaction containing confirmation of this batch"
isLoading=
{
isPlaceholderData
}
>
Confirmation tx
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
TxEntityL1
hash=
{
data
.
arbitrum
?.
confirmation_transaction
.
hash
}
isLoading=
{
isPlaceholderData
}
/>
{
data
.
arbitrum
?.
commitment_transaction
.
status
===
'
finalized
'
&&
<
StatusTag
type=
"ok"
text=
"Finalized"
ml=
{
2
}
/>
}
</
DetailsInfoItem
.
Value
>
</>
)
}
</>
)
}
{
!
rollupFeature
.
isEnabled
&&
!
totalReward
.
isEqualTo
(
ZERO
)
&&
!
config
.
UI
.
views
.
block
.
hiddenFields
?.
total_reward
&&
(
{
!
rollupFeature
.
isEnabled
&&
!
totalReward
.
isEqualTo
(
ZERO
)
&&
!
config
.
UI
.
views
.
block
.
hiddenFields
?.
total_reward
&&
(
<>
<>
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
...
...
ui/blocks/BlocksContent.tsx
View file @
baf47a66
...
@@ -23,9 +23,11 @@ const TABS_HEIGHT = 88;
...
@@ -23,9 +23,11 @@ const TABS_HEIGHT = 88;
interface
Props
{
interface
Props
{
type
?:
BlockType
;
type
?:
BlockType
;
query
:
QueryWithPagesResult
<
'
blocks
'
>
;
query
:
QueryWithPagesResult
<
'
blocks
'
>
;
showSocketInfo
?:
boolean
;
top
?:
number
;
}
}
const
BlocksContent
=
({
type
,
query
}:
Props
)
=>
{
const
BlocksContent
=
({
type
,
query
,
showSocketInfo
=
true
,
top
}:
Props
)
=>
{
const
queryClient
=
useQueryClient
();
const
queryClient
=
useQueryClient
();
const
isMobile
=
useIsMobile
();
const
isMobile
=
useIsMobile
();
const
[
socketAlert
,
setSocketAlert
]
=
React
.
useState
(
''
);
const
[
socketAlert
,
setSocketAlert
]
=
React
.
useState
(
''
);
...
@@ -71,7 +73,7 @@ const BlocksContent = ({ type, query }: Props) => {
...
@@ -71,7 +73,7 @@ const BlocksContent = ({ type, query }: Props) => {
topic
:
'
blocks:new_block
'
,
topic
:
'
blocks:new_block
'
,
onSocketClose
:
handleSocketClose
,
onSocketClose
:
handleSocketClose
,
onSocketError
:
handleSocketError
,
onSocketError
:
handleSocketError
,
isDisabled
:
query
.
isPlaceholderData
||
query
.
isError
||
query
.
pagination
.
page
!==
1
,
isDisabled
:
query
.
isPlaceholderData
||
query
.
isError
||
query
.
pagination
.
page
!==
1
||
!
showSocketInfo
,
});
});
useSocketMessage
({
useSocketMessage
({
channel
,
channel
,
...
@@ -82,7 +84,7 @@ const BlocksContent = ({ type, query }: Props) => {
...
@@ -82,7 +84,7 @@ const BlocksContent = ({ type, query }: Props) => {
const
content
=
query
.
data
?.
items
?
(
const
content
=
query
.
data
?.
items
?
(
<>
<>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
{
query
.
pagination
.
page
===
1
&&
(
{
query
.
pagination
.
page
===
1
&&
showSocketInfo
&&
(
<
SocketNewItemsNotice
.
Mobile
<
SocketNewItemsNotice
.
Mobile
url=
{
window
.
location
.
href
}
url=
{
window
.
location
.
href
}
num=
{
newItemsCount
}
num=
{
newItemsCount
}
...
@@ -96,10 +98,10 @@ const BlocksContent = ({ type, query }: Props) => {
...
@@ -96,10 +98,10 @@ const BlocksContent = ({ type, query }: Props) => {
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
block
'
}
}
>
<
BlocksTable
<
BlocksTable
data=
{
query
.
data
.
items
}
data=
{
query
.
data
.
items
}
top=
{
query
.
pagination
.
isVisible
?
TABS_HEIGHT
:
0
}
top=
{
top
||
(
query
.
pagination
.
isVisible
?
TABS_HEIGHT
:
0
)
}
page=
{
query
.
pagination
.
page
}
page=
{
query
.
pagination
.
page
}
isLoading=
{
query
.
isPlaceholderData
}
isLoading=
{
query
.
isPlaceholderData
}
showSocketInfo=
{
query
.
pagination
.
page
===
1
}
showSocketInfo=
{
query
.
pagination
.
page
===
1
&&
showSocketInfo
}
socketInfoNum=
{
newItemsCount
}
socketInfoNum=
{
newItemsCount
}
socketInfoAlert=
{
socketAlert
}
socketInfoAlert=
{
socketAlert
}
/>
/>
...
...
ui/messages/ArbitrumL2Messages.tsx
0 → 100644
View file @
baf47a66
import
{
Hide
,
Show
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
rightLineArrow
,
nbsp
}
from
'
lib/html-entities
'
;
import
{
ARBITRUM_MESSAGES_ITEM
}
from
'
stubs/arbitrumL2
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
ArbitrumL2MessagesListItem
from
'
ui/messages/ArbitrumL2MessagesListItem
'
;
import
ArbitrumL2MessagesTable
from
'
ui/messages/ArbitrumL2MessagesTable
'
;
import
{
ACTION_BAR_HEIGHT_DESKTOP
}
from
'
ui/shared/ActionBar
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
StickyPaginationWithText
from
'
ui/shared/StickyPaginationWithText
'
;
export
type
MessagesDirection
=
'
from-rollup
'
|
'
to-rollup
'
;
type
Props
=
{
direction
:
MessagesDirection
;
}
const
ArbitrumL2Messages
=
({
direction
}:
Props
)
=>
{
const
type
=
direction
===
'
from-rollup
'
?
'
withdrawals
'
:
'
deposits
'
;
const
{
data
,
isError
,
isPlaceholderData
,
pagination
}
=
useQueryWithPages
({
resourceName
:
'
arbitrum_l2_messages
'
,
pathParams
:
{
direction
},
options
:
{
placeholderData
:
generateListStub
<
'
arbitrum_l2_messages
'
>
(
ARBITRUM_MESSAGES_ITEM
,
50
,
{
next_page_params
:
{
items_count
:
50
,
direction
:
'
to-rollup
'
,
id
:
123456
}
},
),
},
});
const
countersQuery
=
useApiQuery
(
'
arbitrum_l2_messages_count
'
,
{
pathParams
:
{
direction
},
queryOptions
:
{
placeholderData
:
1927029
,
},
});
const
content
=
data
?.
items
?
(
<>
<
Show
below=
"lg"
ssr=
{
false
}
>
{
data
.
items
.
map
(((
item
,
index
)
=>
(
<
ArbitrumL2MessagesListItem
key=
{
String
(
item
.
id
)
+
(
isPlaceholderData
?
index
:
''
)
}
isLoading=
{
isPlaceholderData
}
item=
{
item
}
direction=
{
direction
}
/>
)))
}
</
Show
>
<
Hide
below=
"lg"
ssr=
{
false
}
>
<
ArbitrumL2MessagesTable
items=
{
data
.
items
}
direction=
{
direction
}
top=
{
pagination
.
isVisible
?
ACTION_BAR_HEIGHT_DESKTOP
:
0
}
isLoading=
{
isPlaceholderData
}
/>
</
Hide
>
</>
)
:
null
;
const
text
=
(()
=>
{
if
(
countersQuery
.
isError
)
{
return
null
;
}
return
(
<
Skeleton
isLoaded=
{
!
countersQuery
.
isPlaceholderData
}
display=
"inline-block"
>
A total of
{
countersQuery
.
data
?.
toLocaleString
()
}
{
type
}
found
</
Skeleton
>
);
})();
const
actionBar
=
<
StickyPaginationWithText
text=
{
text
}
pagination=
{
pagination
}
/>;
return
(
<>
<
PageTitle
title=
{
direction
===
'
from-rollup
'
?
`Withdrawals (L2${ nbsp }${ rightLineArrow }${ nbsp }L1)`
:
`Deposits (L1${ nbsp }${ rightLineArrow }${ nbsp }L2)`
}
withTextAd
/>
<
DataListDisplay
isError=
{
isError
}
items=
{
data
?.
items
}
emptyText=
{
`There are no ${ type }.`
}
content=
{
content
}
actionBar=
{
actionBar
}
/>
</>
);
};
export
default
ArbitrumL2Messages
;
ui/messages/ArbitrumL2MessagesListItem.tsx
0 → 100644
View file @
baf47a66
import
{
Skeleton
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2MessagesItem
}
from
'
types/api/arbitrumL2
'
;
import
config
from
'
configs/app
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
BlockEntityL1
from
'
ui/shared/entities/block/BlockEntityL1
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
ListItemMobileGrid
from
'
ui/shared/ListItemMobile/ListItemMobileGrid
'
;
import
ArbitrumL2MessageStatus
from
'
ui/shared/statusTag/ArbitrumL2MessageStatus
'
;
import
type
{
MessagesDirection
}
from
'
./ArbitrumL2Messages
'
;
const
rollupFeature
=
config
.
features
.
rollup
;
type
Props
=
{
item
:
ArbitrumL2MessagesItem
;
isLoading
?:
boolean
;
direction
:
MessagesDirection
};
const
ArbitrumL2MessagesListItem
=
({
item
,
isLoading
,
direction
}:
Props
)
=>
{
if
(
!
rollupFeature
.
isEnabled
||
rollupFeature
.
type
!==
'
arbitrum
'
)
{
return
null
;
}
const
timeAgo
=
dayjs
(
item
.
origination_timestamp
).
fromNow
();
const
l1TxHash
=
direction
===
'
from-rollup
'
?
item
.
completion_transaction_hash
:
item
.
origination_transaction_hash
;
const
l2TxHash
=
direction
===
'
from-rollup
'
?
item
.
origination_transaction_hash
:
item
.
completion_transaction_hash
;
return
(
<
ListItemMobileGrid
.
Container
gridTemplateColumns=
"110px auto"
>
{
direction
===
'
to-rollup
'
&&
(
<>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L1 block
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
BlockEntityL1
number=
{
item
.
origination_transaction_block_number
}
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
/>
</
ListItemMobileGrid
.
Value
>
</>
)
}
{
direction
===
'
from-rollup
'
&&
(
<>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
From
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
AddressEntity
address=
{
{
hash
:
item
.
origination_address
}
}
truncation=
"constant"
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
/>
</
ListItemMobileGrid
.
Value
>
</>
)
}
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Message #
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
{
item
.
id
}
</
Skeleton
>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L2 transaction
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
{
l2TxHash
?
(
<
TxEntity
isLoading=
{
isLoading
}
hash=
{
l2TxHash
}
fontSize=
"sm"
lineHeight=
{
5
}
truncation=
"constant_long"
/>
)
:
(
<
chakra
.
span
color=
"text_secondary"
>
N/A
</
chakra
.
span
>
)
}
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Age
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
{
timeAgo
}
</
Skeleton
>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Status
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
ArbitrumL2MessageStatus
status=
{
item
.
status
}
isLoading=
{
isLoading
}
/>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L1 transaction
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
{
l1TxHash
?
(
<
TxEntityL1
isLoading=
{
isLoading
}
hash=
{
l1TxHash
}
fontSize=
"sm"
lineHeight=
{
5
}
truncation=
"constant_long"
/>
)
:
(
<
chakra
.
span
color=
"text_secondary"
>
N/A
</
chakra
.
span
>
)
}
</
ListItemMobileGrid
.
Value
>
</
ListItemMobileGrid
.
Container
>
);
};
export
default
ArbitrumL2MessagesListItem
;
ui/messages/ArbitrumL2MessagesTable.tsx
0 → 100644
View file @
baf47a66
import
{
Table
,
Tbody
,
Th
,
Tr
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2MessagesItem
}
from
'
types/api/arbitrumL2
'
;
import
{
default
as
Thead
}
from
'
ui/shared/TheadSticky
'
;
import
type
{
MessagesDirection
}
from
'
./ArbitrumL2Messages
'
;
import
ArbitrumL2MessagesTableItem
from
'
./ArbitrumL2MessagesTableItem
'
;
type
Props
=
{
items
:
Array
<
ArbitrumL2MessagesItem
>
;
direction
:
MessagesDirection
;
top
:
number
;
isLoading
?:
boolean
;
}
const
ArbitrumL2MessagesTable
=
({
items
,
direction
,
top
,
isLoading
}:
Props
)
=>
{
return
(
<
Table
variant=
"simple"
size=
"sm"
style=
{
{
tableLayout
:
'
auto
'
}
}
minW=
"950px"
>
<
Thead
top=
{
top
}
>
<
Tr
>
{
direction
===
'
to-rollup
'
&&
<
Th
>
L1 block
</
Th
>
}
{
direction
===
'
from-rollup
'
&&
<
Th
>
From
</
Th
>
}
<
Th
>
Message #
</
Th
>
<
Th
>
L2 transaction
</
Th
>
<
Th
>
Age
</
Th
>
<
Th
>
Status
</
Th
>
<
Th
>
L1 transaction
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
>
{
items
.
map
((
item
,
index
)
=>
(
<
ArbitrumL2MessagesTableItem
key=
{
String
(
item
.
id
)
+
(
isLoading
?
index
:
''
)
}
item=
{
item
}
direction=
{
direction
}
isLoading=
{
isLoading
}
/>
))
}
</
Tbody
>
</
Table
>
);
};
export
default
ArbitrumL2MessagesTable
;
ui/messages/ArbitrumL2MessagesTableItem.tsx
0 → 100644
View file @
baf47a66
import
{
Td
,
Tr
,
Skeleton
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2MessagesItem
}
from
'
types/api/arbitrumL2
'
;
import
config
from
'
configs/app
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
BlockEntityL1
from
'
ui/shared/entities/block/BlockEntityL1
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
ArbitrumL2MessageStatus
from
'
ui/shared/statusTag/ArbitrumL2MessageStatus
'
;
import
type
{
MessagesDirection
}
from
'
./ArbitrumL2Messages
'
;
const
rollupFeature
=
config
.
features
.
rollup
;
type
Props
=
{
item
:
ArbitrumL2MessagesItem
;
isLoading
?:
boolean
;
direction
:
MessagesDirection
};
const
ArbitrumL2MessagesTableItem
=
({
item
,
direction
,
isLoading
}:
Props
)
=>
{
if
(
!
rollupFeature
.
isEnabled
||
rollupFeature
.
type
!==
'
arbitrum
'
)
{
return
null
;
}
const
timeAgo
=
dayjs
(
item
.
origination_timestamp
).
fromNow
();
const
l1TxHash
=
direction
===
'
from-rollup
'
?
item
.
completion_transaction_hash
:
item
.
origination_transaction_hash
;
const
l2TxHash
=
direction
===
'
from-rollup
'
?
item
.
origination_transaction_hash
:
item
.
completion_transaction_hash
;
return
(
<
Tr
>
{
direction
===
'
to-rollup
'
&&
(
<
Td
verticalAlign=
"middle"
>
<
BlockEntityL1
number=
{
item
.
origination_transaction_block_number
}
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
noIcon
/>
</
Td
>
)
}
{
direction
===
'
from-rollup
'
&&
(
<
Td
verticalAlign=
"middle"
>
<
AddressEntity
address=
{
{
hash
:
item
.
origination_address
}
}
truncation=
"constant"
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
/>
</
Td
>
)
}
<
Td
verticalAlign=
"middle"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
>
<
span
>
{
item
.
id
}
</
span
>
</
Skeleton
>
</
Td
>
<
Td
verticalAlign=
"middle"
>
{
l2TxHash
?
(
<
TxEntity
isLoading=
{
isLoading
}
hash=
{
l2TxHash
}
fontSize=
"sm"
lineHeight=
{
5
}
truncation=
"constant_long"
noIcon
/>
)
:
(
<
chakra
.
span
color=
"text_secondary"
>
N/A
</
chakra
.
span
>
)
}
</
Td
>
<
Td
verticalAlign=
"middle"
pr=
{
12
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
>
<
span
>
{
timeAgo
}
</
span
>
</
Skeleton
>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
ArbitrumL2MessageStatus
status=
{
item
.
status
}
isLoading=
{
isLoading
}
/>
</
Td
>
<
Td
verticalAlign=
"middle"
>
{
l1TxHash
?
(
<
TxEntityL1
isLoading=
{
isLoading
}
hash=
{
l1TxHash
}
truncation=
"constant_long"
noIcon
fontSize=
"sm"
lineHeight=
{
5
}
/>
)
:
(
<
chakra
.
span
color=
"text_secondary"
>
N/A
</
chakra
.
span
>
)
}
</
Td
>
</
Tr
>
);
};
export
default
ArbitrumL2MessagesTableItem
;
ui/pages/ArbitrumL2Deposits.tsx
0 → 100644
View file @
baf47a66
import
React
from
'
react
'
;
import
ArbitrumL2Messages
from
'
ui/messages/ArbitrumL2Messages
'
;
const
ArbitrumL2Deposits
=
()
=>
{
return
<
ArbitrumL2Messages
direction=
"to-rollup"
/>;
};
export
default
ArbitrumL2Deposits
;
ui/pages/ArbitrumL2TxnBatch.tsx
0 → 100644
View file @
baf47a66
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/Tabs/types
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/contexts/app
'
;
import
throwOnAbsentParamError
from
'
lib/errors/throwOnAbsentParamError
'
;
import
throwOnResourceLoadError
from
'
lib/errors/throwOnResourceLoadError
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
ARBITRUM_L2_TXN_BATCH
}
from
'
stubs/arbitrumL2
'
;
import
{
BLOCK
}
from
'
stubs/block
'
;
import
{
TX
}
from
'
stubs/tx
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
BlocksContent
from
'
ui/blocks/BlocksContent
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
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
ArbitrumL2TxnBatchDetails
from
'
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchDetails
'
;
import
TxsWithFrontendSorting
from
'
ui/txs/TxsWithFrontendSorting
'
;
const
TAB_LIST_PROPS
=
{
marginBottom
:
0
,
py
:
5
,
marginTop
:
-
5
,
};
const
TABS_HEIGHT
=
80
;
const
ArbitrumL2TxnBatch
=
()
=>
{
const
router
=
useRouter
();
const
appProps
=
useAppContext
();
const
number
=
getQueryParamString
(
router
.
query
.
number
);
const
tab
=
getQueryParamString
(
router
.
query
.
tab
);
const
isMobile
=
useIsMobile
();
const
batchQuery
=
useApiQuery
(
'
arbitrum_l2_txn_batch
'
,
{
pathParams
:
{
number
},
queryOptions
:
{
enabled
:
Boolean
(
number
),
placeholderData
:
ARBITRUM_L2_TXN_BATCH
,
},
});
const
batchTxsQuery
=
useQueryWithPages
({
resourceName
:
'
arbitrum_l2_txn_batch_txs
'
,
pathParams
:
{
number
},
options
:
{
enabled
:
Boolean
(
!
batchQuery
.
isPlaceholderData
&&
batchQuery
.
data
?.
number
&&
tab
===
'
txs
'
),
placeholderData
:
generateListStub
<
'
arbitrum_l2_txn_batch_txs
'
>
(
TX
,
50
,
{
next_page_params
:
{
batch_number
:
'
8122
'
,
block_number
:
1338932
,
index
:
0
,
items_count
:
50
,
}
}),
},
});
const
batchBlocksQuery
=
useQueryWithPages
({
resourceName
:
'
arbitrum_l2_txn_batch_blocks
'
,
pathParams
:
{
number
},
options
:
{
enabled
:
Boolean
(
!
batchQuery
.
isPlaceholderData
&&
batchQuery
.
data
?.
number
&&
tab
===
'
blocks
'
),
placeholderData
:
generateListStub
<
'
arbitrum_l2_txn_batch_blocks
'
>
(
BLOCK
,
50
,
{
next_page_params
:
{
batch_number
:
'
8122
'
,
block_number
:
1338932
,
items_count
:
50
,
}
}),
},
});
throwOnAbsentParamError
(
number
);
throwOnResourceLoadError
(
batchQuery
);
let
pagination
;
if
(
tab
===
'
txs
'
)
{
pagination
=
batchTxsQuery
.
pagination
;
}
if
(
tab
===
'
blocks
'
)
{
pagination
=
batchBlocksQuery
.
pagination
;
}
const
hasPagination
=
!
isMobile
&&
pagination
?.
isVisible
;
const
tabs
:
Array
<
RoutedTab
>
=
React
.
useMemo
(()
=>
([
{
id
:
'
index
'
,
title
:
'
Details
'
,
component
:
<
ArbitrumL2TxnBatchDetails
query=
{
batchQuery
}
/>
},
{
id
:
'
txs
'
,
title
:
'
Transactions
'
,
component
:
<
TxsWithFrontendSorting
query=
{
batchTxsQuery
}
showSocketInfo=
{
false
}
top=
{
hasPagination
?
TABS_HEIGHT
:
0
}
/>,
},
{
id
:
'
blocks
'
,
title
:
'
Blocks
'
,
component
:
<
BlocksContent
type=
"block"
query=
{
batchBlocksQuery
}
showSocketInfo=
{
false
}
top=
{
hasPagination
?
TABS_HEIGHT
:
0
}
/>,
},
].
filter
(
Boolean
)),
[
batchQuery
,
batchTxsQuery
,
batchBlocksQuery
,
hasPagination
]);
const
backLink
=
React
.
useMemo
(()
=>
{
const
hasGoBackLink
=
appProps
.
referrer
&&
appProps
.
referrer
.
endsWith
(
'
/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
{
...
(
pagination
)
}
/>
:
null
}
stickyEnabled=
{
hasPagination
}
/>
)
}
</>
);
};
export
default
ArbitrumL2TxnBatch
;
ui/pages/ArbitrumL2TxnBatches.tsx
0 → 100644
View file @
baf47a66
import
{
Hide
,
Show
,
Skeleton
,
Text
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
nbsp
}
from
'
lib/html-entities
'
;
import
{
ARBITRUM_L2_TXN_BATCHES_ITEM
}
from
'
stubs/arbitrumL2
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
{
ACTION_BAR_HEIGHT_DESKTOP
}
from
'
ui/shared/ActionBar
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
StickyPaginationWithText
from
'
ui/shared/StickyPaginationWithText
'
;
import
ArbitrumL2TxnBatchesListItem
from
'
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesListItem
'
;
import
ArbitrumL2TxnBatchesTable
from
'
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesTable
'
;
const
ArbitrumL2TxnBatches
=
()
=>
{
const
{
data
,
isError
,
isPlaceholderData
,
pagination
}
=
useQueryWithPages
({
resourceName
:
'
arbitrum_l2_txn_batches
'
,
options
:
{
placeholderData
:
generateListStub
<
'
arbitrum_l2_txn_batches
'
>
(
ARBITRUM_L2_TXN_BATCHES_ITEM
,
50
,
{
next_page_params
:
{
items_count
:
50
,
number
:
9045200
,
},
},
),
},
});
const
countersQuery
=
useApiQuery
(
'
arbitrum_l2_txn_batches_count
'
,
{
queryOptions
:
{
placeholderData
:
5231746
,
},
});
const
content
=
data
?.
items
?
(
<>
<
Show
below=
"lg"
ssr=
{
false
}
>
{
data
.
items
.
map
(((
item
,
index
)
=>
(
<
ArbitrumL2TxnBatchesListItem
key=
{
item
.
number
+
(
isPlaceholderData
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
Show
>
<
Hide
below=
"lg"
ssr=
{
false
}
>
<
ArbitrumL2TxnBatchesTable
items=
{
data
.
items
}
top=
{
pagination
.
isVisible
?
ACTION_BAR_HEIGHT_DESKTOP
:
0
}
isLoading=
{
isPlaceholderData
}
/>
</
Hide
>
</>
)
:
null
;
const
text
=
(()
=>
{
if
(
countersQuery
.
isError
||
isError
||
!
data
?.
items
.
length
)
{
return
null
;
}
return
(
<
Skeleton
isLoaded=
{
!
countersQuery
.
isPlaceholderData
&&
!
isPlaceholderData
}
display=
"flex"
flexWrap=
"wrap"
>
Tx batch (L2 block)
<
Text
fontWeight=
{
600
}
whiteSpace=
"pre"
>
#
{
data
.
items
[
0
].
number
}
</
Text
>
to
<
Text
fontWeight=
{
600
}
whiteSpace=
"pre"
>
#
{
data
.
items
[
data
.
items
.
length
-
1
].
number
}
</
Text
>
(total of
{
countersQuery
.
data
?.
toLocaleString
()
}
batches)
</
Skeleton
>
);
})();
const
actionBar
=
<
StickyPaginationWithText
text=
{
text
}
pagination=
{
pagination
}
/>;
return
(
<>
<
PageTitle
title=
{
`Tx batches (L2${ nbsp }blocks)`
}
withTextAd
/>
<
DataListDisplay
isError=
{
isError
}
items=
{
data
?.
items
}
emptyText=
"There are no tx batches."
content=
{
content
}
actionBar=
{
actionBar
}
/>
</>
);
};
export
default
ArbitrumL2TxnBatches
;
ui/pages/ArbitrumL2Withdrawals.tsx
0 → 100644
View file @
baf47a66
import
React
from
'
react
'
;
import
ArbitrumL2Messages
from
'
ui/messages/ArbitrumL2Messages
'
;
const
ArbitrumL2Withdrawals
=
()
=>
{
return
<
ArbitrumL2Messages
direction=
"from-rollup"
/>;
};
export
default
ArbitrumL2Withdrawals
;
ui/pages/Block.tsx
View file @
baf47a66
...
@@ -47,6 +47,11 @@ const BlockPageContent = () => {
...
@@ -47,6 +47,11 @@ const BlockPageContent = () => {
const
blockWithdrawalsQuery
=
useBlockWithdrawalsQuery
({
heightOrHash
,
blockQuery
,
tab
});
const
blockWithdrawalsQuery
=
useBlockWithdrawalsQuery
({
heightOrHash
,
blockQuery
,
tab
});
const
blockBlobTxsQuery
=
useBlockBlobTxsQuery
({
heightOrHash
,
blockQuery
,
tab
});
const
blockBlobTxsQuery
=
useBlockBlobTxsQuery
({
heightOrHash
,
blockQuery
,
tab
});
const
hasPagination
=
!
isMobile
&&
(
(
tab
===
'
txs
'
&&
blockTxsQuery
.
pagination
.
isVisible
)
||
(
tab
===
'
withdrawals
'
&&
blockWithdrawalsQuery
.
pagination
.
isVisible
)
);
const
tabs
:
Array
<
RoutedTab
>
=
React
.
useMemo
(()
=>
([
const
tabs
:
Array
<
RoutedTab
>
=
React
.
useMemo
(()
=>
([
{
{
id
:
'
index
'
,
id
:
'
index
'
,
...
@@ -64,7 +69,7 @@ const BlockPageContent = () => {
...
@@ -64,7 +69,7 @@ const BlockPageContent = () => {
component
:
(
component
:
(
<>
<>
{
blockTxsQuery
.
isDegradedData
&&
<
ServiceDegradationWarning
isLoading=
{
blockTxsQuery
.
isPlaceholderData
}
mb=
{
6
}
/>
}
{
blockTxsQuery
.
isDegradedData
&&
<
ServiceDegradationWarning
isLoading=
{
blockTxsQuery
.
isPlaceholderData
}
mb=
{
6
}
/>
}
<
TxsWithFrontendSorting
query=
{
blockTxsQuery
}
showBlockInfo=
{
false
}
showSocketInfo=
{
false
}
top=
{
TABS_HEIGHT
}
/>
<
TxsWithFrontendSorting
query=
{
blockTxsQuery
}
showBlockInfo=
{
false
}
showSocketInfo=
{
false
}
top=
{
hasPagination
?
TABS_HEIGHT
:
0
}
/>
</>
</>
),
),
},
},
...
@@ -87,12 +92,7 @@ const BlockPageContent = () => {
...
@@ -87,12 +92,7 @@ const BlockPageContent = () => {
</>
</>
),
),
}
:
null
,
}
:
null
,
].
filter
(
Boolean
)),
[
blockBlobTxsQuery
,
blockQuery
,
blockTxsQuery
,
blockWithdrawalsQuery
]);
].
filter
(
Boolean
)),
[
blockBlobTxsQuery
,
blockQuery
,
blockTxsQuery
,
blockWithdrawalsQuery
,
hasPagination
]);
const
hasPagination
=
!
isMobile
&&
(
(
tab
===
'
txs
'
&&
blockTxsQuery
.
pagination
.
isVisible
)
||
(
tab
===
'
withdrawals
'
&&
blockWithdrawalsQuery
.
pagination
.
isVisible
)
);
let
pagination
;
let
pagination
;
if
(
tab
===
'
txs
'
)
{
if
(
tab
===
'
txs
'
)
{
...
...
ui/pages/ZkSyncL2TxnBatch.tsx
View file @
baf47a66
...
@@ -27,6 +27,8 @@ const TAB_LIST_PROPS = {
...
@@ -27,6 +27,8 @@ const TAB_LIST_PROPS = {
marginTop
:
-
5
,
marginTop
:
-
5
,
};
};
const
TABS_HEIGHT
=
80
;
const
ZkSyncL2TxnBatch
=
()
=>
{
const
ZkSyncL2TxnBatch
=
()
=>
{
const
router
=
useRouter
();
const
router
=
useRouter
();
const
appProps
=
useAppContext
();
const
appProps
=
useAppContext
();
...
@@ -59,10 +61,16 @@ const ZkSyncL2TxnBatch = () => {
...
@@ -59,10 +61,16 @@ const ZkSyncL2TxnBatch = () => {
throwOnAbsentParamError
(
number
);
throwOnAbsentParamError
(
number
);
throwOnResourceLoadError
(
batchQuery
);
throwOnResourceLoadError
(
batchQuery
);
const
hasPagination
=
!
isMobile
&&
batchTxsQuery
.
pagination
.
isVisible
&&
tab
===
'
txs
'
;
const
tabs
:
Array
<
RoutedTab
>
=
React
.
useMemo
(()
=>
([
const
tabs
:
Array
<
RoutedTab
>
=
React
.
useMemo
(()
=>
([
{
id
:
'
index
'
,
title
:
'
Details
'
,
component
:
<
ZkSyncL2TxnBatchDetails
query=
{
batchQuery
}
/>
},
{
id
:
'
index
'
,
title
:
'
Details
'
,
component
:
<
ZkSyncL2TxnBatchDetails
query=
{
batchQuery
}
/>
},
{
id
:
'
txs
'
,
title
:
'
Transactions
'
,
component
:
<
TxsWithFrontendSorting
query=
{
batchTxsQuery
}
showSocketInfo=
{
false
}
/>
},
{
].
filter
(
Boolean
)),
[
batchQuery
,
batchTxsQuery
]);
id
:
'
txs
'
,
title
:
'
Transactions
'
,
component
:
<
TxsWithFrontendSorting
query=
{
batchTxsQuery
}
showSocketInfo=
{
false
}
top=
{
hasPagination
?
TABS_HEIGHT
:
0
}
/>,
},
].
filter
(
Boolean
)),
[
batchQuery
,
batchTxsQuery
,
hasPagination
]);
const
backLink
=
React
.
useMemo
(()
=>
{
const
backLink
=
React
.
useMemo
(()
=>
{
const
hasGoBackLink
=
appProps
.
referrer
&&
appProps
.
referrer
.
endsWith
(
'
/batches
'
);
const
hasGoBackLink
=
appProps
.
referrer
&&
appProps
.
referrer
.
endsWith
(
'
/batches
'
);
...
@@ -77,8 +85,6 @@ const ZkSyncL2TxnBatch = () => {
...
@@ -77,8 +85,6 @@ const ZkSyncL2TxnBatch = () => {
};
};
},
[
appProps
.
referrer
]);
},
[
appProps
.
referrer
]);
const
hasPagination
=
!
isMobile
&&
batchTxsQuery
.
pagination
.
isVisible
&&
tab
===
'
txs
'
;
return
(
return
(
<>
<>
<
TextAd
mb=
{
6
}
/>
<
TextAd
mb=
{
6
}
/>
...
...
ui/shared/statusTag/ArbitrumL2MessageStatus.tsx
0 → 100644
View file @
baf47a66
import
React
from
'
react
'
;
import
type
{
ArbitrumL2MessagesItem
}
from
'
types/api/arbitrumL2
'
;
import
type
{
StatusTagType
}
from
'
./StatusTag
'
;
import
StatusTag
from
'
./StatusTag
'
;
export
interface
Props
{
status
:
ArbitrumL2MessagesItem
[
'
status
'
];
isLoading
?:
boolean
;
}
const
ArbitrumL2MessageStatus
=
({
status
,
isLoading
}:
Props
)
=>
{
let
type
:
StatusTagType
;
switch
(
status
)
{
case
'
relayed
'
:
case
'
confirmed
'
:
type
=
'
ok
'
;
break
;
default
:
type
=
'
pending
'
;
break
;
}
return
<
StatusTag
type=
{
type
}
text=
{
status
}
isLoading=
{
isLoading
}
/>;
};
export
default
ArbitrumL2MessageStatus
;
ui/shared/statusTag/ArbitrumL2TxnBatchStatus.tsx
0 → 100644
View file @
baf47a66
import
React
from
'
react
'
;
import
type
{
ArbitrumL2TxnBatchesItem
}
from
'
types/api/arbitrumL2
'
;
import
type
{
StatusTagType
}
from
'
./StatusTag
'
;
import
StatusTag
from
'
./StatusTag
'
;
export
interface
Props
{
status
:
ArbitrumL2TxnBatchesItem
[
'
commitment_transaction
'
][
'
status
'
];
isLoading
?:
boolean
;
}
const
ArbitrumL2TxnBatchStatus
=
({
status
,
isLoading
}:
Props
)
=>
{
let
type
:
StatusTagType
;
switch
(
status
)
{
case
'
finalized
'
:
type
=
'
ok
'
;
break
;
default
:
type
=
'
pending
'
;
break
;
}
return
<
StatusTag
type=
{
type
}
text=
{
status
}
isLoading=
{
isLoading
}
/>;
};
export
default
ArbitrumL2TxnBatchStatus
;
ui/shared/statusTag/StatusTag.tsx
View file @
baf47a66
import
{
TagLabel
,
Tooltip
}
from
'
@chakra-ui/react
'
;
import
{
TagLabel
,
Tooltip
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
Tag
from
'
ui/shared/chakra/Tag
'
;
import
Tag
from
'
ui/shared/chakra/Tag
'
;
...
@@ -12,9 +12,10 @@ export interface Props {
...
@@ -12,9 +12,10 @@ export interface Props {
text
:
string
;
text
:
string
;
errorText
?:
string
|
null
;
errorText
?:
string
|
null
;
isLoading
?:
boolean
;
isLoading
?:
boolean
;
className
?:
string
;
}
}
const
StatusTag
=
({
type
,
text
,
errorText
,
isLoading
}:
Props
)
=>
{
const
StatusTag
=
({
type
,
text
,
errorText
,
isLoading
,
className
}:
Props
)
=>
{
let
icon
:
IconName
;
let
icon
:
IconName
;
let
colorScheme
;
let
colorScheme
;
...
@@ -35,7 +36,7 @@ const StatusTag = ({ type, text, errorText, isLoading }: Props) => {
...
@@ -35,7 +36,7 @@ const StatusTag = ({ type, text, errorText, isLoading }: Props) => {
return
(
return
(
<
Tooltip
label=
{
errorText
}
>
<
Tooltip
label=
{
errorText
}
>
<
Tag
colorScheme=
{
colorScheme
}
display=
"flex"
isLoading=
{
isLoading
}
>
<
Tag
colorScheme=
{
colorScheme
}
display=
"flex"
isLoading=
{
isLoading
}
className=
{
className
}
>
<
IconSvg
boxSize=
{
2.5
}
name=
{
icon
}
mr=
{
1
}
flexShrink=
{
0
}
/>
<
IconSvg
boxSize=
{
2.5
}
name=
{
icon
}
mr=
{
1
}
flexShrink=
{
0
}
/>
<
TagLabel
display=
"block"
>
{
text
}
</
TagLabel
>
<
TagLabel
display=
"block"
>
{
text
}
</
TagLabel
>
</
Tag
>
</
Tag
>
...
@@ -43,4 +44,4 @@ const StatusTag = ({ type, text, errorText, isLoading }: Props) => {
...
@@ -43,4 +44,4 @@ const StatusTag = ({ type, text, errorText, isLoading }: Props) => {
);
);
};
};
export
default
StatusTag
;
export
default
chakra
(
StatusTag
)
;
ui/shared/verificationSteps/VerificationStep.tsx
View file @
baf47a66
...
@@ -9,10 +9,16 @@ type Props = {
...
@@ -9,10 +9,16 @@ type Props = {
step
:
Step
;
step
:
Step
;
isLast
:
boolean
;
isLast
:
boolean
;
isPassed
:
boolean
;
isPassed
:
boolean
;
isPending
?:
boolean
;
}
}
const
VerificationStep
=
({
step
,
isLast
,
isPassed
}:
Props
)
=>
{
const
VerificationStep
=
({
step
,
isLast
,
isPassed
,
isPending
}:
Props
)
=>
{
const
stepColor
=
isPassed
?
'
green.500
'
:
'
text_secondary
'
;
let
stepColor
=
'
text_secondary
'
;
if
(
isPending
)
{
stepColor
=
'
yellow.500
'
;
}
else
if
(
isPassed
)
{
stepColor
=
'
green.500
'
;
}
return
(
return
(
<
HStack
gap=
{
2
}
color=
{
stepColor
}
>
<
HStack
gap=
{
2
}
color=
{
stepColor
}
>
...
...
ui/shared/verificationSteps/VerificationSteps.tsx
View file @
baf47a66
...
@@ -7,13 +7,14 @@ import VerificationStep from './VerificationStep';
...
@@ -7,13 +7,14 @@ import VerificationStep from './VerificationStep';
export
interface
Props
{
export
interface
Props
{
currentStep
:
string
;
currentStep
:
string
;
currentStepPending
?:
boolean
;
steps
:
Array
<
Step
>
;
steps
:
Array
<
Step
>
;
isLoading
?:
boolean
;
isLoading
?:
boolean
;
rightSlot
?:
React
.
ReactNode
;
rightSlot
?:
React
.
ReactNode
;
className
?:
string
;
className
?:
string
;
}
}
const
VerificationSteps
=
({
currentStep
,
steps
,
isLoading
,
rightSlot
,
className
}:
Props
)
=>
{
const
VerificationSteps
=
({
currentStep
,
currentStepPending
,
steps
,
isLoading
,
rightSlot
,
className
}:
Props
)
=>
{
const
currentStepIndex
=
steps
.
findIndex
((
step
)
=>
{
const
currentStepIndex
=
steps
.
findIndex
((
step
)
=>
{
const
label
=
typeof
step
===
'
string
'
?
step
:
step
.
label
;
const
label
=
typeof
step
===
'
string
'
?
step
:
step
.
label
;
return
label
===
currentStep
;
return
label
===
currentStep
;
...
@@ -34,6 +35,7 @@ const VerificationSteps = ({ currentStep, steps, isLoading, rightSlot, className
...
@@ -34,6 +35,7 @@ const VerificationSteps = ({ currentStep, steps, isLoading, rightSlot, className
step=
{
step
}
step=
{
step
}
isLast=
{
index
===
steps
.
length
-
1
&&
!
rightSlot
}
isLast=
{
index
===
steps
.
length
-
1
&&
!
rightSlot
}
isPassed=
{
index
<=
currentStepIndex
}
isPassed=
{
index
<=
currentStepIndex
}
isPending=
{
index
===
currentStepIndex
&&
currentStepPending
}
/>
/>
))
}
))
}
{
rightSlot
}
{
rightSlot
}
...
...
ui/tx/details/TxInfo.tsx
View file @
baf47a66
...
@@ -15,6 +15,7 @@ import BigNumber from 'bignumber.js';
...
@@ -15,6 +15,7 @@ import BigNumber from 'bignumber.js';
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
scroller
,
Element
}
from
'
react-scroll
'
;
import
{
scroller
,
Element
}
from
'
react-scroll
'
;
import
{
ARBITRUM_L2_TX_BATCH_STATUSES
}
from
'
types/api/arbitrumL2
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
{
ZKEVM_L2_TX_STATUSES
}
from
'
types/api/transaction
'
;
import
{
ZKEVM_L2_TX_STATUSES
}
from
'
types/api/transaction
'
;
import
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
from
'
types/api/zkSyncL2
'
;
import
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
from
'
types/api/zkSyncL2
'
;
...
@@ -23,6 +24,7 @@ import { route } from 'nextjs-routes';
...
@@ -23,6 +24,7 @@ import { route } from 'nextjs-routes';
import
config
from
'
configs/app
'
;
import
config
from
'
configs/app
'
;
import
{
WEI
,
WEI_IN_GWEI
}
from
'
lib/consts
'
;
import
{
WEI
,
WEI_IN_GWEI
}
from
'
lib/consts
'
;
import
getArbitrumVerificationStepStatus
from
'
lib/getArbitrumVerificationStepStatus
'
;
import
getNetworkValidatorTitle
from
'
lib/networks/getNetworkValidatorTitle
'
;
import
getNetworkValidatorTitle
from
'
lib/networks/getNetworkValidatorTitle
'
;
import
getConfirmationDuration
from
'
lib/tx/getConfirmationDuration
'
;
import
getConfirmationDuration
from
'
lib/tx/getConfirmationDuration
'
;
import
{
currencyUnits
}
from
'
lib/units
'
;
import
{
currencyUnits
}
from
'
lib/units
'
;
...
@@ -36,10 +38,12 @@ import DetailsTimestamp from 'ui/shared/DetailsTimestamp';
...
@@ -36,10 +38,12 @@ import DetailsTimestamp from 'ui/shared/DetailsTimestamp';
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
BatchEntityL2
from
'
ui/shared/entities/block/BatchEntityL2
'
;
import
BatchEntityL2
from
'
ui/shared/entities/block/BatchEntityL2
'
;
import
BlockEntity
from
'
ui/shared/entities/block/BlockEntity
'
;
import
BlockEntity
from
'
ui/shared/entities/block/BlockEntity
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
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
'
;
import
StatusTag
from
'
ui/shared/statusTag/StatusTag
'
;
import
TxStatus
from
'
ui/shared/statusTag/TxStatus
'
;
import
TxStatus
from
'
ui/shared/statusTag/TxStatus
'
;
import
TextSeparator
from
'
ui/shared/TextSeparator
'
;
import
TextSeparator
from
'
ui/shared/TextSeparator
'
;
import
TxFeeStability
from
'
ui/shared/tx/TxFeeStability
'
;
import
TxFeeStability
from
'
ui/shared/tx/TxFeeStability
'
;
...
@@ -152,7 +156,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -152,7 +156,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
isLoading=
{
isLoading
}
isLoading=
{
isLoading
}
>
>
{
{
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
zkEvm
'
||
rollupFeature
.
type
===
'
zkSync
'
)
?
rollupFeature
.
isEnabled
&&
(
rollupFeature
.
type
===
'
zkEvm
'
||
rollupFeature
.
type
===
'
zkSync
'
||
rollupFeature
.
type
===
'
arbitrum
'
)
?
'
L2 status and method
'
:
'
L2 status and method
'
:
'
Status and method
'
'
Status and method
'
}
}
...
@@ -164,6 +168,11 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -164,6 +168,11 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
{
data
.
method
}
{
data
.
method
}
</
Tag
>
</
Tag
>
)
}
)
}
{
data
.
arbitrum
?.
contains_message
&&
(
<
Tag
isLoading=
{
isLoading
}
isTruncated
ml=
{
3
}
>
{
data
.
arbitrum
?.
contains_message
===
'
incoming
'
?
'
Incoming message
'
:
'
Outgoing message
'
}
</
Tag
>
)
}
</
DetailsInfoItem
.
Value
>
</
DetailsInfoItem
.
Value
>
{
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
optimistic
'
&&
data
.
op_withdrawals
&&
data
.
op_withdrawals
.
length
>
0
&&
{
rollupFeature
.
isEnabled
&&
rollupFeature
.
type
===
'
optimistic
'
&&
data
.
op_withdrawals
&&
data
.
op_withdrawals
.
length
>
0
&&
...
@@ -172,7 +181,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -172,7 +181,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
hint=
"Detailed status progress of the transaction"
hint=
"Detailed status progress of the transaction"
>
>
Withdrawal status
Withdrawal status
</
DetailsInfoItem
.
Label
>
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Value
>
<
Flex
flexDir=
"column"
rowGap=
{
2
}
>
<
Flex
flexDir=
"column"
rowGap=
{
2
}
>
...
@@ -207,6 +216,25 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -207,6 +216,25 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
</>
</>
)
}
)
}
{
data
.
arbitrum
?.
status
&&
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
L1_status
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"Status of the transaction confirmation path to L1"
isLoading=
{
isLoading
}
>
L1 status
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
VerificationSteps
currentStep=
{
data
.
arbitrum
.
status
}
currentStepPending=
{
getArbitrumVerificationStepStatus
(
data
.
arbitrum
)
===
'
pending
'
}
steps=
{
ARBITRUM_L2_TX_BATCH_STATUSES
}
isLoading=
{
isLoading
}
/>
</
DetailsInfoItem
.
Value
>
</>
)
}
{
data
.
revert_reason
&&
(
{
data
.
revert_reason
&&
(
<>
<>
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
...
@@ -226,7 +254,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -226,7 +254,7 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
hint=
"Status is the short interpretation of the batch lifecycle"
hint=
"Status is the short interpretation of the batch lifecycle"
isLoading=
{
isLoading
}
isLoading=
{
isLoading
}
>
>
L1 status
L1 status
</
DetailsInfoItem
.
Label
>
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Value
>
<
VerificationSteps
steps=
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
currentStep=
{
data
.
zksync
.
status
}
isLoading=
{
isLoading
}
/>
<
VerificationSteps
steps=
{
ZKSYNC_L2_TX_BATCH_STATUSES
}
currentStep=
{
data
.
zksync
.
status
}
isLoading=
{
isLoading
}
/>
...
@@ -295,6 +323,22 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -295,6 +323,22 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
</>
</>
)
}
)
}
{
data
.
arbitrum
&&
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
batch
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"Index of the batch containing this transaction"
isLoading=
{
isLoading
}
>
Batch
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
{
data
.
arbitrum
.
batch_number
?
<
BatchEntityL2
isLoading=
{
isLoading
}
number=
{
data
.
arbitrum
.
batch_number
}
/>
:
<
Skeleton
isLoaded=
{
!
isLoading
}
>
Pending
</
Skeleton
>
}
</
DetailsInfoItem
.
Value
>
</>
)
}
{
data
.
timestamp
&&
(
{
data
.
timestamp
&&
(
<>
<>
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
...
@@ -412,6 +456,41 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
...
@@ -412,6 +456,41 @@ const TxInfo = ({ data, isLoading, socketStatus }: Props) => {
<
DetailsInfoItemDivider
/>
<
DetailsInfoItemDivider
/>
{
(
data
.
arbitrum
?.
commitment_transaction
.
hash
||
data
.
arbitrum
?.
confirmation_transaction
.
hash
)
&&
(
<>
{
data
.
arbitrum
?.
commitment_transaction
.
hash
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"L1 transaction containing this batch commitment"
isLoading=
{
isLoading
}
>
Commitment tx
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
TxEntityL1
hash=
{
data
.
arbitrum
?.
commitment_transaction
.
hash
}
isLoading=
{
isLoading
}
/>
{
data
.
arbitrum
?.
commitment_transaction
.
status
===
'
finalized
'
&&
<
StatusTag
type=
"ok"
text=
"Finalized"
ml=
{
2
}
/>
}
</
DetailsInfoItem
.
Value
>
</>
)
}
{
data
.
arbitrum
?.
confirmation_transaction
.
hash
&&
(
<>
<
DetailsInfoItem
.
Label
hint=
"L1 transaction containing confirmation of this batch"
isLoading=
{
isLoading
}
>
Confirmation tx
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
TxEntityL1
hash=
{
data
.
arbitrum
?.
confirmation_transaction
.
hash
}
isLoading=
{
isLoading
}
/>
{
data
.
arbitrum
?.
commitment_transaction
.
status
===
'
finalized
'
&&
<
StatusTag
type=
"ok"
text=
"Finalized"
ml=
{
2
}
/>
}
</
DetailsInfoItem
.
Value
>
</>
)
}
<
DetailsInfoItemDivider
/>
</>
)
}
{
data
.
zkevm_sequence_hash
&&
(
{
data
.
zkevm_sequence_hash
&&
(
<>
<>
<
DetailsInfoItem
.
Label
<
DetailsInfoItem
.
Label
...
...
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchDetails.tsx
0 → 100644
View file @
baf47a66
import
{
Grid
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2TxnBatch
}
from
'
types/api/arbitrumL2
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
type
{
ResourceError
}
from
'
lib/api/resources
'
;
import
throwOnResourceLoadError
from
'
lib/errors/throwOnResourceLoadError
'
;
import
isCustomAppError
from
'
ui/shared/AppError/isCustomAppError
'
;
import
CopyToClipboard
from
'
ui/shared/CopyToClipboard
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
*
as
DetailsInfoItem
from
'
ui/shared/DetailsInfoItem
'
;
import
DetailsTimestamp
from
'
ui/shared/DetailsTimestamp
'
;
import
BlockEntityL1
from
'
ui/shared/entities/block/BlockEntityL1
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
PrevNext
from
'
ui/shared/PrevNext
'
;
interface
Props
{
query
:
UseQueryResult
<
ArbitrumL2TxnBatch
,
ResourceError
>
;
}
const
ArbitrumL2TxnBatchDetails
=
({
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
:
'
/batches/[number]
'
,
query
:
{
number
:
nextId
}
},
undefined
);
},
[
data
,
router
]);
if
(
isError
)
{
if
(
isCustomAppError
(
error
))
{
throwOnResourceLoadError
({
isError
,
error
});
}
return
<
DataFetchAlert
/>;
}
if
(
!
data
)
{
return
null
;
}
const
blocksCount
=
data
.
end_block
-
data
.
start_block
+
1
;
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
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"Batch number indicates the length of batches produced by grouping L2 blocks to be proven on L1"
>
Tx batch number
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
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
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"Date and time at which batch is submitted to L1"
>
Timestamp
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
{
data
.
commitment_transaction
.
timestamp
?
<
DetailsTimestamp
timestamp=
{
data
.
commitment_transaction
.
timestamp
}
isLoading=
{
isPlaceholderData
}
/>
:
'
Undefined
'
}
</
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"Number of transactions in this batch"
>
Transactions
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
<
LinkInternal
href=
{
route
({
pathname
:
'
/batches/[number]
'
,
query
:
{
number
:
data
.
number
.
toString
(),
tab
:
'
txs
'
}
})
}
>
{
data
.
transactions_count
}
transaction
{
data
.
transactions_count
===
1
?
''
:
'
s
'
}
</
LinkInternal
>
</
Skeleton
>
</
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"Number of L2 blocks in this batch"
>
Blocks
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
<
LinkInternal
href=
{
route
({
pathname
:
'
/batches/[number]
'
,
query
:
{
number
:
data
.
number
.
toString
(),
tab
:
'
blocks
'
}
})
}
>
{
blocksCount
}
block
{
blocksCount
===
1
?
''
:
'
s
'
}
</
LinkInternal
>
</
Skeleton
>
</
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"Hash of L1 transaction in which transactions was committed"
>
L1 transaction hash
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
TxEntityL1
isLoading=
{
isPlaceholderData
}
hash=
{
data
.
commitment_transaction
.
hash
}
maxW=
"100%"
/>
</
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"Heigh of L1 block which includes L1 transactions"
>
L1 block
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
BlockEntityL1
isLoading=
{
isPlaceholderData
}
number=
{
data
.
commitment_transaction
.
block_number
}
/>
</
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"The hash of the state before the batch"
>
Before acc
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
overflow=
"hidden"
>
<
HashStringShortenDynamic
hash=
{
data
.
before_acc
}
/>
<
CopyToClipboard
text=
{
data
.
before_acc
}
/>
</
Skeleton
>
</
DetailsInfoItem
.
Value
>
<
DetailsInfoItem
.
Label
isLoading=
{
isPlaceholderData
}
hint=
"The hash of the state after the batch"
>
After acc
</
DetailsInfoItem
.
Label
>
<
DetailsInfoItem
.
Value
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
overflow=
"hidden"
>
<
HashStringShortenDynamic
hash=
{
data
.
after_acc
}
/>
<
CopyToClipboard
text=
{
data
.
after_acc
}
/>
</
Skeleton
>
</
DetailsInfoItem
.
Value
>
</
Grid
>
);
};
export
default
ArbitrumL2TxnBatchDetails
;
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesListItem.tsx
0 → 100644
View file @
baf47a66
import
{
Skeleton
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2TxnBatchesItem
}
from
'
types/api/arbitrumL2
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
config
from
'
configs/app
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
BatchEntityL2
from
'
ui/shared/entities/block/BatchEntityL2
'
;
import
BlockEntityL1
from
'
ui/shared/entities/block/BlockEntityL1
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
ListItemMobileGrid
from
'
ui/shared/ListItemMobile/ListItemMobileGrid
'
;
import
ArbitrumL2TxnBatchStatus
from
'
ui/shared/statusTag/ArbitrumL2TxnBatchStatus
'
;
const
rollupFeature
=
config
.
features
.
rollup
;
type
Props
=
{
item
:
ArbitrumL2TxnBatchesItem
;
isLoading
?:
boolean
};
const
ArbitrumL2TxnBatchesListItem
=
({
item
,
isLoading
}:
Props
)
=>
{
const
timeAgo
=
item
.
commitment_transaction
.
timestamp
?
dayjs
(
item
.
commitment_transaction
.
timestamp
).
fromNow
()
:
'
Undefined
'
;
if
(
!
rollupFeature
.
isEnabled
||
rollupFeature
.
type
!==
'
arbitrum
'
)
{
return
null
;
}
return
(
<
ListItemMobileGrid
.
Container
gridTemplateColumns=
"110px auto"
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Batch #
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
BatchEntityL2
isLoading=
{
isLoading
}
number=
{
item
.
number
}
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
/>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L1 status
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
ArbitrumL2TxnBatchStatus
status=
{
item
.
commitment_transaction
.
status
}
isLoading=
{
isLoading
}
/>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L1 block
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
BlockEntityL1
number=
{
item
.
commitment_transaction
.
block_number
}
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
/>
</
ListItemMobileGrid
.
Value
>
{
item
.
block_count
&&
(
<>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L2 block txn count
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
{
item
.
block_count
}
</
Skeleton
>
</
ListItemMobileGrid
.
Value
>
</>
)
}
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
L1 transaction
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
TxEntityL1
hash=
{
item
.
commitment_transaction
.
hash
}
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
truncation=
"constant_long"
/>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Age
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
{
timeAgo
}
</
Skeleton
>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Txn count
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
LinkInternal
href=
{
route
({
pathname
:
'
/batches/[number]
'
,
query
:
{
number
:
item
.
number
.
toString
(),
tab
:
'
txs
'
}
})
}
isLoading=
{
isLoading
}
fontWeight=
{
600
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
minW=
"40px"
>
{
item
.
transactions_count
}
</
Skeleton
>
</
LinkInternal
>
</
ListItemMobileGrid
.
Value
>
</
ListItemMobileGrid
.
Container
>
);
};
export
default
ArbitrumL2TxnBatchesListItem
;
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesTable.tsx
0 → 100644
View file @
baf47a66
import
{
Table
,
Tbody
,
Th
,
Tr
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2TxnBatchesItem
}
from
'
types/api/arbitrumL2
'
;
import
{
default
as
Thead
}
from
'
ui/shared/TheadSticky
'
;
import
ArbitrumL2TxnBatchesTableItem
from
'
./ArbitrumL2TxnBatchesTableItem
'
;
type
Props
=
{
items
:
Array
<
ArbitrumL2TxnBatchesItem
>
;
top
:
number
;
isLoading
?:
boolean
;
}
const
ArbitrumL2TxnBatchesTable
=
({
items
,
top
,
isLoading
}:
Props
)
=>
{
return
(
<
Table
variant=
"simple"
size=
"sm"
minW=
"1000px"
style=
{
{
tableLayout
:
'
auto
'
}
}
>
<
Thead
top=
{
top
}
>
<
Tr
>
<
Th
>
Batch #
</
Th
>
<
Th
>
L1 status
</
Th
>
<
Th
>
L1 block
</
Th
>
<
Th
>
L2 block txn count
</
Th
>
<
Th
>
L1 transaction
</
Th
>
<
Th
>
Age
</
Th
>
<
Th
>
Txn count
</
Th
>
</
Tr
>
</
Thead
>
<
Tbody
>
{
items
.
map
((
item
,
index
)
=>
(
<
ArbitrumL2TxnBatchesTableItem
key=
{
item
.
number
+
(
isLoading
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
isLoading
}
/>
))
}
</
Tbody
>
</
Table
>
);
};
export
default
ArbitrumL2TxnBatchesTable
;
ui/txnBatches/arbitrumL2/ArbitrumL2TxnBatchesTableItem.tsx
0 → 100644
View file @
baf47a66
import
{
Td
,
Tr
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
ArbitrumL2TxnBatchesItem
}
from
'
types/api/arbitrumL2
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
config
from
'
configs/app
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
BatchEntityL2
from
'
ui/shared/entities/block/BatchEntityL2
'
;
import
BlockEntityL1
from
'
ui/shared/entities/block/BlockEntityL1
'
;
import
TxEntityL1
from
'
ui/shared/entities/tx/TxEntityL1
'
;
import
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
ArbitrumL2TxnBatchStatus
from
'
ui/shared/statusTag/ArbitrumL2TxnBatchStatus
'
;
const
rollupFeature
=
config
.
features
.
rollup
;
type
Props
=
{
item
:
ArbitrumL2TxnBatchesItem
;
isLoading
?:
boolean
};
const
TxnBatchesTableItem
=
({
item
,
isLoading
}:
Props
)
=>
{
const
timeAgo
=
item
.
commitment_transaction
.
timestamp
?
dayjs
(
item
.
commitment_transaction
.
timestamp
).
fromNow
()
:
'
Undefined
'
;
if
(
!
rollupFeature
.
isEnabled
||
rollupFeature
.
type
!==
'
arbitrum
'
)
{
return
null
;
}
return
(
<
Tr
>
<
Td
verticalAlign=
"middle"
>
<
BatchEntityL2
isLoading=
{
isLoading
}
number=
{
item
.
number
}
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
noIcon
/>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
ArbitrumL2TxnBatchStatus
status=
{
item
.
commitment_transaction
.
status
}
isLoading=
{
isLoading
}
/>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
BlockEntityL1
number=
{
item
.
commitment_transaction
.
block_number
}
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
/>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
{
item
.
block_count
||
'
N/A
'
}
</
Skeleton
>
</
Td
>
<
Td
pr=
{
12
}
verticalAlign=
"middle"
>
<
TxEntityL1
hash=
{
item
.
commitment_transaction
.
hash
}
isLoading=
{
isLoading
}
fontSize=
"sm"
lineHeight=
{
5
}
truncation=
"constant_long"
/>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
>
<
span
>
{
timeAgo
}
</
span
>
</
Skeleton
>
</
Td
>
<
Td
verticalAlign=
"middle"
>
<
LinkInternal
href=
{
route
({
pathname
:
'
/batches/[number]
'
,
query
:
{
number
:
item
.
number
.
toString
(),
tab
:
'
txs
'
}
})
}
isLoading=
{
isLoading
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
minW=
"40px"
>
{
item
.
transactions_count
}
</
Skeleton
>
</
LinkInternal
>
</
Td
>
</
Tr
>
);
};
export
default
TxnBatchesTableItem
;
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