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
1274f1e4
Commit
1274f1e4
authored
Mar 07, 2024
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add user ops tx interpretation
parent
154cdad6
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
155 additions
and
17 deletions
+155
-17
.env.eth_goerli
configs/envs/.env.eth_goerli
+1
-0
resources.ts
lib/api/resources.ts
+5
-0
UserOp.tsx
ui/pages/UserOp.tsx
+2
-2
DetailsActionsWrapper.tsx
ui/shared/DetailsActionsWrapper.tsx
+5
-4
TokenEntity.tsx
ui/shared/entities/token/TokenEntity.tsx
+1
-1
TxInterpretation.tsx
ui/shared/tx/interpretation/TxInterpretation.tsx
+0
-0
utils.test.ts
ui/shared/tx/interpretation/utils.test.ts
+0
-0
utils.ts
ui/shared/tx/interpretation/utils.ts
+0
-0
TxSubHeading.tsx
ui/tx/TxSubHeading.tsx
+2
-2
TxState.pw.tsx_default_base-view-mobile-1.png
...reenshots__/TxState.pw.tsx_default_base-view-mobile-1.png
+0
-0
TxState.pw.tsx_mobile_base-view-mobile-1.png
...creenshots__/TxState.pw.tsx_mobile_base-view-mobile-1.png
+0
-0
TxDetailsActionsInterpretation.tsx
...tails/txDetailsActions/TxDetailsActionsInterpretation.tsx
+4
-5
TxDetailsActionsRaw.tsx
ui/tx/details/txDetailsActions/TxDetailsActionsRaw.tsx
+3
-3
UserOpDetails.tsx
ui/userOp/UserOpDetails.tsx
+4
-0
UserOpDetailsActions.tsx
ui/userOp/UserOpDetailsActions.tsx
+47
-0
UserOpSubHeading.tsx
ui/userOp/UserOpSubHeading.tsx
+81
-0
No files found.
configs/envs/.env.eth_goerli
View file @
1274f1e4
...
...
@@ -53,6 +53,7 @@ NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED='true'
NEXT_PUBLIC_HAS_BEACON_CHAIN=true
NEXT_PUBLIC_HAS_USER_OPS=true
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth-goerli.png?raw=true
\ No newline at end of file
lib/api/resources.ts
View file @
1274f1e4
...
...
@@ -662,6 +662,10 @@ export const RESOURCES = {
path
:
'
/api/v2/proxy/account-abstraction/accounts/:hash
'
,
pathParams
:
[
'
hash
'
as
const
],
},
user_op_interpretation
:
{
path
:
'
/api/v2/proxy/account-abstraction/operations/:hash/summary
'
,
pathParams
:
[
'
hash
'
as
const
],
},
// VALIDATORS
validators
:
{
...
...
@@ -881,6 +885,7 @@ Q extends 'domains_lookup' ? EnsDomainLookupResponse :
Q
extends
'
user_ops
'
?
UserOpsResponse
:
Q
extends
'
user_op
'
?
UserOp
:
Q
extends
'
user_ops_account
'
?
UserOpsAccount
:
Q
extends
'
user_op_interpretation
'
?
TxInterpretationResponse
:
never
;
/* eslint-enable @typescript-eslint/indent */
...
...
ui/pages/UserOp.tsx
View file @
1274f1e4
...
...
@@ -13,7 +13,6 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
USER_OP
}
from
'
stubs/userOps
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
UserOpEntity
from
'
ui/shared/entities/userOp/UserOpEntity
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
RoutedTabs
from
'
ui/shared/Tabs/RoutedTabs
'
;
import
TabsSkeleton
from
'
ui/shared/Tabs/TabsSkeleton
'
;
...
...
@@ -23,6 +22,7 @@ import TxTokenTransfer from 'ui/tx/TxTokenTransfer';
import
useTxQuery
from
'
ui/tx/useTxQuery
'
;
import
UserOpDetails
from
'
ui/userOp/UserOpDetails
'
;
import
UserOpRaw
from
'
ui/userOp/UserOpRaw
'
;
import
UserOpSubHeading
from
'
ui/userOp/UserOpSubHeading
'
;
const
UserOp
=
()
=>
{
const
router
=
useRouter
();
...
...
@@ -90,7 +90,7 @@ const UserOp = () => {
throwOnAbsentParamError
(
hash
);
throwOnResourceLoadError
(
userOpQuery
);
const
titleSecondRow
=
<
UserOp
Entity
hash=
{
hash
}
noLink
noCopy=
{
false
}
fontWeight=
{
500
}
fontFamily=
"heading"
/>;
const
titleSecondRow
=
<
UserOp
SubHeading
hash=
{
hash
}
/>;
return
(
<>
...
...
ui/
tx/details/txDetailsActions/Tx
DetailsActionsWrapper.tsx
→
ui/
shared/
DetailsActionsWrapper.tsx
View file @
1274f1e4
...
...
@@ -9,9 +9,10 @@ const SCROLL_GRADIENT_HEIGHT = 48;
type
Props
=
{
children
:
React
.
ReactNode
;
isLoading
?:
boolean
;
type
:
'
tx
'
|
'
user_op
'
;
}
const
TxDetailsActions
=
({
children
,
isLoading
}:
Props
)
=>
{
const
DetailsActionsWrapper
=
({
children
,
isLoading
,
type
}:
Props
)
=>
{
const
containerRef
=
React
.
useRef
<
HTMLDivElement
>
(
null
);
const
[
hasScroll
,
setHasScroll
]
=
React
.
useState
(
false
);
...
...
@@ -25,8 +26,8 @@ const TxDetailsActions = ({ children, isLoading }: Props) => {
return
(
<
DetailsInfoItem
title=
"Transaction action"
hint=
"Highlighted events of the transaction"
title=
{
`${ type === 'tx' ? 'Transaction' : 'User operation' } action`
}
hint=
{
`Highlighted events of the ${ type === 'tx' ? 'transaction' : 'user operation' }`
}
note=
{
hasScroll
?
'
Scroll to see more
'
:
undefined
}
position=
"relative"
isLoading=
{
isLoading
}
...
...
@@ -47,4 +48,4 @@ const TxDetailsActions = ({ children, isLoading }: Props) => {
);
};
export
default
React
.
memo
(
TxDetailsActions
);
export
default
React
.
memo
(
DetailsActionsWrapper
);
ui/shared/entities/token/TokenEntity.tsx
View file @
1274f1e4
...
...
@@ -66,7 +66,7 @@ type ContentProps = Omit<EntityBase.ContentBaseProps, 'text'> & Pick<EntityProps
const
Content
=
chakra
((
props
:
ContentProps
)
=>
{
const
nameString
=
[
!
props
.
onlySymbol
&&
(
props
.
token
.
name
??
'
Unnamed token
'
),
props
.
onlySymbol
&&
(
props
.
token
.
symbol
??
'
'
),
props
.
onlySymbol
&&
(
props
.
token
.
symbol
??
props
.
token
.
name
??
'
Unnamed token
'
),
props
.
token
.
symbol
&&
props
.
jointSymbol
&&
!
props
.
onlySymbol
&&
`(
${
props
.
token
.
symbol
}
)`
,
].
filter
(
Boolean
).
join
(
'
'
);
...
...
ui/tx/interpretation/TxInterpretation.tsx
→
ui/
shared/
tx/interpretation/TxInterpretation.tsx
View file @
1274f1e4
File moved
ui/tx/interpretation/utils.test.ts
→
ui/
shared/
tx/interpretation/utils.test.ts
View file @
1274f1e4
File moved
ui/tx/interpretation/utils.ts
→
ui/
shared/
tx/interpretation/utils.ts
View file @
1274f1e4
File moved
ui/tx/TxSubHeading.tsx
View file @
1274f1e4
...
...
@@ -5,10 +5,10 @@ import config from 'configs/app';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
TX_INTERPRETATION
}
from
'
stubs/txInterpretation
'
;
import
AccountActionsMenu
from
'
ui/shared/AccountActionsMenu/AccountActionsMenu
'
;
import
{
TX_ACTIONS_BLOCK_ID
}
from
'
ui/shared/DetailsActionsWrapper
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
import
NetworkExplorers
from
'
ui/shared/NetworkExplorers
'
;
import
{
TX_ACTIONS_BLOCK_ID
}
from
'
ui/tx/details/txDetailsActions/TxDetailsActionsWrapper
'
;
import
TxInterpretation
from
'
ui/tx/interpretation/TxInterpretation
'
;
import
TxInterpretation
from
'
ui/shared/tx/interpretation/TxInterpretation
'
;
import
type
{
TxQuery
}
from
'
./useTxQuery
'
;
...
...
ui/tx/__screenshots__/TxState.pw.tsx_default_base-view-mobile-1.png
View replaced file @
154cdad6
View file @
1274f1e4
55.3 KB
|
W:
|
H:
57 KB
|
W:
|
H:
2-up
Swipe
Onion skin
ui/tx/__screenshots__/TxState.pw.tsx_mobile_base-view-mobile-1.png
View replaced file @
154cdad6
View file @
1274f1e4
77.7 KB
|
W:
|
H:
80.1 KB
|
W:
|
H:
2-up
Swipe
Onion skin
ui/tx/details/txDetailsActions/TxDetailsActionsInterpretation.tsx
View file @
1274f1e4
...
...
@@ -2,10 +2,9 @@ import React from 'react';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
TX_INTERPRETATION
}
from
'
stubs/txInterpretation
'
;
import
DetailsActionsWrapper
from
'
ui/shared/DetailsActionsWrapper
'
;
import
DetailsInfoItemDivider
from
'
ui/shared/DetailsInfoItemDivider
'
;
import
TxInterpretation
from
'
ui/tx/interpretation/TxInterpretation
'
;
import
TxDetailsActionsWrapper
from
'
./TxDetailsActionsWrapper
'
;
import
TxInterpretation
from
'
ui/shared/tx/interpretation/TxInterpretation
'
;
interface
Props
{
hash
?:
string
;
...
...
@@ -30,7 +29,7 @@ const TxDetailsActionsInterpretation = ({ hash, isTxDataLoading }: Props) => {
return
(
<>
<
TxDetailsActionsWrapper
isLoading=
{
isTxDataLoading
||
txInterpretationQuery
.
isPlaceholderData
}
>
<
DetailsActionsWrapper
isLoading=
{
isTxDataLoading
||
txInterpretationQuery
.
isPlaceholderData
}
type=
"tx"
>
{
actions
.
map
((
action
,
index
:
number
)
=>
(
<
TxInterpretation
key=
{
index
}
...
...
@@ -39,7 +38,7 @@ const TxDetailsActionsInterpretation = ({ hash, isTxDataLoading }: Props) => {
/>
),
)
}
</
Tx
DetailsActionsWrapper
>
</
DetailsActionsWrapper
>
<
DetailsInfoItemDivider
/>
</>
);
...
...
ui/tx/details/txDetailsActions/TxDetailsActionsRaw.tsx
View file @
1274f1e4
...
...
@@ -2,10 +2,10 @@ import React from 'react';
import
type
{
TxAction
}
from
'
types/api/txAction
'
;
import
DetailsActionsWrapper
from
'
ui/shared/DetailsActionsWrapper
'
;
import
DetailsInfoItemDivider
from
'
ui/shared/DetailsInfoItemDivider
'
;
import
TxDetailsAction
from
'
./TxDetailsAction
'
;
import
TxDetailsActionsWrapper
from
'
./TxDetailsActionsWrapper
'
;
interface
Props
{
actions
:
Array
<
TxAction
>
;
...
...
@@ -15,9 +15,9 @@ interface Props {
const
TxDetailsActionsRaw
=
({
actions
,
isLoading
}:
Props
)
=>
{
return
(
<>
<
TxDetailsActionsWrapper
isLoading=
{
isLoading
}
>
<
DetailsActionsWrapper
isLoading=
{
isLoading
}
type=
"tx"
>
{
actions
.
map
((
action
,
index
:
number
)
=>
<
TxDetailsAction
key=
{
index
}
action=
{
action
}
/>)
}
</
Tx
DetailsActionsWrapper
>
</
DetailsActionsWrapper
>
<
DetailsInfoItemDivider
/>
</>
);
...
...
ui/userOp/UserOpDetails.tsx
View file @
1274f1e4
...
...
@@ -26,6 +26,8 @@ import UserOpSponsorType from 'ui/shared/userOps/UserOpSponsorType';
import
UserOpStatus
from
'
ui/shared/userOps/UserOpStatus
'
;
import
Utilization
from
'
ui/shared/Utilization/Utilization
'
;
import
UserOpDetailsActions
from
'
./UserOpDetailsActions
'
;
interface
Props
{
query
:
UseQueryResult
<
UserOp
,
ResourceError
>
;
}
...
...
@@ -168,6 +170,8 @@ const UserOpDetails = ({ query }: Props) => {
<
AddressStringOrParam
address=
{
data
.
entry_point
}
isLoading=
{
isPlaceholderData
}
/>
</
DetailsInfoItem
>
{
config
.
features
.
txInterpretation
.
isEnabled
&&
<
UserOpDetailsActions
hash=
{
data
.
hash
}
isUserOpDataLoading=
{
isPlaceholderData
}
/>
}
{
/* CUT */
}
<
GridItem
colSpan=
{
{
base
:
undefined
,
lg
:
2
}
}
>
<
Element
name=
{
CUT_LINK_NAME
}
>
...
...
ui/userOp/UserOpDetailsActions.tsx
0 → 100644
View file @
1274f1e4
import
React
from
'
react
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
TX_INTERPRETATION
}
from
'
stubs/txInterpretation
'
;
import
DetailsActionsWrapper
from
'
ui/shared/DetailsActionsWrapper
'
;
import
DetailsInfoItemDivider
from
'
ui/shared/DetailsInfoItemDivider
'
;
import
TxInterpretation
from
'
ui/shared/tx/interpretation/TxInterpretation
'
;
interface
Props
{
hash
?:
string
;
isUserOpDataLoading
:
boolean
;
}
const
TxDetailsActionsInterpretation
=
({
hash
,
isUserOpDataLoading
}:
Props
)
=>
{
const
interpretationQuery
=
useApiQuery
(
'
user_op_interpretation
'
,
{
pathParams
:
{
hash
},
queryOptions
:
{
enabled
:
Boolean
(
hash
)
&&
!
isUserOpDataLoading
,
placeholderData
:
TX_INTERPRETATION
,
refetchOnMount
:
false
,
},
});
const
actions
=
interpretationQuery
.
data
?.
data
.
summaries
;
if
(
!
actions
||
actions
.
length
<
2
)
{
return
null
;
}
return
(
<>
<
DetailsActionsWrapper
isLoading=
{
isUserOpDataLoading
||
interpretationQuery
.
isPlaceholderData
}
type=
"user_op"
>
{
actions
.
map
((
action
,
index
:
number
)
=>
(
<
TxInterpretation
key=
{
index
}
summary=
{
action
}
isLoading=
{
isUserOpDataLoading
||
interpretationQuery
.
isPlaceholderData
}
/>
),
)
}
</
DetailsActionsWrapper
>
<
DetailsInfoItemDivider
/>
</>
);
};
export
default
TxDetailsActionsInterpretation
;
ui/userOp/UserOpSubHeading.tsx
0 → 100644
View file @
1274f1e4
import
{
Flex
,
Link
}
from
'
@chakra-ui/react
'
;
// import type { UseQueryResult } from '@tanstack/react-query';
import
React
from
'
react
'
;
// import type { UserOp } from 'types/api/userOps';
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
{
TX_ACTIONS_BLOCK_ID
}
from
'
ui/shared/DetailsActionsWrapper
'
;
import
UserOpEntity
from
'
ui/shared/entities/userOp/UserOpEntity
'
;
import
TxInterpretation
from
'
ui/shared/tx/interpretation/TxInterpretation
'
;
type
Props
=
{
hash
?:
string
;
// userOpQuery: UseQueryResult<UserOp, ResourceError<unknown>>;
}
const
UserOpSubHeading
=
({
hash
}:
Props
)
=>
{
const
hasInterpretationFeature
=
config
.
features
.
txInterpretation
.
isEnabled
;
const
txInterpretationQuery
=
useApiQuery
(
'
user_op_interpretation
'
,
{
pathParams
:
{
hash
},
queryOptions
:
{
enabled
:
Boolean
(
hash
)
&&
hasInterpretationFeature
,
placeholderData
:
TX_INTERPRETATION
,
},
});
const
hasInterpretation
=
hasInterpretationFeature
&&
(
txInterpretationQuery
.
isPlaceholderData
||
Boolean
(
txInterpretationQuery
.
data
?.
data
.
summaries
.
length
));
const
hasViewAllInterpretationsLink
=
!
txInterpretationQuery
.
isPlaceholderData
&&
txInterpretationQuery
.
data
?.
data
.
summaries
&&
txInterpretationQuery
.
data
?.
data
.
summaries
.
length
>
1
;
if
(
hasInterpretation
)
{
return
(
<
Flex
mr=
{
{
base
:
0
,
lg
:
6
}
}
flexWrap=
"wrap"
alignItems=
"center"
>
<
TxInterpretation
summary=
{
txInterpretationQuery
.
data
?.
data
.
summaries
[
0
]
}
isLoading=
{
txInterpretationQuery
.
isPlaceholderData
}
fontSize=
"lg"
mr=
{
hasViewAllInterpretationsLink
?
3
:
0
}
/>
{
hasViewAllInterpretationsLink
&&
<
Link
href=
{
`#${ TX_ACTIONS_BLOCK_ID }`
}
>
View all
</
Link
>
}
</
Flex
>
);
// fallback will be added later
// } else if (hasInterpretationFeature && userOpQuery.data?.decoded_call_data.method_call && userOpQuery.data?.sender && userOpQuery.data?.to) {
// return (
// <TxInterpretation
// summary={{
// summary_template: `{sender_hash} called {method} on {receiver_hash}`,
// summary_template_variables: {
// sender_hash: {
// type: 'address',
// value: txQuery.data.from,
// },
// method: {
// type: 'method',
// value: txQuery.data.method,
// },
// receiver_hash: {
// type: 'address',
// value: txQuery.data.to,
// },
// },
// }}
// isLoading={ txQuery.isPlaceholderData }
// fontSize="lg"
// />
// );
}
else
{
return
<
UserOpEntity
hash=
{
hash
}
noLink
noCopy=
{
false
}
fontWeight=
{
500
}
fontFamily=
"heading"
/>;
}
};
export
default
UserOpSubHeading
;
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