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
411cd1dc
Commit
411cd1dc
authored
Jan 17, 2024
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
address user ops
parent
d1d615e6
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
212 additions
and
124 deletions
+212
-124
resources.ts
lib/api/resources.ts
+7
-2
userOps.ts
stubs/userOps.ts
+7
-1
userOps.ts
types/api/userOps.ts
+5
-0
AddressUserOps.tsx
ui/address/AddressUserOps.tsx
+35
-0
Address.tsx
ui/pages/Address.tsx
+24
-2
UserOps.tsx
ui/pages/UserOps.tsx
+3
-37
TxUserOps.tsx
ui/tx/TxUserOps.tsx
+4
-45
UserOpsContent.tsx
ui/userOps/UserOpsContent.tsx
+66
-0
UserOpsListItem.tsx
ui/userOps/UserOpsListItem.tsx
+26
-16
UserOpsTable.tsx
ui/userOps/UserOpsTable.tsx
+12
-4
UserOpsTableItem.tsx
ui/userOps/UserOpsTableItem.tsx
+23
-17
No files found.
lib/api/resources.ts
View file @
411cd1dc
...
@@ -77,7 +77,7 @@ import type {
...
@@ -77,7 +77,7 @@ import type {
import
type
{
TxInterpretationResponse
}
from
'
types/api/txInterpretation
'
;
import
type
{
TxInterpretationResponse
}
from
'
types/api/txInterpretation
'
;
import
type
{
TTxsFilters
}
from
'
types/api/txsFilters
'
;
import
type
{
TTxsFilters
}
from
'
types/api/txsFilters
'
;
import
type
{
TxStateChanges
}
from
'
types/api/txStateChanges
'
;
import
type
{
TxStateChanges
}
from
'
types/api/txStateChanges
'
;
import
type
{
UserOpsResponse
,
UserOp
,
UserOpsFilters
}
from
'
types/api/userOps
'
;
import
type
{
UserOpsResponse
,
UserOp
,
UserOpsFilters
,
UserOpsAccount
}
from
'
types/api/userOps
'
;
import
type
{
VerifiedContractsSorting
}
from
'
types/api/verifiedContracts
'
;
import
type
{
VerifiedContractsSorting
}
from
'
types/api/verifiedContracts
'
;
import
type
{
VisualizedContract
}
from
'
types/api/visualization
'
;
import
type
{
VisualizedContract
}
from
'
types/api/visualization
'
;
import
type
{
WithdrawalsResponse
,
WithdrawalsCounters
}
from
'
types/api/withdrawals
'
;
import
type
{
WithdrawalsResponse
,
WithdrawalsCounters
}
from
'
types/api/withdrawals
'
;
...
@@ -583,13 +583,17 @@ export const RESOURCES = {
...
@@ -583,13 +583,17 @@ export const RESOURCES = {
// USER OPS
// USER OPS
user_ops
:
{
user_ops
:
{
path
:
'
/api/v2/proxy/account-abstraction/operations
'
,
path
:
'
/api/v2/proxy/account-abstraction/operations
'
,
filterFields
:
[
'
transaction_hash
'
as
const
],
filterFields
:
[
'
transaction_hash
'
as
const
,
'
sender
'
as
const
],
},
},
user_op
:
{
user_op
:
{
path
:
'
/api/v2/proxy/account-abstraction/operations/:hash
'
,
path
:
'
/api/v2/proxy/account-abstraction/operations/:hash
'
,
pathParams
:
[
'
hash
'
as
const
],
pathParams
:
[
'
hash
'
as
const
],
},
},
user_ops_account
:
{
path
:
'
/api/v2/proxy/account-abstraction/accounts/:hash
'
,
pathParams
:
[
'
hash
'
as
const
],
},
// CONFIGS
// CONFIGS
config_backend_version
:
{
config_backend_version
:
{
...
@@ -768,6 +772,7 @@ Q extends 'domain_events' ? EnsDomainEventsResponse :
...
@@ -768,6 +772,7 @@ Q extends 'domain_events' ? EnsDomainEventsResponse :
Q
extends
'
domains_lookup
'
?
EnsDomainLookupResponse
:
Q
extends
'
domains_lookup
'
?
EnsDomainLookupResponse
:
Q
extends
'
user_ops
'
?
UserOpsResponse
:
Q
extends
'
user_ops
'
?
UserOpsResponse
:
Q
extends
'
user_op
'
?
UserOp
:
Q
extends
'
user_op
'
?
UserOp
:
Q
extends
'
user_ops_account
'
?
UserOpsAccount
:
never
;
never
;
/* eslint-enable @typescript-eslint/indent */
/* eslint-enable @typescript-eslint/indent */
...
...
stubs/userOps.ts
View file @
411cd1dc
import
type
{
UserOpsItem
,
UserOp
}
from
'
types/api/userOps
'
;
import
type
{
UserOpsItem
,
UserOp
,
UserOpsAccount
}
from
'
types/api/userOps
'
;
export
const
USER_OPS_ITEM
:
UserOpsItem
=
{
export
const
USER_OPS_ITEM
:
UserOpsItem
=
{
hash
:
'
0xb94fab8f31f83001a23e20b2ce3cdcfb284c57a64b9a073e0e09c018bc701978
'
,
hash
:
'
0xb94fab8f31f83001a23e20b2ce3cdcfb284c57a64b9a073e0e09c018bc701978
'
,
...
@@ -39,4 +39,10 @@ export const USER_OP: UserOp = {
...
@@ -39,4 +39,10 @@ export const USER_OP: UserOp = {
sponsor_type
:
'
paymaster_sponsor
'
,
sponsor_type
:
'
paymaster_sponsor
'
,
fee
:
'
17927001792700
'
,
fee
:
'
17927001792700
'
,
timestamp
:
'
1704994440
'
,
timestamp
:
'
1704994440
'
,
user_logs_count
:
1
,
user_logs_start_index
:
2
,
};
export
const
USER_OPS_ACCOUNT
:
UserOpsAccount
=
{
total_ops
:
1
,
};
};
types/api/userOps.ts
View file @
411cd1dc
...
@@ -53,4 +53,9 @@ export type UserOp = {
...
@@ -53,4 +53,9 @@ export type UserOp = {
export
type
UserOpsFilters
=
{
export
type
UserOpsFilters
=
{
transaction_hash
?:
string
;
transaction_hash
?:
string
;
sender
?:
string
;
}
export
type
UserOpsAccount
=
{
total_ops
:
number
;
}
}
ui/address/AddressUserOps.tsx
0 → 100644
View file @
411cd1dc
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
USER_OPS_ITEM
}
from
'
stubs/userOps
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
UserOpsContent
from
'
ui/userOps/UserOpsContent
'
;
type
Props
=
{
scrollRef
?:
React
.
RefObject
<
HTMLDivElement
>
;
}
const
AddressUserOps
=
({
scrollRef
}:
Props
)
=>
{
const
router
=
useRouter
();
const
hash
=
getQueryParamString
(
router
.
query
.
hash
);
const
userOpsQuery
=
useQueryWithPages
({
resourceName
:
'
user_ops
'
,
scrollRef
,
options
:
{
enabled
:
Boolean
(
hash
),
placeholderData
:
generateListStub
<
'
user_ops
'
>
(
USER_OPS_ITEM
,
50
,
{
next_page_params
:
{
page_token
:
'
10355938,0x5956a847d8089e254e02e5111cad6992b99ceb9e5c2dc4343fd53002834c4dc6
'
,
page_size
:
50
,
}
}),
},
filters
:
{
sender
:
hash
},
});
return
<
UserOpsContent
query=
{
userOpsQuery
}
showSender=
{
false
}
/>;
};
export
default
AddressUserOps
;
ui/pages/Address.tsx
View file @
411cd1dc
...
@@ -11,6 +11,7 @@ import useContractTabs from 'lib/hooks/useContractTabs';
...
@@ -11,6 +11,7 @@ import useContractTabs from 'lib/hooks/useContractTabs';
import
useIsSafeAddress
from
'
lib/hooks/useIsSafeAddress
'
;
import
useIsSafeAddress
from
'
lib/hooks/useIsSafeAddress
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
ADDRESS_INFO
,
ADDRESS_TABS_COUNTERS
}
from
'
stubs/address
'
;
import
{
ADDRESS_INFO
,
ADDRESS_TABS_COUNTERS
}
from
'
stubs/address
'
;
import
{
USER_OPS_ACCOUNT
}
from
'
stubs/userOps
'
;
import
AddressBlocksValidated
from
'
ui/address/AddressBlocksValidated
'
;
import
AddressBlocksValidated
from
'
ui/address/AddressBlocksValidated
'
;
import
AddressCoinBalance
from
'
ui/address/AddressCoinBalance
'
;
import
AddressCoinBalance
from
'
ui/address/AddressCoinBalance
'
;
import
AddressContract
from
'
ui/address/AddressContract
'
;
import
AddressContract
from
'
ui/address/AddressContract
'
;
...
@@ -20,6 +21,7 @@ import AddressLogs from 'ui/address/AddressLogs';
...
@@ -20,6 +21,7 @@ import AddressLogs from 'ui/address/AddressLogs';
import
AddressTokens
from
'
ui/address/AddressTokens
'
;
import
AddressTokens
from
'
ui/address/AddressTokens
'
;
import
AddressTokenTransfers
from
'
ui/address/AddressTokenTransfers
'
;
import
AddressTokenTransfers
from
'
ui/address/AddressTokenTransfers
'
;
import
AddressTxs
from
'
ui/address/AddressTxs
'
;
import
AddressTxs
from
'
ui/address/AddressTxs
'
;
import
AddressUserOps
from
'
ui/address/AddressUserOps
'
;
import
AddressWithdrawals
from
'
ui/address/AddressWithdrawals
'
;
import
AddressWithdrawals
from
'
ui/address/AddressWithdrawals
'
;
import
AddressFavoriteButton
from
'
ui/address/details/AddressFavoriteButton
'
;
import
AddressFavoriteButton
from
'
ui/address/details/AddressFavoriteButton
'
;
import
AddressQrCode
from
'
ui/address/details/AddressQrCode
'
;
import
AddressQrCode
from
'
ui/address/details/AddressQrCode
'
;
...
@@ -62,6 +64,14 @@ const AddressPageContent = () => {
...
@@ -62,6 +64,14 @@ const AddressPageContent = () => {
},
},
});
});
const
userOpsAccountQuery
=
useApiQuery
(
'
user_ops_account
'
,
{
pathParams
:
{
hash
},
queryOptions
:
{
enabled
:
Boolean
(
hash
),
placeholderData
:
USER_OPS_ACCOUNT
,
},
});
const
isSafeAddress
=
useIsSafeAddress
(
!
addressQuery
.
isPlaceholderData
&&
addressQuery
.
data
?.
is_contract
?
hash
:
undefined
);
const
isSafeAddress
=
useIsSafeAddress
(
!
addressQuery
.
isPlaceholderData
&&
addressQuery
.
data
?.
is_contract
?
hash
:
undefined
);
const
contractTabs
=
useContractTabs
(
addressQuery
.
data
);
const
contractTabs
=
useContractTabs
(
addressQuery
.
data
);
...
@@ -74,6 +84,14 @@ const AddressPageContent = () => {
...
@@ -74,6 +84,14 @@ const AddressPageContent = () => {
count
:
addressTabsCountersQuery
.
data
?.
transactions_count
,
count
:
addressTabsCountersQuery
.
data
?.
transactions_count
,
component
:
<
AddressTxs
scrollRef=
{
tabsScrollRef
}
/>,
component
:
<
AddressTxs
scrollRef=
{
tabsScrollRef
}
/>,
},
},
config
.
features
.
userOps
.
isEnabled
&&
Boolean
(
userOpsAccountQuery
.
data
?.
total_ops
)
?
{
id
:
'
user_ops
'
,
title
:
'
User operations
'
,
count
:
userOpsAccountQuery
.
data
?.
total_ops
,
component
:
<
AddressUserOps
/>,
}
:
undefined
,
config
.
features
.
beaconChain
.
isEnabled
&&
addressTabsCountersQuery
.
data
?.
withdrawals_count
?
config
.
features
.
beaconChain
.
isEnabled
&&
addressTabsCountersQuery
.
data
?.
withdrawals_count
?
{
{
id
:
'
withdrawals
'
,
id
:
'
withdrawals
'
,
...
@@ -140,7 +158,7 @@ const AddressPageContent = () => {
...
@@ -140,7 +158,7 @@ const AddressPageContent = () => {
subTabs
:
contractTabs
.
map
(
tab
=>
tab
.
id
),
subTabs
:
contractTabs
.
map
(
tab
=>
tab
.
id
),
}
:
undefined
,
}
:
undefined
,
].
filter
(
Boolean
);
].
filter
(
Boolean
);
},
[
addressQuery
.
data
,
contractTabs
,
addressTabsCountersQuery
.
data
]);
},
[
addressQuery
.
data
,
contractTabs
,
addressTabsCountersQuery
.
data
,
userOpsAccountQuery
.
data
]);
const
tags
=
(
const
tags
=
(
<
EntityTags
<
EntityTags
...
@@ -151,6 +169,7 @@ const AddressPageContent = () => {
...
@@ -151,6 +169,7 @@ const AddressPageContent = () => {
addressQuery
.
data
?.
implementation_address
?
{
label
:
'
proxy
'
,
display_name
:
'
Proxy
'
}
:
undefined
,
addressQuery
.
data
?.
implementation_address
?
{
label
:
'
proxy
'
,
display_name
:
'
Proxy
'
}
:
undefined
,
addressQuery
.
data
?.
token
?
{
label
:
'
token
'
,
display_name
:
'
Token
'
}
:
undefined
,
addressQuery
.
data
?.
token
?
{
label
:
'
token
'
,
display_name
:
'
Token
'
}
:
undefined
,
isSafeAddress
?
{
label
:
'
safe
'
,
display_name
:
'
Multisig: Safe
'
}
:
undefined
,
isSafeAddress
?
{
label
:
'
safe
'
,
display_name
:
'
Multisig: Safe
'
}
:
undefined
,
userOpsAccountQuery
.
data
?.
total_ops
?
{
label
:
'
user_ops_acc
'
,
display_name
:
'
Smart contract wallet
'
}
:
undefined
,
]
}
]
}
/>
/>
);
);
...
@@ -222,7 +241,10 @@ const AddressPageContent = () => {
...
@@ -222,7 +241,10 @@ const AddressPageContent = () => {
<
AddressDetails
addressQuery=
{
addressQuery
}
scrollRef=
{
tabsScrollRef
}
/>
<
AddressDetails
addressQuery=
{
addressQuery
}
scrollRef=
{
tabsScrollRef
}
/>
{
/* should stay before tabs to scroll up with pagination */
}
{
/* should stay before tabs to scroll up with pagination */
}
<
Box
ref=
{
tabsScrollRef
}
></
Box
>
<
Box
ref=
{
tabsScrollRef
}
></
Box
>
{
(
addressQuery
.
isPlaceholderData
||
addressTabsCountersQuery
.
isPlaceholderData
)
?
<
TabsSkeleton
tabs=
{
tabs
}
/>
:
content
}
{
(
addressQuery
.
isPlaceholderData
||
addressTabsCountersQuery
.
isPlaceholderData
||
userOpsAccountQuery
.
isPlaceholderData
)
?
<
TabsSkeleton
tabs=
{
tabs
}
/>
:
content
}
</>
</>
);
);
};
};
...
...
ui/pages/UserOps.tsx
View file @
411cd1dc
import
{
Hide
,
Show
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
USER_OPS_ITEM
}
from
'
stubs/userOps
'
;
import
{
USER_OPS_ITEM
}
from
'
stubs/userOps
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
UserOpsListItem
from
'
ui/userOps/UserOpsListItem
'
;
import
UserOpsContent
from
'
ui/userOps/UserOpsContent
'
;
import
UserOpsTable
from
'
ui/userOps/UserOpsTable
'
;
const
UserOps
=
()
=>
{
const
UserOps
=
()
=>
{
const
{
data
,
isError
,
isPlaceholderData
,
pagination
}
=
useQueryWithPages
({
const
query
=
useQueryWithPages
({
resourceName
:
'
user_ops
'
,
resourceName
:
'
user_ops
'
,
options
:
{
options
:
{
placeholderData
:
generateListStub
<
'
user_ops
'
>
(
USER_OPS_ITEM
,
50
,
{
next_page_params
:
{
placeholderData
:
generateListStub
<
'
user_ops
'
>
(
USER_OPS_ITEM
,
50
,
{
next_page_params
:
{
...
@@ -22,39 +17,10 @@ const UserOps = () => {
...
@@ -22,39 +17,10 @@ const UserOps = () => {
},
},
});
});
const
content
=
data
?.
items
?
(
<>
<
Show
below=
"lg"
ssr=
{
false
}
>
{
data
.
items
.
map
(((
item
,
index
)
=>
(
<
UserOpsListItem
key=
{
item
.
hash
+
(
isPlaceholderData
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
Show
>
<
Hide
below=
"lg"
ssr=
{
false
}
>
<
UserOpsTable
items=
{
data
.
items
}
top=
{
pagination
.
isVisible
?
80
:
0
}
isLoading=
{
isPlaceholderData
}
/>
</
Hide
>
</>
)
:
null
;
const
actionBar
=
pagination
.
isVisible
?
(
<
ActionBar
mt=
{
-
6
}
alignItems=
"center"
>
<
Pagination
ml=
"auto"
{
...
pagination
}
/>
</
ActionBar
>
)
:
null
;
return
(
return
(
<>
<>
<
PageTitle
title=
"User operations"
withTextAd
/>
<
PageTitle
title=
"User operations"
withTextAd
/>
<
DataListDisplay
<
UserOpsContent
query=
{
query
}
/>
isError=
{
isError
}
items=
{
data
?.
items
}
emptyText=
"There are no user operations."
content=
{
content
}
actionBar=
{
actionBar
}
/>
</>
</>
);
);
};
};
...
...
ui/tx/TxUserOps.tsx
View file @
411cd1dc
import
{
Hide
,
Show
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
SECOND
}
from
'
lib/consts
'
;
import
{
SECOND
}
from
'
lib/consts
'
;
import
{
USER_OPS_ITEM
}
from
'
stubs/userOps
'
;
import
{
USER_OPS_ITEM
}
from
'
stubs/userOps
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
TxPendingAlert
from
'
ui/tx/TxPendingAlert
'
;
import
TxPendingAlert
from
'
ui/tx/TxPendingAlert
'
;
import
TxSocketAlert
from
'
ui/tx/TxSocketAlert
'
;
import
TxSocketAlert
from
'
ui/tx/TxSocketAlert
'
;
import
useFetchTxInfo
from
'
ui/tx/useFetchTxInfo
'
;
import
useFetchTxInfo
from
'
ui/tx/useFetchTxInfo
'
;
import
UserOpsListItem
from
'
ui/userOps/UserOpsListItem
'
;
import
UserOpsContent
from
'
ui/userOps/UserOpsContent
'
;
import
UserOpsTable
from
'
ui/userOps/UserOpsTable
'
;
const
Tx
TokenTransfer
=
()
=>
{
const
Tx
UserOps
=
()
=>
{
const
txsInfo
=
useFetchTxInfo
({
updateDelay
:
5
*
SECOND
});
const
txsInfo
=
useFetchTxInfo
({
updateDelay
:
5
*
SECOND
});
const
userOpsQuery
=
useQueryWithPages
({
const
userOpsQuery
=
useQueryWithPages
({
...
@@ -32,42 +26,7 @@ const TxTokenTransfer = () => {
...
@@ -32,42 +26,7 @@ const TxTokenTransfer = () => {
return
txsInfo
.
socketStatus
?
<
TxSocketAlert
status=
{
txsInfo
.
socketStatus
}
/>
:
<
TxPendingAlert
/>;
return
txsInfo
.
socketStatus
?
<
TxSocketAlert
status=
{
txsInfo
.
socketStatus
}
/>
:
<
TxPendingAlert
/>;
}
}
if
(
txsInfo
.
isError
||
userOpsQuery
.
isError
)
{
return
<
UserOpsContent
query=
{
userOpsQuery
}
showTx=
{
false
}
/>;
return
<
DataFetchAlert
/>;
}
const
content
=
userOpsQuery
.
data
?.
items
?
(
<>
<
Hide
below=
"lg"
ssr=
{
false
}
>
<
UserOpsTable
items=
{
userOpsQuery
.
data
?.
items
}
top=
{
userOpsQuery
.
pagination
.
isVisible
?
0
:
80
}
isLoading=
{
userOpsQuery
.
isPlaceholderData
}
/>
</
Hide
>
<
Show
below=
"lg"
ssr=
{
false
}
>
{
userOpsQuery
.
data
.
items
.
map
(((
item
,
index
)
=>
(
<
UserOpsListItem
key=
{
item
.
hash
+
(
userOpsQuery
.
isPlaceholderData
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
userOpsQuery
.
isPlaceholderData
}
/>
)))
}
</
Show
>
</>
)
:
null
;
const
actionBar
=
userOpsQuery
.
pagination
.
isVisible
?
(
<
ActionBar
mt=
{
-
6
}
alignItems=
"center"
>
<
Pagination
ml=
"auto"
{
...
userOpsQuery
.
pagination
}
/>
</
ActionBar
>
)
:
null
;
return
(
<
DataListDisplay
isError=
{
txsInfo
.
isError
||
userOpsQuery
.
isError
}
items=
{
userOpsQuery
.
data
?.
items
}
emptyText=
"There are no user operations."
content=
{
content
}
actionBar=
{
actionBar
}
/>
);
};
};
export
default
Tx
TokenTransfer
;
export
default
Tx
UserOps
;
ui/userOps/UserOpsContent.tsx
0 → 100644
View file @
411cd1dc
import
{
Hide
,
Show
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
ActionBar
from
'
ui/shared/ActionBar
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
DataListDisplay
from
'
ui/shared/DataListDisplay
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
type
{
QueryWithPagesResult
}
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
UserOpsListItem
from
'
ui/userOps/UserOpsListItem
'
;
import
UserOpsTable
from
'
ui/userOps/UserOpsTable
'
;
type
Props
=
{
query
:
QueryWithPagesResult
<
'
user_ops
'
>
;
showTx
?:
boolean
;
showSender
?:
boolean
;
};
const
UserOpsContent
=
({
query
,
showTx
=
true
,
showSender
=
true
}:
Props
)
=>
{
if
(
query
.
isError
)
{
return
<
DataFetchAlert
/>;
}
const
content
=
query
.
data
?.
items
?
(
<>
<
Hide
below=
"lg"
ssr=
{
false
}
>
<
UserOpsTable
items=
{
query
.
data
.
items
}
top=
{
query
.
pagination
.
isVisible
?
0
:
80
}
isLoading=
{
query
.
isPlaceholderData
}
showTx=
{
showTx
}
showSender=
{
showSender
}
/>
</
Hide
>
<
Show
below=
"lg"
ssr=
{
false
}
>
{
query
.
data
.
items
.
map
(((
item
,
index
)
=>
(
<
UserOpsListItem
key=
{
item
.
hash
+
(
query
.
isPlaceholderData
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
query
.
isPlaceholderData
}
showTx=
{
showTx
}
showSender=
{
showSender
}
/>
)))
}
</
Show
>
</>
)
:
null
;
const
actionBar
=
query
.
pagination
.
isVisible
?
(
<
ActionBar
mt=
{
-
6
}
alignItems=
"center"
>
<
Pagination
ml=
"auto"
{
...
query
.
pagination
}
/>
</
ActionBar
>
)
:
null
;
return
(
<
DataListDisplay
isError=
{
query
.
isError
}
items=
{
query
.
data
?.
items
}
emptyText=
"There are no user operations."
content=
{
content
}
actionBar=
{
actionBar
}
/>
);
};
export
default
UserOpsContent
;
ui/userOps/UserOpsListItem.tsx
View file @
411cd1dc
...
@@ -16,9 +16,11 @@ import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
...
@@ -16,9 +16,11 @@ import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
type
Props
=
{
type
Props
=
{
item
:
UserOpsItem
;
item
:
UserOpsItem
;
isLoading
?:
boolean
;
isLoading
?:
boolean
;
showTx
:
boolean
;
showSender
:
boolean
;
};
};
const
UserOpsListItem
=
({
item
,
isLoading
}:
Props
)
=>
{
const
UserOpsListItem
=
({
item
,
isLoading
,
showTx
,
showSender
}:
Props
)
=>
{
// format will be fixed on the back-end
// format will be fixed on the back-end
const
timeAgo
=
dayjs
(
Number
(
item
.
timestamp
)
*
1000
).
fromNow
();
const
timeAgo
=
dayjs
(
Number
(
item
.
timestamp
)
*
1000
).
fromNow
();
...
@@ -40,22 +42,30 @@ const UserOpsListItem = ({ item, isLoading }: Props) => {
...
@@ -40,22 +42,30 @@ const UserOpsListItem = ({ item, isLoading }: Props) => {
<
UserOpStatus
status=
{
item
.
status
}
isLoading=
{
isLoading
}
/>
<
UserOpStatus
status=
{
item
.
status
}
isLoading=
{
isLoading
}
/>
</
ListItemMobileGrid
.
Value
>
</
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Sender
</
ListItemMobileGrid
.
Label
>
{
showSender
&&
(
<
ListItemMobileGrid
.
Value
>
<>
<
UserOpsAddress
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Sender
</
ListItemMobileGrid
.
Label
>
address=
{
item
.
address
}
<
ListItemMobileGrid
.
Value
>
isLoading=
{
isLoading
}
<
UserOpsAddress
/>
address=
{
item
.
address
}
</
ListItemMobileGrid
.
Value
>
isLoading=
{
isLoading
}
/>
</
ListItemMobileGrid
.
Value
>
</>
)
}
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Tx hash
</
ListItemMobileGrid
.
Label
>
{
showTx
&&
(
<
ListItemMobileGrid
.
Value
>
<>
<
TxEntity
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Tx hash
</
ListItemMobileGrid
.
Label
>
hash=
{
item
.
transaction_hash
}
<
ListItemMobileGrid
.
Value
>
isLoading=
{
isLoading
}
<
TxEntity
noIcon
hash=
{
item
.
transaction_hash
}
/>
isLoading=
{
isLoading
}
</
ListItemMobileGrid
.
Value
>
noIcon
/>
</
ListItemMobileGrid
.
Value
>
</>
)
}
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Block
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Block
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
ListItemMobileGrid
.
Value
>
...
...
ui/userOps/UserOpsTable.tsx
View file @
411cd1dc
...
@@ -12,9 +12,11 @@ import UserOpsTableItem from './UserOpsTableItem';
...
@@ -12,9 +12,11 @@ import UserOpsTableItem from './UserOpsTableItem';
items
:
Array
<
UserOpsItem
>
;
items
:
Array
<
UserOpsItem
>
;
isLoading
?:
boolean
;
isLoading
?:
boolean
;
top
:
number
;
top
:
number
;
showTx
:
boolean
;
showSender
:
boolean
;
};
};
const
UserOpsTable
=
({
items
,
isLoading
,
top
}:
Props
)
=>
{
const
UserOpsTable
=
({
items
,
isLoading
,
top
,
showTx
,
showSender
}:
Props
)
=>
{
return
(
return
(
<
Table
variant=
"simple"
size=
"sm"
>
<
Table
variant=
"simple"
size=
"sm"
>
<
Thead
top=
{
top
}
>
<
Thead
top=
{
top
}
>
...
@@ -22,15 +24,21 @@ const UserOpsTable = ({ items, isLoading, top }: Props) => {
...
@@ -22,15 +24,21 @@ const UserOpsTable = ({ items, isLoading, top }: Props) => {
<
Th
w=
"60%"
>
User op hash
</
Th
>
<
Th
w=
"60%"
>
User op hash
</
Th
>
<
Th
w=
"110px"
>
Age
</
Th
>
<
Th
w=
"110px"
>
Age
</
Th
>
<
Th
w=
"140px"
>
Status
</
Th
>
<
Th
w=
"140px"
>
Status
</
Th
>
<
Th
w=
"160px"
>
Sender
</
Th
>
{
showSender
&&
<
Th
w=
"160px"
>
Sender
</
Th
>
}
<
Th
w=
"160px"
>
Tx hash
</
Th
>
{
showTx
&&
<
Th
w=
"160px"
>
Tx hash
</
Th
>
}
<
Th
w=
"40%"
>
Block
</
Th
>
<
Th
w=
"40%"
>
Block
</
Th
>
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
tx_fee
&&
<
Th
w=
"120px"
isNumeric
>
{
`Fee ${ config.chain.currency.symbol }`
}
</
Th
>
}
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
tx_fee
&&
<
Th
w=
"120px"
isNumeric
>
{
`Fee ${ config.chain.currency.symbol }`
}
</
Th
>
}
</
Tr
>
</
Tr
>
</
Thead
>
</
Thead
>
<
Tbody
>
<
Tbody
>
{
items
.
map
((
item
,
index
)
=>
(
{
items
.
map
((
item
,
index
)
=>
(
<
UserOpsTableItem
key=
{
(
isLoading
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
isLoading
}
/>
<
UserOpsTableItem
key=
{
(
isLoading
?
String
(
index
)
:
''
)
}
item=
{
item
}
isLoading=
{
isLoading
}
showSender=
{
showSender
}
showTx=
{
showTx
}
/>
))
}
))
}
</
Tbody
>
</
Tbody
>
</
Table
>
</
Table
>
...
...
ui/userOps/UserOpsTableItem.tsx
View file @
411cd1dc
...
@@ -15,9 +15,11 @@ import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
...
@@ -15,9 +15,11 @@ import UserOpStatus from 'ui/shared/userOps/UserOpStatus';
type
Props
=
{
type
Props
=
{
item
:
UserOpsItem
;
item
:
UserOpsItem
;
isLoading
?:
boolean
;
isLoading
?:
boolean
;
showTx
:
boolean
;
showSender
:
boolean
;
};
};
const
WithdrawalsTableItem
=
({
item
,
isLoading
}:
Props
)
=>
{
const
UserOpsTableItem
=
({
item
,
isLoading
,
showTx
,
showSender
}:
Props
)
=>
{
// will be fixed on the back-end
// will be fixed on the back-end
const
timeAgo
=
dayjs
(
Number
(
item
.
timestamp
)
*
1000
).
fromNow
();
const
timeAgo
=
dayjs
(
Number
(
item
.
timestamp
)
*
1000
).
fromNow
();
...
@@ -32,21 +34,25 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
...
@@ -32,21 +34,25 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
<
Td
verticalAlign=
"middle"
>
<
Td
verticalAlign=
"middle"
>
<
UserOpStatus
status=
{
item
.
status
}
isLoading=
{
isLoading
}
/>
<
UserOpStatus
status=
{
item
.
status
}
isLoading=
{
isLoading
}
/>
</
Td
>
</
Td
>
<
Td
verticalAlign=
"middle"
>
{
showSender
&&
(
<
UserOpsAddress
<
Td
verticalAlign=
"middle"
>
address=
{
item
.
address
}
<
UserOpsAddress
isLoading=
{
isLoading
}
address=
{
item
.
address
}
truncation=
"constant"
isLoading=
{
isLoading
}
/>
truncation=
"constant"
</
Td
>
/>
<
Td
verticalAlign=
"middle"
>
</
Td
>
<
TxEntity
)
}
hash=
{
item
.
transaction_hash
}
{
showTx
&&
(
isLoading=
{
isLoading
}
<
Td
verticalAlign=
"middle"
>
truncation=
"constant"
<
TxEntity
noIcon
hash=
{
item
.
transaction_hash
}
/>
isLoading=
{
isLoading
}
</
Td
>
truncation=
"constant"
noIcon
/>
</
Td
>
)
}
<
Td
verticalAlign=
"middle"
>
<
Td
verticalAlign=
"middle"
>
<
BlockEntity
<
BlockEntity
number=
{
item
.
block_number
}
number=
{
item
.
block_number
}
...
@@ -65,4 +71,4 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
...
@@ -65,4 +71,4 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
);
);
};
};
export
default
Withdrawal
sTableItem
;
export
default
UserOp
sTableItem
;
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