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
898cfafa
Commit
898cfafa
authored
Dec 21, 2023
by
isstuev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add transaction interpretations
parent
9facb82d
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
352 additions
and
6 deletions
+352
-6
index.ts
configs/app/features/index.ts
+1
-0
txInterpretation.ts
configs/app/features/txInterpretation.ts
+21
-0
.env.eth
configs/envs/.env.eth
+1
-0
schema.ts
deploy/tools/envs-validator/schema.ts
+1
-0
ENVS.md
docs/ENVS.md
+11
-0
action.svg
icons/action.svg
+3
-0
resources.ts
lib/api/resources.ts
+6
-0
txInterpretation.ts
mocks/txs/txInterpretation.ts
+45
-0
tx.ts
stubs/tx.ts
+29
-0
txInterpretation.ts
types/api/txInterpretation.ts
+47
-0
Transaction.tsx
ui/pages/Transaction.tsx
+26
-6
TxInterpretation.pw.tsx
ui/tx/interpretation/TxInterpretation.pw.tsx
+21
-0
TxInterpretation.tsx
ui/tx/interpretation/TxInterpretation.tsx
+66
-0
TxInterpretation.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png
...n.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png
+0
-0
TxInterpretation.pw.tsx_default_base-view-mobile-dark-mode-1.png
...pretation.pw.tsx_default_base-view-mobile-dark-mode-1.png
+0
-0
TxInterpretation.pw.tsx_mobile_base-view-mobile-dark-mode-1.png
...rpretation.pw.tsx_mobile_base-view-mobile-dark-mode-1.png
+0
-0
utils.test.ts
ui/tx/interpretation/utils.test.ts
+43
-0
utils.ts
ui/tx/interpretation/utils.ts
+31
-0
No files found.
configs/app/features/index.ts
View file @
898cfafa
...
@@ -17,6 +17,7 @@ export { default as sentry } from './sentry';
...
@@ -17,6 +17,7 @@ export { default as sentry } from './sentry';
export
{
default
as
sol2uml
}
from
'
./sol2uml
'
;
export
{
default
as
sol2uml
}
from
'
./sol2uml
'
;
export
{
default
as
stats
}
from
'
./stats
'
;
export
{
default
as
stats
}
from
'
./stats
'
;
export
{
default
as
suave
}
from
'
./suave
'
;
export
{
default
as
suave
}
from
'
./suave
'
;
export
{
default
as
txInterpretation
}
from
'
./txInterpretation
'
;
export
{
default
as
web3Wallet
}
from
'
./web3Wallet
'
;
export
{
default
as
web3Wallet
}
from
'
./web3Wallet
'
;
export
{
default
as
verifiedTokens
}
from
'
./verifiedTokens
'
;
export
{
default
as
verifiedTokens
}
from
'
./verifiedTokens
'
;
export
{
default
as
zkEvmRollup
}
from
'
./zkEvmRollup
'
;
export
{
default
as
zkEvmRollup
}
from
'
./zkEvmRollup
'
;
configs/app/features/txInterpretation.ts
0 → 100644
View file @
898cfafa
import
type
{
Feature
}
from
'
./types
'
;
import
{
getEnvValue
}
from
'
../utils
'
;
const
title
=
'
Transaction interpretation
'
;
const
config
:
Feature
<
{
isEnabled
:
true
}
>
=
(()
=>
{
if
(
getEnvValue
(
'
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED
'
)
===
'
true
'
)
{
return
Object
.
freeze
({
title
,
isEnabled
:
true
,
});
}
return
Object
.
freeze
({
title
,
isEnabled
:
false
,
});
})();
export
default
config
;
configs/envs/.env.eth
View file @
898cfafa
...
@@ -42,6 +42,7 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s.blockscout.com
...
@@ -42,6 +42,7 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED=true
#meta
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true
deploy/tools/envs-validator/schema.ts
View file @
898cfafa
...
@@ -438,6 +438,7 @@ const schema = yup
...
@@ -438,6 +438,7 @@ const schema = yup
return
isNoneSchema
.
isValidSync
(
data
)
||
isArrayOfWalletsSchema
.
isValidSync
(
data
);
return
isNoneSchema
.
isValidSync
(
data
)
||
isArrayOfWalletsSchema
.
isValidSync
(
data
);
}),
}),
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET
:
yup
.
boolean
(),
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET
:
yup
.
boolean
(),
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED
:
yup
.
boolean
(),
NEXT_PUBLIC_AD_TEXT_PROVIDER
:
yup
.
string
<
AdTextProviders
>
().
oneOf
(
SUPPORTED_AD_TEXT_PROVIDERS
),
NEXT_PUBLIC_AD_TEXT_PROVIDER
:
yup
.
string
<
AdTextProviders
>
().
oneOf
(
SUPPORTED_AD_TEXT_PROVIDERS
),
NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE
:
yup
.
boolean
(),
NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE
:
yup
.
boolean
(),
NEXT_PUBLIC_OG_DESCRIPTION
:
yup
.
string
(),
NEXT_PUBLIC_OG_DESCRIPTION
:
yup
.
string
(),
...
...
docs/ENVS.md
View file @
898cfafa
...
@@ -44,6 +44,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
...
@@ -44,6 +44,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
-
[
Solidity to UML diagrams
](
ENVS.md#solidity-to-uml-diagrams
)
-
[
Solidity to UML diagrams
](
ENVS.md#solidity-to-uml-diagrams
)
-
[
Blockchain statistics
](
ENVS.md#blockchain-statistics
)
-
[
Blockchain statistics
](
ENVS.md#blockchain-statistics
)
-
[
Web3 wallet integration
](
ENVS.md#web3-wallet-integration-add-token-or-network-to-the-wallet
)
(
add
token or network to the wallet)
-
[
Web3 wallet integration
](
ENVS.md#web3-wallet-integration-add-token-or-network-to-the-wallet
)
(
add
token or network to the wallet)
-
[
Transaction interpretation
](
ENVS.md#transaction-interpretation
)
-
[
Verified tokens info
](
ENVS.md#verified-tokens-info
)
-
[
Verified tokens info
](
ENVS.md#verified-tokens-info
)
-
[
Bridged tokens
](
ENVS.md#bridged-tokens
)
-
[
Bridged tokens
](
ENVS.md#bridged-tokens
)
-
[
Safe{Core} address tags
](
ENVS.md#safecore-address-tags
)
-
[
Safe{Core} address tags
](
ENVS.md#safecore-address-tags
)
...
@@ -473,6 +474,16 @@ This feature is **enabled by default** with the `['metamask']` value. To switch
...
@@ -473,6 +474,16 @@ This feature is **enabled by default** with the `['metamask']` value. To switch
### Transaction interpretation
<!-- Nikita will provide feature description -->
| Variable | Type| Description | Compulsoriness | Default value | Example value |
| --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_TRANSACTION_INTERPRETATION_ENABLED |
`boolean`
| Set to
`true`
to enable transaction interpretation | - | - |
`true`
|
### Verified tokens info
### Verified tokens info
| Variable | Type| Description | Compulsoriness | Default value | Example value |
| Variable | Type| Description | Compulsoriness | Default value | Example value |
...
...
icons/action.svg
0 → 100644
View file @
898cfafa
<svg
xmlns=
"http://www.w3.org/2000/svg"
fill=
"none"
viewBox=
"0 0 20 20"
>
<path
fill=
"currentColor"
d=
"M10.833 7.5H17.5L9.167 20v-7.5H3.333l7.5-12.5v7.5ZM9.167 9.167v-3.15l-2.89 4.816h4.556v3.662l3.553-5.328h-5.22Z"
/>
</svg>
lib/api/resources.ts
View file @
898cfafa
...
@@ -65,6 +65,7 @@ import type {
...
@@ -65,6 +65,7 @@ import type {
TransactionsResponseWatchlist
,
TransactionsResponseWatchlist
,
TransactionsSorting
,
TransactionsSorting
,
}
from
'
types/api/transaction
'
;
}
from
'
types/api/transaction
'
;
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
{
VerifiedContractsSorting
}
from
'
types/api/verifiedContracts
'
;
import
type
{
VerifiedContractsSorting
}
from
'
types/api/verifiedContracts
'
;
...
@@ -246,6 +247,10 @@ export const RESOURCES = {
...
@@ -246,6 +247,10 @@ export const RESOURCES = {
pathParams
:
[
'
hash
'
as
const
],
pathParams
:
[
'
hash
'
as
const
],
filterFields
:
[],
filterFields
:
[],
},
},
tx_interpretation
:
{
path
:
'
/api/v2/transactions/:hash/summary
'
,
pathParams
:
[
'
hash
'
as
const
],
},
withdrawals
:
{
withdrawals
:
{
path
:
'
/api/v2/withdrawals
'
,
path
:
'
/api/v2/withdrawals
'
,
filterFields
:
[],
filterFields
:
[],
...
@@ -651,6 +656,7 @@ Q extends 'tx_logs' ? LogsResponseTx :
...
@@ -651,6 +656,7 @@ Q extends 'tx_logs' ? LogsResponseTx :
Q
extends
'
tx_token_transfers
'
?
TokenTransferResponse
:
Q
extends
'
tx_token_transfers
'
?
TokenTransferResponse
:
Q
extends
'
tx_raw_trace
'
?
RawTracesResponse
:
Q
extends
'
tx_raw_trace
'
?
RawTracesResponse
:
Q
extends
'
tx_state_changes
'
?
TxStateChanges
:
Q
extends
'
tx_state_changes
'
?
TxStateChanges
:
Q
extends
'
tx_interpretation
'
?
TxInterpretationResponse
:
Q
extends
'
addresses
'
?
AddressesResponse
:
Q
extends
'
addresses
'
?
AddressesResponse
:
Q
extends
'
address
'
?
Address
:
Q
extends
'
address
'
?
Address
:
Q
extends
'
address_counters
'
?
AddressCounters
:
Q
extends
'
address_counters
'
?
AddressCounters
:
...
...
mocks/txs/txInterpretation.ts
0 → 100644
View file @
898cfafa
import
type
{
TxInterpretationResponse
}
from
'
types/api/txInterpretation
'
;
export
const
txInterpretation
:
TxInterpretationResponse
=
{
data
:
{
summaries
:
[
{
summary_template
:
`{action_type} {amount} {token} to {to_address} on {timestamp}`
,
summary_template_variables
:
{
action_type
:
{
type
:
'
string
'
,
value
:
'
Transfer
'
},
amount
:
{
type
:
'
currency
'
,
value
:
'
100
'
},
token
:
{
type
:
'
token
'
,
value
:
{
name
:
'
Duck
'
,
type
:
'
ERC-20
'
,
symbol
:
'
DUCK
'
,
address
:
'
0x486a3c5f34cDc4EF133f248f1C81168D78da52e8
'
,
holders
:
'
1152
'
,
decimals
:
'
18
'
,
icon_url
:
null
,
total_supply
:
'
210000000000000000000000000
'
,
exchange_rate
:
null
,
circulating_market_cap
:
null
,
},
},
to_address
:
{
type
:
'
address
'
,
value
:
{
hash
:
'
0x48c04ed5691981C42154C6167398f95e8f38a7fF
'
,
implementation_name
:
null
,
is_contract
:
false
,
is_verified
:
false
,
name
:
null
,
private_tags
:
[],
public_tags
:
[],
watchlist_names
:
[],
},
},
timestamp
:
{
type
:
'
timestamp
'
,
value
:
'
1687005431
'
,
},
},
}
],
},
};
stubs/tx.ts
View file @
898cfafa
import
type
{
RawTracesResponse
}
from
'
types/api/rawTrace
'
;
import
type
{
RawTracesResponse
}
from
'
types/api/rawTrace
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
type
{
Transaction
}
from
'
types/api/transaction
'
;
import
type
{
TxInterpretationResponse
}
from
'
types/api/txInterpretation
'
;
import
{
ADDRESS_PARAMS
}
from
'
./addressParams
'
;
import
{
ADDRESS_PARAMS
}
from
'
./addressParams
'
;
...
@@ -59,3 +60,31 @@ export const TX_ZKEVM_L2: Transaction = {
...
@@ -59,3 +60,31 @@ export const TX_ZKEVM_L2: Transaction = {
};
};
export
const
TX_RAW_TRACE
:
RawTracesResponse
=
[];
export
const
TX_RAW_TRACE
:
RawTracesResponse
=
[];
export
const
TX_INTERPRETATION
:
TxInterpretationResponse
=
{
data
:
{
summaries
:
[
{
summary_template
:
'
{action_type} {source_amount} Ether into {destination_amount} {destination_token}
'
,
summary_template_variables
:
{
action_type
:
{
type
:
'
string
'
,
value
:
'
Wrap
'
},
source_amount
:
{
type
:
'
currency
'
,
value
:
'
0.7
'
},
destination_amount
:
{
type
:
'
currency
'
,
value
:
'
0.7
'
},
destination_token
:
{
type
:
'
token
'
,
value
:
{
name
:
'
Museion
'
,
type
:
'
ERC-20
'
,
symbol
:
'
MUSA
'
,
address
:
'
0x486a3c5f34cDc4EF133f248f1C81168D78da52e8
'
,
holders
:
'
1152
'
,
decimals
:
'
18
'
,
icon_url
:
null
,
total_supply
:
'
210000000000000000000000000
'
,
exchange_rate
:
null
,
circulating_market_cap
:
null
,
},
},
},
}
],
},
};
types/api/txInterpretation.ts
0 → 100644
View file @
898cfafa
import
type
{
AddressParam
}
from
'
types/api/addressParams
'
;
import
type
{
TokenInfo
}
from
'
types/api/token
'
;
export
interface
TxInterpretationResponse
{
data
:
{
summaries
:
Array
<
TxInterpretationSummary
>
;
};
}
export
type
TxInterpretationSummary
=
{
summary_template
:
string
;
summary_template_variables
:
Record
<
string
,
TxInterpretationVariable
>
;
}
export
type
TxInterpretationVariable
=
TxInterpretationVariableString
|
TxInterpretationVariableCurrency
|
TxInterpretationVariableTimestamp
|
TxInterpretationVariableToken
|
TxInterpretationVariableAddress
;
export
type
TxInterpretationVariableType
=
'
string
'
|
'
currency
'
|
'
timestamp
'
|
'
token
'
|
'
address
'
;
export
type
TxInterpretationVariableString
=
{
type
:
'
string
'
;
value
:
string
;
}
export
type
TxInterpretationVariableCurrency
=
{
type
:
'
currency
'
;
value
:
string
;
}
export
type
TxInterpretationVariableTimestamp
=
{
type
:
'
timestamp
'
;
value
:
string
;
}
export
type
TxInterpretationVariableToken
=
{
type
:
'
token
'
;
value
:
TokenInfo
;
}
export
type
TxInterpretationVariableAddress
=
{
type
:
'
address
'
;
value
:
AddressParam
;
}
ui/pages/Transaction.tsx
View file @
898cfafa
import
{
Box
,
Flex
}
from
'
@chakra-ui/react
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
...
@@ -7,7 +8,7 @@ import config from 'configs/app';
...
@@ -7,7 +8,7 @@ import config from 'configs/app';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/contexts/app
'
;
import
{
useAppContext
}
from
'
lib/contexts/app
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
TX
}
from
'
stubs/tx
'
;
import
{
TX
,
TX_INTERPRETATION
}
from
'
stubs/tx
'
;
import
AccountActionsMenu
from
'
ui/shared/AccountActionsMenu/AccountActionsMenu
'
;
import
AccountActionsMenu
from
'
ui/shared/AccountActionsMenu/AccountActionsMenu
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
...
@@ -17,6 +18,8 @@ import PageTitle from 'ui/shared/Page/PageTitle';
...
@@ -17,6 +18,8 @@ import PageTitle from 'ui/shared/Page/PageTitle';
import
RoutedTabs
from
'
ui/shared/Tabs/RoutedTabs
'
;
import
RoutedTabs
from
'
ui/shared/Tabs/RoutedTabs
'
;
import
TabsSkeleton
from
'
ui/shared/Tabs/TabsSkeleton
'
;
import
TabsSkeleton
from
'
ui/shared/Tabs/TabsSkeleton
'
;
import
useTabIndexFromQuery
from
'
ui/shared/Tabs/useTabIndexFromQuery
'
;
import
useTabIndexFromQuery
from
'
ui/shared/Tabs/useTabIndexFromQuery
'
;
import
TxInterpretation
from
'
ui/tx/interpretation/TxInterpretation
'
;
import
{
checkTemplate
as
checkInterpretationTemplate
}
from
'
ui/tx/interpretation/utils
'
;
import
TxDetails
from
'
ui/tx/TxDetails
'
;
import
TxDetails
from
'
ui/tx/TxDetails
'
;
import
TxDetailsWrapped
from
'
ui/tx/TxDetailsWrapped
'
;
import
TxDetailsWrapped
from
'
ui/tx/TxDetailsWrapped
'
;
import
TxInternals
from
'
ui/tx/TxInternals
'
;
import
TxInternals
from
'
ui/tx/TxInternals
'
;
...
@@ -39,6 +42,16 @@ const TransactionPageContent = () => {
...
@@ -39,6 +42,16 @@ const TransactionPageContent = () => {
},
},
});
});
const
hasInterpretationFeature
=
config
.
features
.
txInterpretation
.
isEnabled
;
const
txInterpretationQuery
=
useApiQuery
(
'
tx_interpretation
'
,
{
pathParams
:
{
hash
},
queryOptions
:
{
enabled
:
Boolean
(
hash
)
&&
hasInterpretationFeature
,
placeholderData
:
TX_INTERPRETATION
,
},
});
const
tabs
:
Array
<
RoutedTab
>
=
[
const
tabs
:
Array
<
RoutedTab
>
=
[
{
id
:
'
index
'
,
title
:
config
.
features
.
suave
.
isEnabled
&&
data
?.
wrapped
?
'
Confidential compute tx details
'
:
'
Details
'
,
component
:
<
TxDetails
/>
},
{
id
:
'
index
'
,
title
:
config
.
features
.
suave
.
isEnabled
&&
data
?.
wrapped
?
'
Confidential compute tx details
'
:
'
Details
'
,
component
:
<
TxDetails
/>
},
config
.
features
.
suave
.
isEnabled
&&
data
?.
wrapped
?
config
.
features
.
suave
.
isEnabled
&&
data
?.
wrapped
?
...
@@ -73,12 +86,19 @@ const TransactionPageContent = () => {
...
@@ -73,12 +86,19 @@ const TransactionPageContent = () => {
};
};
},
[
appProps
.
referrer
]);
},
[
appProps
.
referrer
]);
const
hasInterpretation
=
hasInterpretationFeature
&&
(
txInterpretationQuery
.
isPlaceholderData
||
(
txInterpretationQuery
.
data
?.
data
.
summaries
[
0
]
&&
checkInterpretationTemplate
(
txInterpretationQuery
.
data
.
data
.
summaries
[
0
])));
const
titleSecondRow
=
(
const
titleSecondRow
=
(
<>
<
Box
display=
{
{
base
:
'
block
'
,
lg
:
'
flex
'
}
}
alignItems=
"center"
w=
"100%"
>
<
TxEntity
hash=
{
hash
}
noLink
noCopy=
{
false
}
fontWeight=
{
500
}
mr=
{
2
}
fontFamily=
"heading"
/>
{
hasInterpretationFeature
&&
<
TxInterpretation
query=
{
txInterpretationQuery
}
mr=
{
{
base
:
0
,
lg
:
6
}
}
/>
}
{
!
data
?.
tx_tag
&&
<
AccountActionsMenu
mr=
{
{
base
:
0
,
lg
:
3
}
}
/>
}
{
!
hasInterpretation
&&
<
TxEntity
hash=
{
hash
}
noLink
noCopy=
{
false
}
fontWeight=
{
500
}
mr=
{
{
base
:
0
,
lg
:
2
}
}
fontFamily=
"heading"
/>
}
<
NetworkExplorers
type=
"tx"
pathParam=
{
hash
}
ml=
{
{
base
:
3
,
lg
:
'
auto
'
}
}
/>
<
Flex
alignItems=
"center"
justifyContent=
{
{
base
:
'
start
'
,
lg
:
'
space-between
'
}
}
flexGrow=
{
1
}
>
</>
{
!
data
?.
tx_tag
&&
<
AccountActionsMenu
mr=
{
3
}
mt=
{
{
base
:
3
,
lg
:
0
}
}
/>
}
<
NetworkExplorers
type=
"tx"
pathParam=
{
hash
}
ml=
{
{
base
:
0
,
lg
:
'
auto
'
}
}
mt=
{
{
base
:
3
,
lg
:
0
}
}
/>
</
Flex
>
</
Box
>
);
);
return
(
return
(
...
...
ui/tx/interpretation/TxInterpretation.pw.tsx
0 → 100644
View file @
898cfafa
import
{
test
,
expect
}
from
'
@playwright/experimental-ct-react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
type
{
TxInterpretationResponse
}
from
'
types/api/txInterpretation
'
;
import
type
{
ResourceError
}
from
'
lib/api/resources
'
;
import
{
txInterpretation
as
txInterpretationMock
}
from
'
mocks/txs/txInterpretation
'
;
import
TestApp
from
'
playwright/TestApp
'
;
import
TxInterpretation
from
'
./TxInterpretation
'
;
test
(
'
base view +@mobile +@dark-mode
'
,
async
({
mount
})
=>
{
const
component
=
await
mount
(
<
TestApp
>
<
TxInterpretation
query=
{
{
data
:
txInterpretationMock
}
as
UseQueryResult
<
TxInterpretationResponse
,
ResourceError
>
}
/>
</
TestApp
>,
);
await
expect
(
component
).
toHaveScreenshot
();
});
ui/tx/interpretation/TxInterpretation.tsx
0 → 100644
View file @
898cfafa
import
{
Skeleton
,
Text
,
Icon
,
chakra
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
import
type
{
TxInterpretationResponse
,
TxInterpretationVariable
}
from
'
types/api/txInterpretation
'
;
import
actionIcon
from
'
icons/action.svg
'
;
import
type
{
ResourceError
}
from
'
lib/api/resources
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
TokenEntity
from
'
ui/shared/entities/token/TokenEntity
'
;
import
{
extractVariables
,
getStringChunks
}
from
'
./utils
'
;
type
Props
=
{
query
:
UseQueryResult
<
TxInterpretationResponse
,
ResourceError
>
;
className
?:
string
;
}
const
TxInterpretationElementByType
=
({
type
,
value
}:
TxInterpretationVariable
)
=>
{
switch
(
type
)
{
case
'
address
'
:
return
<
AddressEntity
address=
{
value
}
truncation=
"constant"
sx=
{
{
'
:not(:first-child)
'
:
{
marginLeft
:
1
}
}
}
/>;
case
'
token
'
:
return
<
TokenEntity
token=
{
value
}
onlySymbol
width=
"fit-content"
sx=
{
{
'
:not(:first-child)
'
:
{
marginLeft
:
1
}
}
}
/>;
case
'
currency
'
:
return
<
Text
>
{
BigNumber
(
value
).
toFormat
()
}
</
Text
>;
case
'
timestamp
'
:
// timestamp is in unix format
return
<
Text
>
{
dayjs
(
Number
(
value
)
*
1000
).
format
(
'
llll
'
)
}
</
Text
>;
case
'
string
'
:
default
:
{
return
<
Text
>
{
value
.
toString
()
}
</
Text
>;
}
}
};
const
TxInterpretation
=
({
query
,
className
}:
Props
)
=>
{
if
(
!
query
.
data
?.
data
.
summaries
[
0
])
{
return
null
;
}
const
template
=
query
.
data
.
data
.
summaries
[
0
].
summary_template
;
const
variables
=
query
.
data
.
data
.
summaries
[
0
].
summary_template_variables
;
const
variablesNames
=
extractVariables
(
template
);
const
chunks
=
getStringChunks
(
template
);
return
(
<
Skeleton
display=
"flex"
flexWrap=
"wrap"
alignItems=
"center"
isLoaded=
{
!
query
.
isPlaceholderData
}
className=
{
className
}
>
<
Icon
as=
{
actionIcon
}
boxSize=
{
5
}
color=
"text_secondary"
mr=
{
2
}
/>
{
chunks
.
map
((
chunk
,
index
)
=>
{
return
(
<>
<
Text
whiteSpace=
"pre"
>
{
chunk
}
</
Text
>
{
index
<
chunks
.
length
-
1
&&
<
TxInterpretationElementByType
{
...
variables
[
variablesNames
[
index
]]
}
/>
}
</>
);
})
}
</
Skeleton
>
);
};
export
default
chakra
(
TxInterpretation
);
ui/tx/interpretation/__screenshots__/TxInterpretation.pw.tsx_dark-color-mode_base-view-mobile-dark-mode-1.png
0 → 100644
View file @
898cfafa
9.31 KB
ui/tx/interpretation/__screenshots__/TxInterpretation.pw.tsx_default_base-view-mobile-dark-mode-1.png
0 → 100644
View file @
898cfafa
9.06 KB
ui/tx/interpretation/__screenshots__/TxInterpretation.pw.tsx_mobile_base-view-mobile-dark-mode-1.png
0 → 100644
View file @
898cfafa
8.77 KB
ui/tx/interpretation/utils.test.ts
0 → 100644
View file @
898cfafa
import
{
extractVariables
,
checkTemplate
}
from
'
./utils
'
;
const
template
=
'
{action_type} {source_amount} Ether into {destination_amount} {destination_token}
'
;
it
(
'
extracts variables names
'
,
()
=>
{
const
result
=
extractVariables
(
template
);
expect
(
result
).
toEqual
([
'
action_type
'
,
'
source_amount
'
,
'
destination_amount
'
,
'
destination_token
'
]);
});
it
(
'
check template true
'
,
()
=>
{
const
variables
=
{
action_type
:
{
type
:
'
string
'
as
const
,
value
:
'
Wrap
'
},
source_amount
:
{
type
:
'
currency
'
as
const
,
value
:
'
0.7
'
},
destination_amount
:
{
type
:
'
currency
'
as
const
,
value
:
'
0.7
'
},
destination_token
:
{
type
:
'
token
'
as
const
,
value
:
{
name
:
'
Duck
'
,
type
:
'
ERC-20
'
as
const
,
symbol
:
'
DUCK
'
,
address
:
'
0x486a3c5f34cDc4EF133f248f1C81168D78da52e8
'
,
holders
:
'
1152
'
,
decimals
:
'
18
'
,
icon_url
:
null
,
total_supply
:
'
210000000000000000000000000
'
,
exchange_rate
:
null
,
circulating_market_cap
:
null
,
},
},
};
const
result
=
checkTemplate
({
summary_template
:
template
,
summary_template_variables
:
variables
});
expect
(
result
).
toBe
(
true
);
});
it
(
'
check template false
'
,
()
=>
{
const
variables
=
{
action_type
:
{
type
:
'
string
'
as
const
,
value
:
'
Wrap
'
},
source_amount
:
{
type
:
'
currency
'
as
const
,
value
:
'
0.7
'
},
destination_amount
:
{
type
:
'
currency
'
as
const
,
value
:
'
0.7
'
},
};
const
result
=
checkTemplate
({
summary_template
:
template
,
summary_template_variables
:
variables
});
expect
(
result
).
toBe
(
false
);
});
ui/tx/interpretation/utils.ts
0 → 100644
View file @
898cfafa
import
type
{
TxInterpretationSummary
}
from
'
types/api/txInterpretation
'
;
// we use that regex as a separator when splitting template and dont want to capture variables
// eslint-disable-next-line regexp/no-useless-non-capturing-group
export
const
VAR_REGEXP
=
/
\{(?:[^
}
]
+
)\}
/g
;
export
function
extractVariables
(
templateString
:
string
)
{
const
matches
=
templateString
.
match
(
VAR_REGEXP
);
const
variablesNames
=
matches
?
matches
.
map
(
match
=>
match
.
slice
(
1
,
-
1
))
:
[];
return
variablesNames
;
}
export
function
getStringChunks
(
template
:
string
)
{
return
template
.
split
(
VAR_REGEXP
);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export
function
checkTemplate
(
summary
:
TxInterpretationSummary
)
{
const
variablesNames
=
extractVariables
(
summary
.
summary_template
);
for
(
const
name
of
variablesNames
)
{
if
(
!
summary
.
summary_template_variables
[
name
])
{
return
false
;
}
}
return
true
;
}
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