mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
shibarium deposits and withdrawals
This commit is contained in:
+1
-1
@@ -369,7 +369,7 @@ This feature is **enabled by default** with the `coinzilla` ads provider. To swi
|
||||
|
||||
| Variable | Type| Description | Compulsoriness | Default value | Example value |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| NEXT_PUBLIC_ROLLUP_TYPE | `'optimistic' \| 'zkEvm' ` | Rollup chain type | Required | - | `'optimistic'` |
|
||||
| NEXT_PUBLIC_ROLLUP_TYPE | `'optimistic' \| 'shibarium' \| 'zkEvm' ` | Rollup chain type | Required | - | `'optimistic'` |
|
||||
| NEXT_PUBLIC_ROLLUP_L1_BASE_URL | `string` | Blockscout base URL for L1 network | Required | - | `'http://eth-goerli.blockscout.com'` |
|
||||
| NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL | `string` | URL for L2 -> L1 withdrawals | - | - | `https://app.optimism.io/bridge/withdraw` |
|
||||
|
||||
|
||||
+25
-3
@@ -57,6 +57,7 @@ import type {
|
||||
} from 'types/api/optimisticL2';
|
||||
import type { RawTracesResponse } from 'types/api/rawTrace';
|
||||
import type { SearchRedirectResult, SearchResult, SearchResultFilters, SearchResultItem } from 'types/api/search';
|
||||
import type { ShibariumWithdrawalsResponse, ShibariumDepositsResponse } from 'types/api/shibarium';
|
||||
import type { Counters, StatsCharts, StatsChart, HomeStats } from 'types/api/stats';
|
||||
import type {
|
||||
TokenCounters,
|
||||
@@ -602,6 +603,25 @@ export const RESOURCES = {
|
||||
filterFields: [],
|
||||
},
|
||||
|
||||
// SHIBARIUM L2
|
||||
shibarium_deposits: {
|
||||
path: '/api/v2/shibarium/deposits',
|
||||
filterFields: [],
|
||||
},
|
||||
|
||||
shibarium_deposits_count: {
|
||||
path: '/api/v2/shibarium/deposits/count',
|
||||
},
|
||||
|
||||
shibarium_withdrawals: {
|
||||
path: '/api/v2/shibarium/withdrawals',
|
||||
filterFields: [],
|
||||
},
|
||||
|
||||
shibarium_withdrawals_count: {
|
||||
path: '/api/v2/shibarium/withdrawals/count',
|
||||
},
|
||||
|
||||
// USER OPS
|
||||
user_ops: {
|
||||
path: '/api/v2/proxy/account-abstraction/operations',
|
||||
@@ -696,6 +716,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
|
||||
'token_instance_transfers' | 'token_instance_holders' |
|
||||
'verified_contracts' |
|
||||
'l2_output_roots' | 'l2_withdrawals' | 'l2_txn_batches' | 'l2_deposits' |
|
||||
'shibarium_deposits' | 'shibarium_withdrawals' |
|
||||
'zkevm_l2_txn_batches' | 'zkevm_l2_txn_batch_txs' |
|
||||
'withdrawals' | 'address_withdrawals' | 'block_withdrawals' |
|
||||
'watchlist' | 'private_tags_address' | 'private_tags_tx' |
|
||||
@@ -819,13 +840,14 @@ Q extends 'marketplace_dapps' ? Array<MarketplaceAppOverview> :
|
||||
Q extends 'marketplace_dapp' ? MarketplaceAppOverview :
|
||||
Q extends 'validators' ? ValidatorsResponse :
|
||||
Q extends 'validators_counters' ? ValidatorsCountersResponse :
|
||||
Q extends 'shibarium_withdrawals' ? ShibariumWithdrawalsResponse :
|
||||
Q extends 'shibarium_deposits' ? ShibariumDepositsResponse :
|
||||
Q extends 'shibarium_withdrawals_count' ? number :
|
||||
Q extends 'shibarium_deposits_count' ? number :
|
||||
never;
|
||||
/* eslint-enable @typescript-eslint/indent */
|
||||
|
||||
export type ResourcePayload<Q extends ResourceName> = ResourcePayloadA<Q> | ResourcePayloadB<Q>;
|
||||
|
||||
// Right now there is no paginated resources in B-part
|
||||
// Add "| ResourcePayloadB<Q>[...]" if it is not true anymore
|
||||
export type PaginatedResponseItems<Q extends ResourceName> = Q extends PaginatedResources ? ResourcePayloadA<Q>['items'] | ResourcePayloadB<Q>['items'] : never;
|
||||
export type PaginatedResponseNextPageParams<Q extends ResourceName> = Q extends PaginatedResources ?
|
||||
ResourcePayloadA<Q>['next_page_params'] | ResourcePayloadB<Q>['next_page_params'] :
|
||||
|
||||
@@ -119,6 +119,23 @@ export default function useNavItems(): ReturnType {
|
||||
ensLookup,
|
||||
].filter(Boolean),
|
||||
];
|
||||
} else if (rollupFeature.isEnabled && rollupFeature.type === 'shibarium') {
|
||||
blockchainNavItems = [
|
||||
[
|
||||
txs,
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: `Deposits (L1${ rightLineArrow }L2)`, nextRoute: { pathname: '/deposits' as const }, icon: 'arrows/south-east', isActive: pathname === '/deposits' },
|
||||
// eslint-disable-next-line max-len
|
||||
{ text: `Withdrawals (L2${ rightLineArrow }L1)`, nextRoute: { pathname: '/withdrawals' as const }, icon: 'arrows/north-east', isActive: pathname === '/withdrawals' },
|
||||
],
|
||||
[
|
||||
blocks,
|
||||
userOps,
|
||||
topAccounts,
|
||||
verifiedContracts,
|
||||
ensLookup,
|
||||
].filter(Boolean),
|
||||
];
|
||||
} else {
|
||||
blockchainNavItems = [
|
||||
txs,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { ShibariumDepositsResponse } from 'types/api/shibarium';
|
||||
|
||||
export const data: ShibariumDepositsResponse = {
|
||||
items: [
|
||||
{
|
||||
l1_block_number: 8382841,
|
||||
timestamp: '2022-05-27T01:13:48.000000Z',
|
||||
l1_transaction_hash: '0xaf3e5f4ef03eac22a622b3434c5dc9f4465aa291900a86bcf0ad9fb14429f05e',
|
||||
user: {
|
||||
hash: '0x6197d1eef304eb5284a0f6720f79403b4e9bf3a5',
|
||||
implementation_name: null,
|
||||
is_contract: false,
|
||||
is_verified: false,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
public_tags: [],
|
||||
watchlist_names: [],
|
||||
ens_domain_name: null,
|
||||
},
|
||||
l2_transaction_hash: '0xb9212c76069b926917816767e4c5a0ef80e519b1ac1c3d3fb5818078f4984667',
|
||||
},
|
||||
{
|
||||
l1_block_number: 8382841,
|
||||
timestamp: '2022-05-27T01:13:48.000000Z',
|
||||
l1_transaction_hash: '0xaf3e5f4ef03eac22a622b3434c5dc9f4465aa291900a86bcf0ad9fb14429f05e',
|
||||
user: {
|
||||
hash: '0x6197d1eef304eb5284a0f6720f79403b4e9bf3a5',
|
||||
implementation_name: null,
|
||||
is_contract: false,
|
||||
is_verified: false,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
public_tags: [],
|
||||
watchlist_names: [],
|
||||
ens_domain_name: null,
|
||||
},
|
||||
l2_transaction_hash: '0xb9212c76069b926917816767e4c5a0ef80e519b1ac1c3d3fb5818078f4984667',
|
||||
},
|
||||
{
|
||||
l1_block_number: 8382841,
|
||||
timestamp: '2022-05-27T01:13:48.000000Z',
|
||||
l1_transaction_hash: '0xaf3e5f4ef03eac22a622b3434c5dc9f4465aa291900a86bcf0ad9fb14429f05e',
|
||||
user: {
|
||||
hash: '0x6197d1eef304eb5284a0f6720f79403b4e9bf3a5',
|
||||
implementation_name: null,
|
||||
is_contract: false,
|
||||
is_verified: false,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
public_tags: [],
|
||||
watchlist_names: [],
|
||||
ens_domain_name: null,
|
||||
},
|
||||
l2_transaction_hash: '0xb9212c76069b926917816767e4c5a0ef80e519b1ac1c3d3fb5818078f4984667',
|
||||
},
|
||||
],
|
||||
next_page_params: {
|
||||
items_count: 50,
|
||||
block_number: 8382363,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { ShibariumWithdrawalsResponse } from 'types/api/shibarium';
|
||||
|
||||
export const data: ShibariumWithdrawalsResponse = {
|
||||
items: [
|
||||
{
|
||||
l2_block_number: 8382841,
|
||||
timestamp: '2022-05-27T01:13:48.000000Z',
|
||||
l1_transaction_hash: '0xaf3e5f4ef03eac22a622b3434c5dc9f4465aa291900a86bcf0ad9fb14429f05e',
|
||||
user: {
|
||||
hash: '0x6197d1eef304eb5284a0f6720f79403b4e9bf3a5',
|
||||
implementation_name: null,
|
||||
is_contract: false,
|
||||
is_verified: false,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
public_tags: [],
|
||||
watchlist_names: [],
|
||||
ens_domain_name: null,
|
||||
},
|
||||
l2_transaction_hash: '0xb9212c76069b926917816767e4c5a0ef80e519b1ac1c3d3fb5818078f4984667',
|
||||
},
|
||||
{
|
||||
l2_block_number: 8382841,
|
||||
timestamp: '2022-05-27T01:13:48.000000Z',
|
||||
l1_transaction_hash: '0xaf3e5f4ef03eac22a622b3434c5dc9f4465aa291900a86bcf0ad9fb14429f05e',
|
||||
user: {
|
||||
hash: '0x6197d1eef304eb5284a0f6720f79403b4e9bf3a5',
|
||||
implementation_name: null,
|
||||
is_contract: false,
|
||||
is_verified: false,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
public_tags: [],
|
||||
watchlist_names: [],
|
||||
ens_domain_name: null,
|
||||
},
|
||||
l2_transaction_hash: '0xb9212c76069b926917816767e4c5a0ef80e519b1ac1c3d3fb5818078f4984667',
|
||||
},
|
||||
{
|
||||
l2_block_number: 8382841,
|
||||
timestamp: '2022-05-27T01:13:48.000000Z',
|
||||
l1_transaction_hash: '0xaf3e5f4ef03eac22a622b3434c5dc9f4465aa291900a86bcf0ad9fb14429f05e',
|
||||
user: {
|
||||
hash: '0x6197d1eef304eb5284a0f6720f79403b4e9bf3a5',
|
||||
implementation_name: null,
|
||||
is_contract: false,
|
||||
is_verified: false,
|
||||
name: null,
|
||||
private_tags: [],
|
||||
public_tags: [],
|
||||
watchlist_names: [],
|
||||
ens_domain_name: null,
|
||||
},
|
||||
l2_transaction_hash: '0xb9212c76069b926917816767e4c5a0ef80e519b1ac1c3d3fb5818078f4984667',
|
||||
},
|
||||
],
|
||||
next_page_params: {
|
||||
items_count: 50,
|
||||
block_number: 8382363,
|
||||
},
|
||||
};
|
||||
@@ -49,10 +49,20 @@ export const verifiedAddresses: GetServerSideProps<Props> = async(context) => {
|
||||
return account(context);
|
||||
};
|
||||
|
||||
export const deposits: GetServerSideProps<Props> = async(context) => {
|
||||
if (!(rollupFeature.isEnabled && (rollupFeature.type === 'optimistic' || rollupFeature.type === 'shibarium'))) {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
return base(context);
|
||||
};
|
||||
|
||||
export const withdrawals: GetServerSideProps<Props> = async(context) => {
|
||||
if (
|
||||
!config.features.beaconChain.isEnabled &&
|
||||
!(rollupFeature.isEnabled && rollupFeature.type === 'optimistic')
|
||||
!(rollupFeature.isEnabled && (rollupFeature.type === 'optimistic' || rollupFeature.type === 'shibarium'))
|
||||
) {
|
||||
return {
|
||||
notFound: true,
|
||||
|
||||
@@ -18,6 +18,7 @@ const Batches = dynamic(() => {
|
||||
case 'optimistic':
|
||||
return import('ui/pages/OptimisticL2TxnBatches');
|
||||
}
|
||||
throw new Error('Deposits feature is not enabled.');
|
||||
}, { ssr: false });
|
||||
|
||||
const Page: NextPage = () => {
|
||||
|
||||
@@ -4,7 +4,20 @@ import React from 'react';
|
||||
|
||||
import PageNextJs from 'nextjs/PageNextJs';
|
||||
|
||||
const Deposits = dynamic(() => import('ui/pages/OptimisticL2Deposits'), { ssr: false });
|
||||
import config from 'configs/app';
|
||||
const rollupFeature = config.features.rollup;
|
||||
|
||||
const Deposits = dynamic(() => {
|
||||
if (rollupFeature.isEnabled && rollupFeature.type === 'optimistic') {
|
||||
return import('ui/pages/OptimisticL2Deposits');
|
||||
}
|
||||
|
||||
if (rollupFeature.isEnabled && rollupFeature.type === 'shibarium') {
|
||||
return import('ui/pages/ShibariumDeposits');
|
||||
}
|
||||
|
||||
throw new Error('Withdrawals feature is not enabled.');
|
||||
}, { ssr: false });
|
||||
|
||||
const Page: NextPage = () => {
|
||||
return (
|
||||
@@ -16,4 +29,4 @@ const Page: NextPage = () => {
|
||||
|
||||
export default Page;
|
||||
|
||||
export { optimisticRollup as getServerSideProps } from 'nextjs/getServerSideProps';
|
||||
export { deposits as getServerSideProps } from 'nextjs/getServerSideProps';
|
||||
|
||||
@@ -12,6 +12,11 @@ const Withdrawals = dynamic(() => {
|
||||
if (rollupFeature.isEnabled && rollupFeature.type === 'optimistic') {
|
||||
return import('ui/pages/OptimisticL2Withdrawals');
|
||||
}
|
||||
|
||||
if (rollupFeature.isEnabled && rollupFeature.type === 'shibarium') {
|
||||
return import('ui/pages/ShibariumWithdrawals');
|
||||
}
|
||||
|
||||
if (beaconChainFeature.isEnabled) {
|
||||
return import('ui/pages/BeaconChainWithdrawals');
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@ export const featureEnvs = {
|
||||
{ name: 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', value: 'https://localhost:3101' },
|
||||
{ name: 'NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL', value: 'https://localhost:3102' },
|
||||
],
|
||||
shibariumRollup: [
|
||||
{ name: 'NEXT_PUBLIC_ROLLUP_TYPE', value: 'shibarium' },
|
||||
{ name: 'NEXT_PUBLIC_ROLLUP_L1_BASE_URL', value: 'https://localhost:3101' },
|
||||
],
|
||||
bridgedTokens: [
|
||||
{
|
||||
name: 'NEXT_PUBLIC_BRIDGED_TOKENS_CHAINS',
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { ShibariumDepositsItem, ShibariumWithdrawalsItem } from 'types/api/shibarium';
|
||||
|
||||
import { ADDRESS_PARAMS } from './addressParams';
|
||||
import { TX_HASH } from './tx';
|
||||
|
||||
export const SHIBARIUM_DEPOSIT_ITEM: ShibariumDepositsItem = {
|
||||
l1_block_number: 9045233,
|
||||
l1_transaction_hash: TX_HASH,
|
||||
l2_transaction_hash: TX_HASH,
|
||||
timestamp: '2023-05-22T18:00:36.000000Z',
|
||||
user: ADDRESS_PARAMS,
|
||||
};
|
||||
|
||||
export const SHIBARIUM_WITHDRAWAL_ITEM: ShibariumWithdrawalsItem = {
|
||||
l2_block_number: 9045233,
|
||||
l1_transaction_hash: TX_HASH,
|
||||
l2_transaction_hash: TX_HASH,
|
||||
timestamp: '2023-05-22T18:00:36.000000Z',
|
||||
user: ADDRESS_PARAMS,
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { AddressParam } from './addressParams';
|
||||
|
||||
export type ShibariumDepositsItem = {
|
||||
l1_block_number: number;
|
||||
l1_transaction_hash: string;
|
||||
l2_transaction_hash: string;
|
||||
timestamp: string;
|
||||
user: AddressParam | string;
|
||||
}
|
||||
|
||||
export type ShibariumDepositsResponse = {
|
||||
items: Array<ShibariumDepositsItem>;
|
||||
next_page_params: {
|
||||
items_count: number;
|
||||
block_number: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type ShibariumWithdrawalsItem = {
|
||||
l1_transaction_hash: string;
|
||||
l2_block_number: number;
|
||||
l2_transaction_hash: string;
|
||||
timestamp: string;
|
||||
user: AddressParam | string;
|
||||
}
|
||||
|
||||
export type ShibariumWithdrawalsResponse = {
|
||||
items: Array<ShibariumWithdrawalsItem>;
|
||||
next_page_params: {
|
||||
items_count: number;
|
||||
block_number: number;
|
||||
};
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import type { ArrayElement } from 'types/utils';
|
||||
|
||||
export const ROLLUP_TYPES = [
|
||||
'optimistic',
|
||||
'shibarium',
|
||||
'zkEvm',
|
||||
] as const;
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { Skeleton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { ShibariumDepositsItem } from 'types/api/shibarium';
|
||||
|
||||
import config from 'configs/app';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressStringOrParam from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
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';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
type Props = { item: ShibariumDepositsItem; isLoading?: boolean };
|
||||
|
||||
const DepositsListItem = ({ item, isLoading }: Props) => {
|
||||
const timeAgo = dayjs(item.timestamp).fromNow();
|
||||
|
||||
if (!(feature.isEnabled && feature.type === 'shibarium')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItemMobileGrid.Container>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 block No</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<BlockEntityL1
|
||||
number={ item.l1_block_number }
|
||||
isLoading={ isLoading }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l1_transaction_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant_long"
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l2_transaction_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant_long"
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>User</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<AddressStringOrParam
|
||||
address={ item.user }
|
||||
isLoading={ isLoading }
|
||||
noCopy
|
||||
truncation="constant"
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>Age</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">{ timeAgo }</Skeleton>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
</ListItemMobileGrid.Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default DepositsListItem;
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Table, Tbody, Th, Tr } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { ShibariumDepositsItem } from 'types/api/shibarium';
|
||||
|
||||
import { default as Thead } from 'ui/shared/TheadSticky';
|
||||
|
||||
import DepositsTableItem from './DepositsTableItem';
|
||||
|
||||
type Props = {
|
||||
items: Array<ShibariumDepositsItem>;
|
||||
top: number;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const DepositsTable = ({ items, top, isLoading }: Props) => {
|
||||
return (
|
||||
<Table variant="simple" size="sm" style={{ tableLayout: 'auto' }} minW="950px">
|
||||
<Thead top={ top }>
|
||||
<Tr>
|
||||
<Th>L1 block No</Th>
|
||||
<Th>L1 txn hash</Th>
|
||||
<Th>L2 txn hash</Th>
|
||||
<Th>User</Th>
|
||||
<Th>Age</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{ items.map((item, index) => (
|
||||
<DepositsTableItem key={ item.l2_transaction_hash + (isLoading ? index : '') } item={ item } isLoading={ isLoading }/>
|
||||
)) }
|
||||
</Tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
export default DepositsTable;
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Td, Tr, Skeleton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { ShibariumDepositsItem } from 'types/api/shibarium';
|
||||
|
||||
import config from 'configs/app';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressStringOrParam from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
type Props = { item: ShibariumDepositsItem; isLoading?: boolean };
|
||||
|
||||
const DepositsTableItem = ({ item, isLoading }: Props) => {
|
||||
const timeAgo = dayjs(item.timestamp).fromNow();
|
||||
|
||||
if (!(feature.isEnabled && feature.type === 'shibarium')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Td verticalAlign="middle">
|
||||
<BlockEntityL1
|
||||
number={ item.l1_block_number }
|
||||
isLoading={ isLoading }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l1_transaction_hash }
|
||||
truncation="constant_long"
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l2_transaction_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant_long"
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<AddressStringOrParam
|
||||
address={ item.user }
|
||||
isLoading={ isLoading }
|
||||
truncation="constant"
|
||||
noCopy
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle" pr={ 12 }>
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block"><span>{ timeAgo }</span></Skeleton>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
};
|
||||
|
||||
export default DepositsTableItem;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { test as base, expect } from '@playwright/experimental-ct-react';
|
||||
import React from 'react';
|
||||
|
||||
import { data as depositsData } from 'mocks/shibarium/deposits';
|
||||
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
|
||||
import TestApp from 'playwright/TestApp';
|
||||
import buildApiUrl from 'playwright/utils/buildApiUrl';
|
||||
import * as configs from 'playwright/utils/configs';
|
||||
|
||||
import ShibariumDeposits from './ShibariumDeposits';
|
||||
|
||||
const DEPOSITS_API_URL = buildApiUrl('shibarium_deposits');
|
||||
const DEPOSITS_COUNT_API_URL = buildApiUrl('shibarium_deposits_count');
|
||||
|
||||
const test = base.extend({
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
context: contextWithEnvs(configs.featureEnvs.shibariumRollup) as any,
|
||||
});
|
||||
|
||||
test('base view +@mobile', async({ mount, page }) => {
|
||||
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: '',
|
||||
}));
|
||||
|
||||
await page.route(DEPOSITS_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: JSON.stringify(depositsData),
|
||||
}));
|
||||
|
||||
await page.route(DEPOSITS_COUNT_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: '3971111',
|
||||
}));
|
||||
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<ShibariumDeposits/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot();
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
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 { SHIBARIUM_DEPOSIT_ITEM } from 'stubs/shibarium';
|
||||
import { generateListStub } from 'stubs/utils';
|
||||
import DepositsListItem from 'ui/deposits/shibarium/DepositsListItem';
|
||||
import DepositsTable from 'ui/deposits/shibarium/DepositsTable';
|
||||
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';
|
||||
|
||||
const L2Deposits = () => {
|
||||
const { data, isError, isPlaceholderData, pagination } = useQueryWithPages({
|
||||
resourceName: 'shibarium_deposits',
|
||||
options: {
|
||||
placeholderData: generateListStub<'shibarium_deposits'>(
|
||||
SHIBARIUM_DEPOSIT_ITEM,
|
||||
50,
|
||||
{
|
||||
next_page_params: {
|
||||
items_count: 50,
|
||||
block_number: 9045200,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
const countersQuery = useApiQuery('shibarium_deposits_count', {
|
||||
queryOptions: {
|
||||
placeholderData: 1927029,
|
||||
},
|
||||
});
|
||||
|
||||
const content = data?.items ? (
|
||||
<>
|
||||
<Show below="lg" ssr={ false }>
|
||||
{ data.items.map(((item, index) => (
|
||||
<DepositsListItem
|
||||
key={ item.l2_transaction_hash + (isPlaceholderData ? index : '') }
|
||||
isLoading={ isPlaceholderData }
|
||||
item={ item }
|
||||
/>
|
||||
))) }
|
||||
</Show>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<DepositsTable items={ data.items } top={ pagination.isVisible ? 80 : 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() } deposits found
|
||||
</Skeleton>
|
||||
);
|
||||
})();
|
||||
|
||||
const actionBar = <StickyPaginationWithText text={ text } pagination={ pagination }/>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={ `Deposits (L1${ nbsp }${ rightLineArrow }${ nbsp }L2)` } withTextAd/>
|
||||
<DataListDisplay
|
||||
isError={ isError }
|
||||
items={ data?.items }
|
||||
emptyText="There are no withdrawals."
|
||||
content={ content }
|
||||
actionBar={ actionBar }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default L2Deposits;
|
||||
@@ -0,0 +1,47 @@
|
||||
import { test as base, expect } from '@playwright/experimental-ct-react';
|
||||
import React from 'react';
|
||||
|
||||
import { data as withdrawalsData } from 'mocks/shibarium/withdrawals';
|
||||
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
|
||||
import TestApp from 'playwright/TestApp';
|
||||
import buildApiUrl from 'playwright/utils/buildApiUrl';
|
||||
import * as configs from 'playwright/utils/configs';
|
||||
|
||||
import ShibariuWithdrawals from './ShibariumWithdrawals';
|
||||
|
||||
const test = base.extend({
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
context: contextWithEnvs(configs.featureEnvs.shibariumRollup) as any,
|
||||
});
|
||||
|
||||
const WITHDRAWALS_API_URL = buildApiUrl('shibarium_withdrawals');
|
||||
const WITHDRAWALS_COUNT_API_URL = buildApiUrl('shibarium_withdrawals_count');
|
||||
|
||||
test('base view +@mobile', async({ mount, page }) => {
|
||||
// test on mobile is flaky
|
||||
// my assumption is there is not enough time to calculate hashes truncation so component is unstable
|
||||
// so I raised the test timeout to check if it helps
|
||||
test.slow();
|
||||
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: '',
|
||||
}));
|
||||
|
||||
await page.route(WITHDRAWALS_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: JSON.stringify(withdrawalsData),
|
||||
}));
|
||||
|
||||
await page.route(WITHDRAWALS_COUNT_API_URL, (route) => route.fulfill({
|
||||
status: 200,
|
||||
body: '397',
|
||||
}));
|
||||
|
||||
const component = await mount(
|
||||
<TestApp>
|
||||
<ShibariuWithdrawals/>
|
||||
</TestApp>,
|
||||
);
|
||||
|
||||
await expect(component).toHaveScreenshot({ timeout: 10_000 });
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
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 { SHIBARIUM_WITHDRAWAL_ITEM } from 'stubs/shibarium';
|
||||
import { generateListStub } from 'stubs/utils';
|
||||
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 WithdrawalsListItem from 'ui/withdrawals/shibarium/WithdrawalsListItem';
|
||||
import WithdrawalsTable from 'ui/withdrawals/shibarium/WithdrawalsTable';
|
||||
|
||||
const L2Withdrawals = () => {
|
||||
const { data, isError, isPlaceholderData, pagination } = useQueryWithPages({
|
||||
resourceName: 'shibarium_withdrawals',
|
||||
options: {
|
||||
placeholderData: generateListStub<'shibarium_withdrawals'>(
|
||||
SHIBARIUM_WITHDRAWAL_ITEM,
|
||||
50,
|
||||
{
|
||||
next_page_params: {
|
||||
items_count: 50,
|
||||
block_number: 123,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
const countersQuery = useApiQuery('shibarium_withdrawals_count', {
|
||||
queryOptions: {
|
||||
placeholderData: 23700,
|
||||
},
|
||||
});
|
||||
|
||||
const content = data?.items ? (
|
||||
<>
|
||||
<Show below="lg" ssr={ false }>{ data.items.map(((item, index) => (
|
||||
<WithdrawalsListItem
|
||||
key={ item.l2_transaction_hash + (isPlaceholderData ? index : '') }
|
||||
item={ item }
|
||||
isLoading={ isPlaceholderData }
|
||||
/>
|
||||
))) }</Show>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<WithdrawalsTable items={ data.items } top={ pagination.isVisible ? 80 : 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() } withdrawals found
|
||||
</Skeleton>
|
||||
);
|
||||
})();
|
||||
|
||||
const actionBar = <StickyPaginationWithText text={ text } pagination={ pagination }/>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={ `Withdrawals (L2${ nbsp }${ rightLineArrow }${ nbsp }L1)` } withTextAd/>
|
||||
<DataListDisplay
|
||||
isError={ isError }
|
||||
items={ data?.items }
|
||||
emptyText="There are no withdrawals."
|
||||
content={ content }
|
||||
actionBar={ actionBar }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default L2Withdrawals;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
+4
-4
@@ -2,14 +2,14 @@ import React from 'react';
|
||||
|
||||
import type { AddressParamBasic } from 'types/api/addressParams';
|
||||
|
||||
import AddressEntity from '../entities/address/AddressEntity';
|
||||
import type { EntityProps } from '../entities/address/AddressEntity';
|
||||
import AddressEntity from './AddressEntity';
|
||||
import type { EntityProps } from './AddressEntity';
|
||||
|
||||
type Props = Omit<EntityProps, 'address'> & {
|
||||
address: string | AddressParamBasic;
|
||||
}
|
||||
|
||||
const UserOpsAddress = ({ address, ...props }: Props) => {
|
||||
const AddressStringOrParam = ({ address, ...props }: Props) => {
|
||||
let addressParam;
|
||||
if (typeof address === 'string') {
|
||||
addressParam = { hash: address };
|
||||
@@ -20,4 +20,4 @@ const UserOpsAddress = ({ address, ...props }: Props) => {
|
||||
return <AddressEntity address={ addressParam } { ...props }/>;
|
||||
};
|
||||
|
||||
export default UserOpsAddress;
|
||||
export default AddressStringOrParam;
|
||||
@@ -17,11 +17,11 @@ import DataFetchAlert from 'ui/shared/DataFetchAlert';
|
||||
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
|
||||
import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
|
||||
import DetailsTimestamp from 'ui/shared/DetailsTimestamp';
|
||||
import UserOpsAddress from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import UserOpEntity from 'ui/shared/entities/userOp/UserOpEntity';
|
||||
import RawInputData from 'ui/shared/RawInputData';
|
||||
import UserOpsAddress from 'ui/shared/userOps/UserOpsAddress';
|
||||
import UserOpSponsorType from 'ui/shared/userOps/UserOpSponsorType';
|
||||
import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
|
||||
import Utilization from 'ui/shared/Utilization/Utilization';
|
||||
|
||||
@@ -6,11 +6,11 @@ import type { UserOpsItem } from 'types/api/userOps';
|
||||
import config from 'configs/app';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import CurrencyValue from 'ui/shared/CurrencyValue';
|
||||
import AddressStringOrParam from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import UserOpEntity from 'ui/shared/entities/userOp/UserOpEntity';
|
||||
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
|
||||
import UserOpsAddress from 'ui/shared/userOps/UserOpsAddress';
|
||||
import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
|
||||
|
||||
type Props = {
|
||||
@@ -45,7 +45,7 @@ const UserOpsListItem = ({ item, isLoading, showTx, showSender }: Props) => {
|
||||
<>
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>Sender</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<UserOpsAddress
|
||||
<AddressStringOrParam
|
||||
address={ item.address }
|
||||
isLoading={ isLoading }
|
||||
truncation="constant"
|
||||
|
||||
@@ -6,10 +6,10 @@ import type { UserOpsItem } from 'types/api/userOps';
|
||||
import config from 'configs/app';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import CurrencyValue from 'ui/shared/CurrencyValue';
|
||||
import AddressStringOrParam from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import UserOpEntity from 'ui/shared/entities/userOp/UserOpEntity';
|
||||
import UserOpsAddress from 'ui/shared/userOps/UserOpsAddress';
|
||||
import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
|
||||
|
||||
type Props = {
|
||||
@@ -35,7 +35,7 @@ const UserOpsTableItem = ({ item, isLoading, showTx, showSender }: Props) => {
|
||||
</Td>
|
||||
{ showSender && (
|
||||
<Td verticalAlign="middle">
|
||||
<UserOpsAddress
|
||||
<AddressStringOrParam
|
||||
address={ item.address }
|
||||
isLoading={ isLoading }
|
||||
truncation="constant"
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { Skeleton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { ShibariumWithdrawalsItem } from 'types/api/shibarium';
|
||||
|
||||
import config from 'configs/app';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressStringOrParam from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
type Props = { item: ShibariumWithdrawalsItem; isLoading?: boolean };
|
||||
|
||||
const WithdrawalsListItem = ({ item, isLoading }: Props) => {
|
||||
const timeAgo = item.timestamp ? dayjs(item.timestamp).fromNow() : null;
|
||||
|
||||
if (!(feature.isEnabled && feature.type === 'shibarium')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItemMobileGrid.Container>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block No</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<BlockEntity
|
||||
number={ item.l2_block_number }
|
||||
isLoading={ isLoading }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l2_transaction_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant_long"
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l1_transaction_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant_long"
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>User</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<AddressStringOrParam
|
||||
address={ item.user }
|
||||
isLoading={ isLoading }
|
||||
noCopy
|
||||
truncation="constant"
|
||||
/>
|
||||
</ListItemMobileGrid.Value>
|
||||
<ListItemMobileGrid.Label isLoading={ isLoading }>Age</ListItemMobileGrid.Label>
|
||||
<ListItemMobileGrid.Value>
|
||||
<Skeleton isLoaded={ !isLoading } display="inline-block">{ timeAgo }</Skeleton>
|
||||
</ListItemMobileGrid.Value>
|
||||
|
||||
</ListItemMobileGrid.Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default WithdrawalsListItem;
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Table, Tbody, Th, Tr } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { ShibariumWithdrawalsItem } from 'types/api/shibarium';
|
||||
|
||||
import { default as Thead } from 'ui/shared/TheadSticky';
|
||||
|
||||
import WithdrawalsTableItem from './WithdrawalsTableItem';
|
||||
|
||||
type Props = {
|
||||
items: Array<ShibariumWithdrawalsItem>;
|
||||
top: number;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const WithdrawalsTable = ({ items, top, isLoading }: Props) => {
|
||||
return (
|
||||
<Table variant="simple" size="sm" style={{ tableLayout: 'auto' }} minW="950px">
|
||||
<Thead top={ top }>
|
||||
<Tr>
|
||||
<Th>L2 block No</Th>
|
||||
<Th>L2 txn hash</Th>
|
||||
<Th>L1 txn hash</Th>
|
||||
<Th>User</Th>
|
||||
<Th>Age</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{ items.map((item, index) => (
|
||||
<WithdrawalsTableItem key={ item.l2_transaction_hash + (isLoading ? index : '') } item={ item } isLoading={ isLoading }/>
|
||||
)) }
|
||||
</Tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
export default WithdrawalsTable;
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Td, Tr, Skeleton } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { ShibariumWithdrawalsItem } from 'types/api/shibarium';
|
||||
|
||||
import config from 'configs/app';
|
||||
import dayjs from 'lib/date/dayjs';
|
||||
import AddressStringOrParam from 'ui/shared/entities/address/AddressStringOrParam';
|
||||
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
|
||||
import TxEntity from 'ui/shared/entities/tx/TxEntity';
|
||||
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
|
||||
|
||||
const feature = config.features.rollup;
|
||||
|
||||
type Props = { item: ShibariumWithdrawalsItem; isLoading?: boolean };
|
||||
|
||||
const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
|
||||
const timeAgo = dayjs(item.timestamp).fromNow();
|
||||
|
||||
if (!(feature.isEnabled && feature.type === 'shibarium')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Td verticalAlign="middle">
|
||||
<BlockEntity
|
||||
number={ item.l2_block_number }
|
||||
isLoading={ isLoading }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
fontWeight={ 600 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<TxEntity
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l2_transaction_hash }
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
truncation="constant_long"
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<TxEntityL1
|
||||
isLoading={ isLoading }
|
||||
hash={ item.l1_transaction_hash }
|
||||
truncation="constant_long"
|
||||
fontSize="sm"
|
||||
lineHeight={ 5 }
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle">
|
||||
<AddressStringOrParam
|
||||
address={ item.user }
|
||||
isLoading={ isLoading }
|
||||
truncation="constant"
|
||||
noCopy
|
||||
/>
|
||||
</Td>
|
||||
<Td verticalAlign="middle" pr={ 12 }>
|
||||
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block"><span>{ timeAgo }</span></Skeleton>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
};
|
||||
|
||||
export default WithdrawalsTableItem;
|
||||
Reference in New Issue
Block a user