Skip to content

Commit

Permalink
Refactor(Tx decoding): use transaction preview endpoint (#4783)
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh authored Jan 20, 2025
1 parent 6a6240c commit bebed8f
Show file tree
Hide file tree
Showing 36 changed files with 446 additions and 551 deletions.
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@safe-global/protocol-kit": "^4.1.3",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-client-gateway-sdk": "v1.60.1",
"@safe-global/safe-gateway-typescript-sdk": "3.22.6",
"@safe-global/safe-gateway-typescript-sdk": "3.22.7-beta.2",
"@safe-global/safe-modules-deployments": "^2.2.1",
"@safe-global/store": "workspace:^",
"@sentry/react": "^7.91.0",
Expand Down
1 change: 1 addition & 0 deletions apps/web/public/fallback-ce627215c0e4a9af.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/web/public/sw.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/web/public/workbox-b52a85cb.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/web/public/worker-a1b55571f2865253.js.map

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion apps/web/src/components/batch/BatchSidebar/BatchTxItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,13 @@ const BatchTxItem = ({ id, count, timestamp, txDetails, onDelete }: BatchTxItemP

<AccordionDetails>
<div className={css.details}>
<TxData txDetails={txDetails} trusted imitation={false} />
<TxData
txInfo={txDetails.txInfo}
txData={txDetails.txData}
txDetails={txDetails}
trusted
imitation={false}
/>

<TxDataRow title="Created:">{timestamp ? dateString(timestamp) : null}</TxDataRow>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('DecodedData', () => {
it('shows an Interact with block if there is no txData but toInfo', () => {
const { getByText } = render(<DecodedData txData={undefined} toInfo={{ value: '0x123' }} />)

expect(getByText('Interact with')).toBeInTheDocument()
expect(getByText('Interact with:')).toBeInTheDocument()
})

it('shows Hex encoded data if there are no parameters', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const DecodedData = ({ txData, toInfo }: Props): ReactElement | null => {

return (
<SendToBlock
title="Interact with"
title="Interact with:"
address={toInfo.value}
name={toInfo.name}
customAvatar={toInfo.logoUri}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import DecodedTx from '@/components/tx/DecodedTx'
import useAsync from '@/hooks/useAsync'
import { useCurrentChain } from '@/hooks/useChains'
import useDecodeTx from '@/hooks/useDecodeTx'
import useSafeInfo from '@/hooks/useSafeInfo'
import { useWeb3ReadOnly } from '@/hooks/wallets/web3'
import { getMultiSendContractDeployment } from '@/services/contracts/deployments'
Expand All @@ -14,6 +13,7 @@ import { useSafeSDK } from '@/hooks/coreSDK/safeCoreSDK'
import { MigrateToL2Information } from '@/components/tx/confirmation-views/MigrateToL2Information'
import { Box } from '@mui/material'
import { isMultisigDetailedExecutionInfo } from '@/utils/transaction-guards'
import useTxPreview from '@/components/tx/confirmation-views/useTxPreview'

export const MigrationToL2TxData = ({ txDetails }: { txDetails: TransactionDetails }) => {
const readOnlyProvider = useWeb3ReadOnly()
Expand Down Expand Up @@ -66,22 +66,21 @@ export const MigrationToL2TxData = ({ txDetails }: { txDetails: TransactionDetai
}
}, [txDetails.txHash, txDetails.detailedExecutionInfo, chain, sdk, readOnlyProvider, safe.version])

const [decodedRealTx, decodedRealTxError] = useDecodeTx(realSafeTx)

const decodedDataUnavailable = !realSafeTx && !realSafeTxLoading
const [txPreview, txPreviewError] = useTxPreview(realSafeTx?.data)

return (
<Box>
<MigrateToL2Information variant="history" txData={txDetails.txData} />

{realSafeTxError ? (
<ErrorMessage>{realSafeTxError.message}</ErrorMessage>
) : decodedRealTxError ? (
<ErrorMessage>{decodedRealTxError.message}</ErrorMessage>
) : txPreviewError ? (
<ErrorMessage>{txPreviewError.message}</ErrorMessage>
) : decodedDataUnavailable ? (
<DecodedData txData={txDetails.txData} />
) : (
<DecodedTx decodedData={decodedRealTx} tx={realSafeTx} />
txPreview && <DecodedTx {...txPreview} tx={realSafeTx} />
)}
</Box>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Safe__factory } from '@/types/contracts'
import { Skeleton } from '@mui/material'
import { getConfirmationView, type TransactionData } from '@safe-global/safe-gateway-typescript-sdk'
import { type TransactionData } from '@safe-global/safe-gateway-typescript-sdk'
import ErrorMessage from '@/components/tx/ErrorMessage'

import DecodedTx from '@/components/tx/DecodedTx'
Expand All @@ -9,9 +9,9 @@ import { useCurrentChain } from '@/hooks/useChains'
import { AppRoutes } from '@/config/routes'
import { useMemo } from 'react'
import type { SafeTransaction } from '@safe-global/safe-core-sdk-types'
import useAsync from '@/hooks/useAsync'
import ExternalLink from '@/components/common/ExternalLink'
import { NestedTransaction } from '../NestedTransaction'
import useTxPreview from '@/components/tx/confirmation-views/useTxPreview'

const safeInterface = Safe__factory.createInterface()

Expand Down Expand Up @@ -55,20 +55,20 @@ export const ExecTransaction = ({
[data?.hexData],
)

const [decodedNestedTransaction, error] = useAsync(async () => {
if (chain?.chainId && data?.to.value && childSafeTx) {
return await getConfirmationView(
chain.chainId,
data.to.value,
childSafeTx.data.data,
childSafeTx.data.to,
childSafeTx.data.value.toString(),
)
}
}, [chain?.chainId, data?.to.value, childSafeTx])
const [txPreview, error] = useTxPreview(
childSafeTx
? {
operation: childSafeTx.data.operation,
data: childSafeTx.data.data,
to: childSafeTx.data.to,
value: childSafeTx.data.value.toString(),
}
: undefined,
data?.to.value,
)

const decodedNestedTxDataBlock = decodedNestedTransaction ? (
<DecodedTx tx={childSafeTx} showMethodCall decodedData={decodedNestedTransaction} showAdvancedDetails={false} />
const decodedNestedTxDataBlock = txPreview ? (
<DecodedTx {...txPreview} tx={childSafeTx} showMethodCall showAdvancedDetails={false} />
) : null

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ export const OnChainConfirmation = ({
<NestedTransaction txData={data} isConfirmationView={isConfirmationView}>
{nestedTxDetails ? (
<>
<TxData txDetails={nestedTxDetails} trusted imitation={false} />
<TxData
txData={nestedTxDetails.txData}
txInfo={nestedTxDetails.txInfo}
txDetails={nestedTxDetails}
trusted
imitation={false}
/>

{(isMultiSendTxInfo(nestedTxDetails.txInfo) || isOrderTxInfo(nestedTxDetails.txInfo)) && (
<ErrorBoundary fallback={<div>Error parsing data</div>}>
Expand Down
62 changes: 37 additions & 25 deletions apps/web/src/components/transactions/TxDetails/TxData/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
isTransferTxInfo,
} from '@/utils/transaction-guards'
import { SpendingLimits } from '@/components/transactions/TxDetails/TxData/SpendingLimits'
import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { TransactionStatus, type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { type ReactElement } from 'react'
import RejectionTxInfo from '@/components/transactions/TxDetails/TxData/Rejection'
import DecodedData from '@/components/transactions/TxDetails/TxData/DecodedData'
Expand All @@ -36,68 +36,80 @@ import { ExecTransaction } from './NestedTransaction/ExecTransaction'
import SafeUpdate from './SafeUpdate'

const TxData = ({
txInfo,
txData,
txDetails,
trusted,
imitation,
}: {
txDetails: TransactionDetails
txInfo: TransactionDetails['txInfo']
txData: TransactionDetails['txData']
txDetails?: TransactionDetails
trusted: boolean
imitation: boolean
}): ReactElement => {
const chainId = useChainId()
const txInfo = txDetails.txInfo
const toInfo = isCustomTxInfo(txDetails.txInfo) ? txDetails.txInfo.to : undefined

if (isOrderTxInfo(txDetails.txInfo)) {
return <SwapOrder txData={txDetails.txData} txInfo={txDetails.txInfo} />
if (isOrderTxInfo(txInfo)) {
return <SwapOrder txData={txData} txInfo={txInfo} />
}

if (isStakingTxDepositInfo(txDetails.txInfo)) {
return <StakingTxDepositDetails txData={txDetails.txData} info={txDetails.txInfo} />
if (isStakingTxDepositInfo(txInfo)) {
return <StakingTxDepositDetails txData={txData} info={txInfo} />
}

if (isStakingTxExitInfo(txDetails.txInfo)) {
return <StakingTxExitDetails info={txDetails.txInfo} />
if (isStakingTxExitInfo(txInfo)) {
return <StakingTxExitDetails info={txInfo} />
}

if (isStakingTxWithdrawInfo(txDetails.txInfo)) {
return <StakingTxWithdrawDetails info={txDetails.txInfo} />
if (isStakingTxWithdrawInfo(txInfo)) {
return <StakingTxWithdrawDetails info={txInfo} />
}

if (isTransferTxInfo(txInfo)) {
return <TransferTxInfo txInfo={txInfo} txStatus={txDetails.txStatus} trusted={trusted} imitation={imitation} />
return (
<TransferTxInfo
txInfo={txInfo}
txStatus={txDetails?.txStatus ?? TransactionStatus.AWAITING_CONFIRMATIONS}
trusted={trusted}
imitation={imitation}
/>
)
}

if (isSettingsChangeTxInfo(txInfo)) {
return <SettingsChangeTxInfo settingsInfo={txInfo.settingsInfo} />
}

if (isCancellationTxInfo(txInfo) && isMultisigDetailedExecutionInfo(txDetails.detailedExecutionInfo)) {
if (txDetails && isCancellationTxInfo(txInfo) && isMultisigDetailedExecutionInfo(txDetails.detailedExecutionInfo)) {
return <RejectionTxInfo nonce={txDetails.detailedExecutionInfo?.nonce} isTxExecuted={!!txDetails.executedAt} />
}

const method = txDetails.txData?.dataDecoded?.method as SpendingLimitMethods
if (isCustomTxInfo(txInfo) && isSupportedSpendingLimitAddress(txInfo, chainId) && isSpendingLimitMethod(method)) {
return <SpendingLimits txData={txDetails.txData} txInfo={txInfo} type={method} />
if (
isCustomTxInfo(txInfo) &&
isSupportedSpendingLimitAddress(txInfo, chainId) &&
isSpendingLimitMethod(txData?.dataDecoded?.method)
) {
return <SpendingLimits txData={txData} txInfo={txInfo} type={txData?.dataDecoded?.method as SpendingLimitMethods} />
}

if (isMigrateToL2TxData(txDetails.txData, chainId)) {
if (txDetails && isMigrateToL2TxData(txData, chainId)) {
return <MigrationToL2TxData txDetails={txDetails} />
}

if (isOnChainConfirmationTxData(txDetails.txData)) {
return <OnChainConfirmation data={txDetails.txData} />
if (isOnChainConfirmationTxData(txData)) {
return <OnChainConfirmation data={txData} />
}

if (isExecTxData(txDetails.txData)) {
return <ExecTransaction data={txDetails.txData} />
if (isExecTxData(txData)) {
return <ExecTransaction data={txData} />
}

if (isSafeUpdateTxData(txDetails.txData)) {
return <SafeUpdate txData={txDetails.txData} />
if (isSafeUpdateTxData(txData)) {
return <SafeUpdate txData={txData} />
}

return <DecodedData txData={txDetails.txData} toInfo={toInfo} />
return <DecodedData txData={txData} toInfo={isCustomTxInfo(txInfo) ? txInfo.to : undefined} />
}

export default TxData
8 changes: 7 additions & 1 deletion apps/web/src/components/transactions/TxDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,13 @@ const TxDetailsBlock = ({ txSummary, txDetails }: TxDetailsProps): ReactElement

<div className={css.txData}>
<ErrorBoundary fallback={<div>Error parsing data</div>}>
<TxData txDetails={txDetails} trusted={isTrustedTransfer} imitation={isImitationTransaction} />
<TxData
txData={txDetails.txData}
txInfo={txDetails.txInfo}
txDetails={txDetails}
trusted={isTrustedTransfer}
imitation={isImitationTransaction}
/>
</ErrorBoundary>
</div>

Expand Down
Loading

0 comments on commit bebed8f

Please sign in to comment.