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
341acb38
Commit
341acb38
authored
Feb 17, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user ops
parent
d13f87b4
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
215 additions
and
233 deletions
+215
-233
[hash].tsx
pages/op/[hash].tsx
+2
-2
ops.tsx
pages/ops.tsx
+2
-2
switch.tsx
toolkit/chakra/switch.tsx
+3
-2
UserOp.tsx
ui/pages/UserOp.tsx
+8
-8
ContainerWithScrollY.tsx
ui/shared/ContainerWithScrollY.tsx
+2
-2
DetailedInfo.tsx
ui/shared/DetailedInfo/DetailedInfo.tsx
+3
-3
UserOpEntity.tsx
ui/shared/entities/userOp/UserOpEntity.tsx
+2
-3
TxInterpretation.tsx
ui/shared/tx/interpretation/TxInterpretation.tsx
+1
-1
UserOpSponsorType.tsx
ui/shared/userOps/UserOpSponsorType.tsx
+3
-2
UserOpCallDataSwitch.tsx
ui/userOp/UserOpCallDataSwitch.tsx
+18
-7
UserOpDetails.tsx
ui/userOp/UserOpDetails.tsx
+167
-198
UserOpRaw.tsx
ui/userOp/UserOpRaw.tsx
+2
-2
UserOpSubHeading.tsx
ui/userOp/UserOpSubHeading.tsx
+2
-1
No files found.
pages/op/[hash].tsx
View file @
341acb38
...
...
@@ -5,12 +5,12 @@ import React from 'react';
import
type
{
Props
}
from
'
nextjs/getServerSideProps
'
;
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
//
const UserOp = dynamic(() => import('ui/pages/UserOp'), { ssr: false });
const
UserOp
=
dynamic
(()
=>
import
(
'
ui/pages/UserOp
'
),
{
ssr
:
false
});
const
Page
:
NextPage
<
Props
>
=
(
props
:
Props
)
=>
{
return
(
<
PageNextJs
pathname=
"/op/[hash]"
query=
{
props
.
query
}
>
{
/* <UserOp/> */
}
<
UserOp
/>
</
PageNextJs
>
);
};
...
...
pages/ops.tsx
View file @
341acb38
...
...
@@ -4,12 +4,12 @@ import React from 'react';
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
//
const UserOps = dynamic(() => import('ui/pages/UserOps'), { ssr: false });
const
UserOps
=
dynamic
(()
=>
import
(
'
ui/pages/UserOps
'
),
{
ssr
:
false
});
const
Page
:
NextPage
=
()
=>
{
return
(
<
PageNextJs
pathname=
"/ops"
>
{
/* <UserOps/> */
}
<
UserOps
/>
</
PageNextJs
>
);
};
...
...
toolkit/chakra/switch.tsx
View file @
341acb38
...
...
@@ -3,6 +3,7 @@ import * as React from 'react';
export
interface
SwitchProps
extends
ChakraSwitch
.
RootProps
{
inputProps
?:
React
.
InputHTMLAttributes
<
HTMLInputElement
>
;
labelProps
?:
ChakraSwitch
.
LabelProps
;
rootRef
?:
React
.
Ref
<
HTMLLabelElement
>
;
trackLabel
?:
{
on
:
React
.
ReactNode
;
off
:
React
.
ReactNode
};
thumbLabel
?:
{
on
:
React
.
ReactNode
;
off
:
React
.
ReactNode
};
...
...
@@ -10,7 +11,7 @@ export interface SwitchProps extends ChakraSwitch.RootProps {
export
const
Switch
=
React
.
forwardRef
<
HTMLInputElement
,
SwitchProps
>
(
function
Switch
(
props
,
ref
)
{
const
{
inputProps
,
children
,
rootRef
,
trackLabel
,
thumbLabel
,
...
rest
}
=
const
{
inputProps
,
children
,
rootRef
,
trackLabel
,
thumbLabel
,
labelProps
,
...
rest
}
=
props
;
return
(
...
...
@@ -31,7 +32,7 @@ export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
)
}
</
ChakraSwitch
.
Control
>
{
children
!=
null
&&
(
<
ChakraSwitch
.
Label
>
{
children
}
</
ChakraSwitch
.
Label
>
<
ChakraSwitch
.
Label
{
...
labelProps
}
>
{
children
}
</
ChakraSwitch
.
Label
>
)
}
</
ChakraSwitch
.
Root
>
);
...
...
ui/pages/UserOp.tsx
View file @
341acb38
...
...
@@ -2,9 +2,9 @@ import { inRange } from 'es-toolkit';
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
TabItemRegular
}
from
'
toolkit/components/AdaptiveTabs/types
'
;
import
type
{
Log
}
from
'
types/api/log
'
;
import
type
{
TokenTransfer
}
from
'
types/api/tokenTransfer
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/Tabs/types
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/contexts/app
'
;
...
...
@@ -12,11 +12,11 @@ import throwOnAbsentParamError from 'lib/errors/throwOnAbsentParamError';
import
throwOnResourceLoadError
from
'
lib/errors/throwOnResourceLoadError
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
USER_OP
}
from
'
stubs/userOps
'
;
import
RoutedTabs
from
'
toolkit/components/RoutedTabs/RoutedTabs
'
;
import
RoutedTabsSkeleton
from
'
toolkit/components/RoutedTabs/RoutedTabsSkeleton
'
;
import
useActiveTabFromQuery
from
'
toolkit/components/RoutedTabs/useActiveTabFromQuery
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
RoutedTabs
from
'
ui/shared/Tabs/RoutedTabs
'
;
import
TabsSkeleton
from
'
ui/shared/Tabs/TabsSkeleton
'
;
import
useTabIndexFromQuery
from
'
ui/shared/Tabs/useTabIndexFromQuery
'
;
import
TxLogs
from
'
ui/tx/TxLogs
'
;
import
TxTokenTransfer
from
'
ui/tx/TxTokenTransfer
'
;
import
useTxQuery
from
'
ui/tx/useTxQuery
'
;
...
...
@@ -65,7 +65,7 @@ const UserOp = () => {
}
},
[
userOpQuery
.
data
]);
const
tabs
:
Array
<
RoutedTab
>
=
React
.
useMemo
(()
=>
([
const
tabs
:
Array
<
TabItemRegular
>
=
React
.
useMemo
(()
=>
([
{
id
:
'
index
'
,
title
:
'
Details
'
,
component
:
<
UserOpDetails
query=
{
userOpQuery
}
/>
},
{
id
:
'
token_transfers
'
,
...
...
@@ -76,7 +76,7 @@ const UserOp = () => {
{
id
:
'
raw
'
,
title
:
'
Raw
'
,
component
:
<
UserOpRaw
rawData=
{
userOpQuery
.
data
?.
raw
}
isLoading=
{
userOpQuery
.
isPlaceholderData
}
/>
},
]),
[
userOpQuery
,
txQuery
,
filterTokenTransfersByLogIndex
,
filterLogsByLogIndex
]);
const
tabIndex
=
useTabIndex
FromQuery
(
tabs
);
const
activeTab
=
useActiveTab
FromQuery
(
tabs
);
const
backLink
=
React
.
useMemo
(()
=>
{
const
hasGoBackLink
=
appProps
.
referrer
&&
appProps
.
referrer
.
includes
(
'
/ops
'
);
...
...
@@ -106,8 +106,8 @@ const UserOp = () => {
/>
{
userOpQuery
.
isPlaceholderData
?
(
<>
<
TabsSkeleton
tabs=
{
tabs
}
mt=
{
6
}
/>
{
tabs
[
tabIndex
]
?.
component
}
<
Routed
TabsSkeleton
tabs=
{
tabs
}
mt=
{
6
}
/>
{
activeTab
?.
component
}
</>
)
:
<
RoutedTabs
tabs=
{
tabs
}
/>
}
...
...
ui/shared/ContainerWithScrollY.tsx
View file @
341acb38
import
type
{
FlexProps
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
Flex
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
export
interface
Props
extends
FlexProps
{
...
...
@@ -44,4 +44,4 @@ const ContainerWithScrollY = ({ gradientHeight, children, onScrollVisibilityChan
);
};
export
default
chakra
(
ContainerWithScrollY
)
;
export
default
ContainerWithScrollY
;
ui/shared/DetailedInfo/DetailedInfo.tsx
View file @
341acb38
...
...
@@ -73,11 +73,11 @@ export const ItemValue = ({ children, ...rest }: ItemValueProps) => {
);
};
export
const
ItemValueWithScroll
=
({
children
,
gradientHeight
,
onScrollVisibilityChange
,
className
}:
ContainerWithScrollY
.
Props
)
=>
{
export
const
ItemValueWithScroll
=
({
children
,
gradientHeight
,
onScrollVisibilityChange
,
...
rest
}:
ContainerWithScrollY
.
Props
)
=>
{
return
(
<
ItemValue
position=
"relative"
>
<
ItemValue
position=
"relative"
>
<
ContainerWithScrollY
.
default
className=
{
className
}
{
...
rest
}
gradientHeight=
{
gradientHeight
}
onScrollVisibilityChange=
{
onScrollVisibilityChange
}
>
...
...
ui/shared/entities/userOp/UserOpEntity.tsx
View file @
341acb38
...
...
@@ -63,13 +63,12 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
const
UserOpEntity
=
(
props
:
EntityProps
)
=>
{
const
partsProps
=
distributeEntityProps
(
props
);
const
content
=
<
Content
{
...
partsProps
.
content
}
/>;
return
(
<
Container
{
...
partsProps
.
container
}
>
<
Icon
{
...
partsProps
.
icon
}
/>
<
Link
{
...
partsProps
.
link
}
>
<
Content
{
...
partsProps
.
content
}
/>
</
Link
>
{
props
.
noLink
?
content
:
<
Link
{
...
partsProps
.
link
}
>
{
content
}
</
Link
>
}
<
Copy
{
...
partsProps
.
copy
}
/>
</
Container
>
);
...
...
ui/shared/tx/interpretation/TxInterpretation.tsx
View file @
341acb38
...
...
@@ -125,7 +125,7 @@ const TxInterpretationElementByType = (
case
'
method
'
:
{
return
(
<
Badge
color
Schem
e=
{
value
===
'
Multicall
'
?
'
teal
'
:
'
gray
'
}
color
Palett
e=
{
value
===
'
Multicall
'
?
'
teal
'
:
'
gray
'
}
truncated
ml=
{
1
}
mr=
{
2
}
...
...
ui/shared/userOps/UserOpSponsorType.tsx
View file @
341acb38
import
{
Tag
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
UserOpSponsorType
as
TUserOpSponsorType
}
from
'
types/api/userOps
'
;
import
{
Badge
}
from
'
toolkit/chakra/badge
'
;
type
Props
=
{
sponsorType
:
TUserOpSponsorType
;
};
...
...
@@ -22,7 +23,7 @@ const UserOpSponsorType = ({ sponsorType }: Props) => {
case
'
wallet_deposit
'
:
text
=
'
Wallet deposit
'
;
}
return
<
Tag
>
{
text
}
</
Tag
>;
return
<
Badge
>
{
text
}
</
Badge
>;
};
export
default
UserOpSponsorType
;
ui/userOp/UserOpCallDataSwitch.tsx
View file @
341acb38
import
{
chakra
,
F
ormLabel
,
FormControl
,
Switch
}
from
'
@chakra-ui/react
'
;
import
{
chakra
,
F
lex
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
Switch
}
from
'
toolkit/chakra/switch
'
;
import
Hint
from
'
ui/shared/Hint
'
;
interface
Props
{
...
...
@@ -22,13 +23,23 @@ const UserOpCallDataSwitch = ({ className, initialValue, isDisabled, onChange }:
},
[
onChange
]);
return
(
<
FormControl
className=
{
className
}
display=
"flex"
columnGap=
{
2
}
ml=
"auto"
w=
"fit-content"
>
<
FormLabel
htmlFor=
"isExternal"
fontSize=
"sm"
lineHeight=
{
5
}
fontWeight=
{
600
}
m=
{
0
}
>
Show external call data
</
FormLabel
>
<
Switch
id=
"isExternal"
isChecked=
{
isChecked
}
isDisabled=
{
isDisabled
}
onChange=
{
handleChange
}
/>
<
Flex
ml=
"auto"
alignItems=
"center"
gap=
{
2
}
>
<
Switch
className=
{
className
}
id=
"call-data-switch"
checked=
{
isChecked
}
disabled=
{
isDisabled
}
onCheckedChange=
{
handleChange
}
flexDirection=
"row-reverse"
size=
"md"
gap=
{
2
}
labelProps=
{
{
fontWeight
:
'
600
'
,
fontSize
:
'
sm
'
}
}
>
<
chakra
.
span
hideBelow=
"lg"
>
Show external call data
</
chakra
.
span
>
<
chakra
.
span
hideFrom=
"lg"
>
External call data
</
chakra
.
span
>
</
Switch
>
<
Hint
label=
"Inner call data is a predicted decoded call from this user operation"
/>
</
F
ormControl
>
</
F
lex
>
);
};
...
...
ui/userOp/UserOpDetails.tsx
View file @
341acb38
import
{
Grid
,
GridItem
,
Text
,
Link
}
from
'
@chakra-ui/react
'
;
import
{
Grid
,
GridItem
,
Text
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
import
{
scroller
,
Element
}
from
'
react-scroll
'
;
import
type
{
UserOp
}
from
'
types/api/userOps
'
;
...
...
@@ -12,12 +11,12 @@ import { WEI, WEI_IN_GWEI } from 'lib/consts';
import
throwOnResourceLoadError
from
'
lib/errors/throwOnResourceLoadError
'
;
import
{
space
}
from
'
lib/html-entities
'
;
import
{
currencyUnits
}
from
'
lib/units
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/skeleton
'
;
import
CutLinkDetails
from
'
toolkit/components/CutLink/CutLinkDetails
'
;
import
isCustomAppError
from
'
ui/shared/AppError/isCustomAppError
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
CurrencyValue
from
'
ui/shared/CurrencyValue
'
;
import
DataFetchAlert
from
'
ui/shared/DataFetchAlert
'
;
import
*
as
DetailedInfo
from
'
ui/shared/DetailedInfo/DetailedInfo
'
;
import
DetailedInfoTimestamp
from
'
ui/shared/DetailedInfo/DetailedInfoTimestamp
'
;
import
AddressStringOrParam
from
'
ui/shared/entities/address/AddressStringOrParam
'
;
import
BlockEntity
from
'
ui/shared/entities/block/BlockEntity
'
;
...
...
@@ -35,21 +34,9 @@ interface Props {
query
:
UseQueryResult
<
UserOp
,
ResourceError
>
;
}
const
CUT_LINK_NAME
=
'
UserOpDetails__cutLink
'
;
const
UserOpDetails
=
({
query
}:
Props
)
=>
{
const
[
isExpanded
,
setIsExpanded
]
=
React
.
useState
(
false
);
const
{
data
,
isPlaceholderData
,
isError
,
error
}
=
query
;
const
handleCutClick
=
React
.
useCallback
(()
=>
{
setIsExpanded
((
flag
)
=>
!
flag
);
scroller
.
scrollTo
(
CUT_LINK_NAME
,
{
duration
:
500
,
smooth
:
true
,
});
},
[]);
if
(
isError
)
{
if
(
error
?.
status
===
400
||
isCustomAppError
(
error
))
{
throwOnResourceLoadError
({
isError
,
error
});
...
...
@@ -76,7 +63,7 @@ const UserOpDetails = ({ query }: Props) => {
User operation hash
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
overflow=
"hidden"
>
<
Skeleton
loading=
{
isPlaceholderData
}
overflow=
"hidden"
>
<
UserOpEntity
hash=
{
data
.
hash
}
noIcon
noLink
noCopy=
{
false
}
/>
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -113,7 +100,7 @@ const UserOpDetails = ({ query }: Props) => {
wordBreak=
"break-all"
whiteSpace=
"normal"
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
<
Skeleton
loading=
{
isPlaceholderData
}
>
{
data
.
revert_reason
}
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -159,7 +146,7 @@ const UserOpDetails = ({ query }: Props) => {
Gas limit
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
<
Skeleton
loading=
{
isPlaceholderData
}
>
{
BigNumber
(
data
.
gas
).
toFormat
()
}
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -171,7 +158,7 @@ const UserOpDetails = ({ query }: Props) => {
Gas used
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
>
<
Skeleton
loading=
{
isPlaceholderData
}
>
{
BigNumber
(
data
.
gas_used
).
toFormat
()
}
</
Skeleton
>
<
Utilization
...
...
@@ -214,185 +201,167 @@ const UserOpDetails = ({ query }: Props) => {
{
config
.
features
.
txInterpretation
.
isEnabled
&&
<
UserOpDetailsActions
hash=
{
data
.
hash
}
isUserOpDataLoading=
{
isPlaceholderData
}
/>
}
{
/* CUT */
}
<
GridItem
colSpan=
{
{
base
:
undefined
,
lg
:
2
}
}
>
<
Element
name=
{
CUT_LINK_NAME
}
>
<
Skeleton
isLoaded=
{
!
isPlaceholderData
}
mt=
{
6
}
display=
"inline-block"
>
<
Link
fontSize=
"sm"
textDecorationLine=
"underline"
textDecorationStyle=
"dashed"
onClick=
{
handleCutClick
}
>
{
isExpanded
?
'
Hide details
'
:
'
View details
'
}
</
Link
>
</
Skeleton
>
</
Element
>
</
GridItem
>
{
/* ADDITIONAL INFO */
}
{
isExpanded
&&
!
isPlaceholderData
&&
(
<>
<
GridItem
colSpan=
{
{
base
:
undefined
,
lg
:
2
}
}
mt=
{
{
base
:
1
,
lg
:
4
}
}
/>
<
DetailedInfo
.
ItemLabel
hint=
"Gas limit for execution phase"
>
Call gas limit
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
BigNumber
(
data
.
call_gas_limit
).
toFormat
()
}
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Gas limit for verification phase"
>
Verification gas limit
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
BigNumber
(
data
.
verification_gas_limit
).
toFormat
()
}
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Gas to compensate the bundler"
>
Pre-verification gas
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
BigNumber
(
data
.
pre_verification_gas
).
toFormat
()
}
</
DetailedInfo
.
ItemValue
>
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
gas_fees
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Maximum fee per gas "
>
Max fee per gas
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Text
>
{
BigNumber
(
data
.
max_fee_per_gas
).
dividedBy
(
WEI
).
toFixed
()
}
{
currencyUnits
.
ether
}
</
Text
>
<
Text
variant=
"secondary"
whiteSpace=
"pre"
>
{
space
}
(
{
BigNumber
(
data
.
max_fee_per_gas
).
dividedBy
(
WEI_IN_GWEI
).
toFixed
()
}
{
currencyUnits
.
gwei
}
)
</
Text
>
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Maximum priority fee per gas"
>
Max priority fee per gas
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Text
>
{
BigNumber
(
data
.
max_priority_fee_per_gas
).
dividedBy
(
WEI
).
toFixed
()
}
{
currencyUnits
.
ether
}
</
Text
>
<
Text
variant=
"secondary"
whiteSpace=
"pre"
>
{
space
}
(
{
BigNumber
(
data
.
max_priority_fee_per_gas
).
dividedBy
(
WEI_IN_GWEI
).
toFixed
()
}
{
currencyUnits
.
gwei
}
)
</
Text
>
</
DetailedInfo
.
ItemValue
>
</>
)
}
<
DetailedInfo
.
ItemDivider
/>
{
data
.
aggregator
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Helper contract to validate an aggregated signature"
>
Aggregator
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
aggregator
}
/>
</
DetailedInfo
.
ItemValue
>
</>
)
}
{
data
.
aggregator_signature
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Aggregator signature"
>
Aggregator signature
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
data
.
aggregator_signature
}
</
DetailedInfo
.
ItemValue
>
</>
)
}
<
DetailedInfo
.
ItemLabel
hint=
"A node (block builder) that handles User operations"
>
Bundler
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
bundler
}
/>
</
DetailedInfo
.
ItemValue
>
{
data
.
factory
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Smart contract that deploys new smart contract wallets for users"
>
Factory
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
factory
}
/>
</
DetailedInfo
.
ItemValue
>
</>
)
}
{
data
.
paymaster
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Contract to sponsor the gas fees for User operations"
>
Paymaster
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
paymaster
}
/>
</
DetailedInfo
.
ItemValue
>
</>
)
}
<
DetailedInfo
.
ItemLabel
hint=
"Type of the gas fees sponsor"
>
Sponsor type
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
UserOpSponsorType
sponsorType=
{
data
.
sponsor_type
}
/>
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemDivider
/>
<
DetailedInfo
.
ItemLabel
hint=
"Used to validate a User operation along with the nonce during verification"
>
Signature
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
wordBreak=
"break-all"
whiteSpace=
"normal"
>
{
data
.
signature
}
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Anti-replay protection; also used as the salt for first-time account creation"
>
Nonce
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
wordBreak=
"break-all"
whiteSpace=
"normal"
>
{
data
.
nonce
}
</
DetailedInfo
.
ItemValue
>
<
UserOpCallData
data=
{
data
}
/>
<
UserOpDecodedCallData
data=
{
data
}
/>
</>
)
}
<
CutLinkDetails
loading=
{
isPlaceholderData
}
mt=
{
6
}
gridColumn=
{
{
base
:
undefined
,
lg
:
'
1 / 3
'
}
}
>
<
GridItem
colSpan=
{
{
base
:
undefined
,
lg
:
2
}
}
mt=
{
{
base
:
1
,
lg
:
4
}
}
/>
<
DetailedInfo
.
ItemLabel
hint=
"Gas limit for execution phase"
>
Call gas limit
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
BigNumber
(
data
.
call_gas_limit
).
toFormat
()
}
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Gas limit for verification phase"
>
Verification gas limit
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
BigNumber
(
data
.
verification_gas_limit
).
toFormat
()
}
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Gas to compensate the bundler"
>
Pre-verification gas
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
BigNumber
(
data
.
pre_verification_gas
).
toFormat
()
}
</
DetailedInfo
.
ItemValue
>
{
!
config
.
UI
.
views
.
tx
.
hiddenFields
?.
gas_fees
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Maximum fee per gas "
>
Max fee per gas
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Text
>
{
BigNumber
(
data
.
max_fee_per_gas
).
dividedBy
(
WEI
).
toFixed
()
}
{
currencyUnits
.
ether
}
</
Text
>
<
Text
color=
"text.secondary"
whiteSpace=
"pre"
>
{
space
}
(
{
BigNumber
(
data
.
max_fee_per_gas
).
dividedBy
(
WEI_IN_GWEI
).
toFixed
()
}
{
currencyUnits
.
gwei
}
)
</
Text
>
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Maximum priority fee per gas"
>
Max priority fee per gas
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Text
>
{
BigNumber
(
data
.
max_priority_fee_per_gas
).
dividedBy
(
WEI
).
toFixed
()
}
{
currencyUnits
.
ether
}
</
Text
>
<
Text
color=
"text.secondary"
whiteSpace=
"pre"
>
{
space
}
(
{
BigNumber
(
data
.
max_priority_fee_per_gas
).
dividedBy
(
WEI_IN_GWEI
).
toFixed
()
}
{
currencyUnits
.
gwei
}
)
</
Text
>
</
DetailedInfo
.
ItemValue
>
</>
)
}
<
DetailedInfo
.
ItemDivider
/>
{
data
.
aggregator
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Helper contract to validate an aggregated signature"
>
Aggregator
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
aggregator
}
/>
</
DetailedInfo
.
ItemValue
>
</>
)
}
{
data
.
aggregator_signature
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Aggregator signature"
>
Aggregator signature
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
{
data
.
aggregator_signature
}
</
DetailedInfo
.
ItemValue
>
</>
)
}
<
DetailedInfo
.
ItemLabel
hint=
"A node (block builder) that handles User operations"
>
Bundler
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
bundler
}
/>
</
DetailedInfo
.
ItemValue
>
{
data
.
factory
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Smart contract that deploys new smart contract wallets for users"
>
Factory
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
factory
}
/>
</
DetailedInfo
.
ItemValue
>
</>
)
}
{
data
.
paymaster
&&
(
<>
<
DetailedInfo
.
ItemLabel
hint=
"Contract to sponsor the gas fees for User operations"
>
Paymaster
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
AddressStringOrParam
address=
{
data
.
paymaster
}
/>
</
DetailedInfo
.
ItemValue
>
</>
)
}
<
DetailedInfo
.
ItemLabel
hint=
"Type of the gas fees sponsor"
>
Sponsor type
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
UserOpSponsorType
sponsorType=
{
data
.
sponsor_type
}
/>
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemDivider
/>
<
DetailedInfo
.
ItemLabel
hint=
"Used to validate a User operation along with the nonce during verification"
>
Signature
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
wordBreak=
"break-all"
whiteSpace=
"normal"
>
{
data
.
signature
}
</
DetailedInfo
.
ItemValue
>
<
DetailedInfo
.
ItemLabel
hint=
"Anti-replay protection; also used as the salt for first-time account creation"
>
Nonce
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
wordBreak=
"break-all"
whiteSpace=
"normal"
>
{
data
.
nonce
}
</
DetailedInfo
.
ItemValue
>
<
UserOpCallData
data=
{
data
}
/>
<
UserOpDecodedCallData
data=
{
data
}
/>
</
CutLinkDetails
>
</
Grid
>
);
};
...
...
ui/userOp/UserOpRaw.tsx
View file @
341acb38
...
...
@@ -2,7 +2,7 @@ import React from 'react';
import
type
{
UserOp
}
from
'
types/api/userOps
'
;
import
Skeleton
from
'
ui/shared/chakra/S
keleton
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/s
keleton
'
;
import
RawDataSnippet
from
'
ui/shared/RawDataSnippet
'
;
// order is taken from the ERC-4337 standard
...
...
@@ -27,7 +27,7 @@ const UserOpRaw = ({ rawData, isLoading }: Props) => {
return
res
;
},
{}
as
UserOp
[
'
raw
'
]),
undefined
,
4
);
return
<
Skeleton
isLoaded=
{
!
isLoading
}
><
RawDataSnippet
data=
{
text
}
/></
Skeleton
>;
return
<
Skeleton
loading=
{
isLoading
}
><
RawDataSnippet
data=
{
text
}
/></
Skeleton
>;
};
export
default
UserOpRaw
;
ui/userOp/UserOpSubHeading.tsx
View file @
341acb38
import
{
Flex
,
Link
}
from
'
@chakra-ui/react
'
;
import
{
Flex
}
from
'
@chakra-ui/react
'
;
// import type { UseQueryResult } from '@tanstack/react-query';
import
React
from
'
react
'
;
...
...
@@ -8,6 +8,7 @@ import config from 'configs/app';
// import type { ResourceError } from 'lib/api/resources';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
TX_INTERPRETATION
}
from
'
stubs/txInterpretation
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TX_ACTIONS_BLOCK_ID
}
from
'
ui/shared/DetailedInfo/DetailedInfoActionsWrapper
'
;
import
UserOpEntity
from
'
ui/shared/entities/userOp/UserOpEntity
'
;
import
TxInterpretation
from
'
ui/shared/tx/interpretation/TxInterpretation
'
;
...
...
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