Skip to content

Commit

Permalink
Refactor: move MigrateToL2Information out of SignOrExecute
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh committed Dec 19, 2024
1 parent 5f34605 commit e452768
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { zeroPadValue } from 'ethers'
import DecodedData from '../DecodedData'
import ErrorMessage from '@/components/tx/ErrorMessage'
import { useSafeSDK } from '@/hooks/coreSDK/safeCoreSDK'
import { MigrateToL2Information } from '@/components/tx/SignOrExecuteForm/MigrateToL2Information'
import { MigrateToL2Information } from '@/components/tx/confirmation-views/MigrateToL2Information'
import { Box } from '@mui/material'
import { isMultisigDetailedExecutionInfo } from '@/utils/transaction-guards'

Expand Down Expand Up @@ -73,7 +73,8 @@ export const MigrationToL2TxData = ({ txDetails }: { txDetails: TransactionDetai

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

{realSafeTxError ? (
<ErrorMessage>{realSafeTxError.message}</ErrorMessage>
) : decodedRealTxError ? (
Expand Down
85 changes: 2 additions & 83 deletions src/components/tx/SignOrExecuteForm/SignOrExecuteForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,20 @@ import UnknownContractError from './UnknownContractError'
import { ErrorBoundary } from '@sentry/react'
import ApprovalEditor from '../ApprovalEditor'
import { isDelegateCall } from '@/services/tx/tx-sender/sdk'
import { getTransactionTrackingType } from '@/services/analytics/tx-tracking'
import { TX_EVENTS } from '@/services/analytics/events/transactions'
import { trackEvent } from '@/services/analytics'
import useChainId from '@/hooks/useChainId'
import ExecuteThroughRoleForm from './ExecuteThroughRoleForm'
import { findAllowingRole, findMostLikelyRole, useRoles } from './ExecuteThroughRoleForm/hooks'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
import { BlockaidBalanceChanges } from '../security/blockaid/BlockaidBalanceChange'
import { Blockaid } from '../security/blockaid'

import { MigrateToL2Information } from './MigrateToL2Information'
import { extractMigrationL2MasterCopyAddress } from '@/utils/safe-migrations'

import { useLazyGetTransactionDetailsQuery } from '@/store/api/gateway'
import { useApprovalInfos } from '../ApprovalEditor/hooks/useApprovalInfos'

import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
import ConfirmationView from '../confirmation-views'
import { SignerForm } from './SignerForm'
import { useSigner } from '@/hooks/wallets/useWallet'
import { isNestedConfirmationTxInfo } from '@/utils/transaction-guards'
import { trackTxEvents } from './tracking'

export type SubmitCallback = (txId: string, isExecuted?: boolean) => void

Expand All @@ -58,76 +50,6 @@ export type SignOrExecuteProps = {
showMethodCall?: boolean
}

const trackTxEvents = (
details: TransactionDetails | undefined,
isCreation: boolean,
isExecuted: boolean,
isRoleExecution: boolean,
isProposerCreation: boolean,
isParentSigner: boolean,
origin?: string,
) => {
const isNestedConfirmation = !!details && isNestedConfirmationTxInfo(details.txInfo)

const creationEvent = getCreationEvent({ isParentSigner, isRoleExecution, isProposerCreation })
const confirmationEvent = getConfirmationEvent({ isParentSigner, isNestedConfirmation })
const executionEvent = getExecutionEvent({ isParentSigner, isNestedConfirmation, isRoleExecution })

const event = (() => {
if (isCreation) {
return creationEvent
}
if (isExecuted) {
return executionEvent
}
return confirmationEvent
})()

const txType = getTransactionTrackingType(details, origin)
trackEvent({ ...event, label: txType })

// Immediate execution on creation
if (isCreation && isExecuted) {
trackEvent({ ...executionEvent, label: txType })
}
}

function getCreationEvent(args: { isParentSigner: boolean; isRoleExecution: boolean; isProposerCreation: boolean }) {
if (args.isParentSigner) {
return TX_EVENTS.CREATE_VIA_PARENT
}
if (args.isRoleExecution) {
return TX_EVENTS.CREATE_VIA_ROLE
}
if (args.isProposerCreation) {
return TX_EVENTS.CREATE_VIA_PROPOSER
}
return TX_EVENTS.CREATE
}

function getConfirmationEvent(args: { isParentSigner: boolean; isNestedConfirmation: boolean }) {
if (args.isParentSigner) {
return TX_EVENTS.CONFIRM_VIA_PARENT
}
if (args.isNestedConfirmation) {
return TX_EVENTS.CONFIRM_IN_PARENT
}
return TX_EVENTS.CONFIRM
}

function getExecutionEvent(args: { isParentSigner: boolean; isNestedConfirmation: boolean; isRoleExecution: boolean }) {
if (args.isParentSigner) {
return TX_EVENTS.EXECUTE_VIA_PARENT
}
if (args.isNestedConfirmation) {
return TX_EVENTS.EXECUTE_IN_PARENT
}
if (args.isRoleExecution) {
return TX_EVENTS.EXECUTE_VIA_ROLE
}
return TX_EVENTS.EXECUTE
}

export const SignOrExecuteForm = ({
chainId,
safeTx,
Expand Down Expand Up @@ -157,8 +79,6 @@ export const SignOrExecuteForm = ({
const isProposer = useIsWalletProposer()
const isProposing = isProposer && !isSafeOwner && isCreation
const isCounterfactualSafe = !safe.deployed
const multiChainMigrationTarget = extractMigrationL2MasterCopyAddress(safeTx)
const isMultiChainMigration = !!multiChainMigrationTarget

// Check if a Zodiac Roles mod is enabled and if the user is a member of any role that allows the transaction
const roles = useRoles(
Expand Down Expand Up @@ -208,7 +128,6 @@ export const SignOrExecuteForm = ({
<>
<TxCard>
{props.children}
{isMultiChainMigration && <MigrateToL2Information variant="queue" newMasterCopy={multiChainMigrationTarget} />}

<ConfirmationView
isCreation={isCreation}
Expand Down Expand Up @@ -256,7 +175,7 @@ export const SignOrExecuteForm = ({

<NetworkWarning />

{!isMultiChainMigration && <UnknownContractError />}
<UnknownContractError txData={props.txDetails?.txData} />

<Blockaid />

Expand Down
11 changes: 8 additions & 3 deletions src/components/tx/SignOrExecuteForm/UnknownContractError.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { type ReactElement } from 'react'
import { useMemo, type ReactElement } from 'react'
import type { TransactionData } from '@safe-global/safe-gateway-typescript-sdk'
import ExternalLink from '@/components/common/ExternalLink'
import { useCurrentChain } from '@/hooks/useChains'
import useSafeInfo from '@/hooks/useSafeInfo'
import { getExplorerLink } from '@/utils/gateway'
import ErrorMessage from '../ErrorMessage'
import { isValidMasterCopy } from '@/services/contracts/safeContracts'
import { extractMigrationL2MasterCopyAddress } from '@/utils/safe-migrations'

const UnknownContractError = (): ReactElement | null => {
const UnknownContractError = ({ txData }: { txData: TransactionData | undefined }): ReactElement | null => {
const { safe, safeAddress } = useSafeInfo()
const currentChain = useCurrentChain()
const newMasterCopy = useMemo(() => {
return txData && extractMigrationL2MasterCopyAddress(txData)
}, [txData])

// Unsupported base contract
const isUnknown = !isValidMasterCopy(safe.implementationVersionState)

if (!isUnknown) return null
if (!isUnknown || !newMasterCopy) return null

return (
<ErrorMessage>
Expand Down
75 changes: 75 additions & 0 deletions src/components/tx/SignOrExecuteForm/tracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { trackEvent } from '@/services/analytics'
import { TX_EVENTS } from '@/services/analytics/events/transactions'
import { getTransactionTrackingType } from '@/services/analytics/tx-tracking'
import { isNestedConfirmationTxInfo } from '@/utils/transaction-guards'
import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'

function getCreationEvent(args: { isParentSigner: boolean; isRoleExecution: boolean; isProposerCreation: boolean }) {
if (args.isParentSigner) {
return TX_EVENTS.CREATE_VIA_PARENT
}
if (args.isRoleExecution) {
return TX_EVENTS.CREATE_VIA_ROLE
}
if (args.isProposerCreation) {
return TX_EVENTS.CREATE_VIA_PROPOSER
}
return TX_EVENTS.CREATE
}

function getConfirmationEvent(args: { isParentSigner: boolean; isNestedConfirmation: boolean }) {
if (args.isParentSigner) {
return TX_EVENTS.CONFIRM_VIA_PARENT
}
if (args.isNestedConfirmation) {
return TX_EVENTS.CONFIRM_IN_PARENT
}
return TX_EVENTS.CONFIRM
}

function getExecutionEvent(args: { isParentSigner: boolean; isNestedConfirmation: boolean; isRoleExecution: boolean }) {
if (args.isParentSigner) {
return TX_EVENTS.EXECUTE_VIA_PARENT
}
if (args.isNestedConfirmation) {
return TX_EVENTS.EXECUTE_IN_PARENT
}
if (args.isRoleExecution) {
return TX_EVENTS.EXECUTE_VIA_ROLE
}
return TX_EVENTS.EXECUTE
}

export function trackTxEvents(
details: TransactionDetails | undefined,
isCreation: boolean,
isExecuted: boolean,
isRoleExecution: boolean,
isProposerCreation: boolean,
isParentSigner: boolean,
origin?: string,
) {
const isNestedConfirmation = !!details && isNestedConfirmationTxInfo(details.txInfo)

const creationEvent = getCreationEvent({ isParentSigner, isRoleExecution, isProposerCreation })
const confirmationEvent = getConfirmationEvent({ isParentSigner, isNestedConfirmation })
const executionEvent = getExecutionEvent({ isParentSigner, isNestedConfirmation, isRoleExecution })

const event = (() => {
if (isCreation) {
return creationEvent
}
if (isExecuted) {
return executionEvent
}
return confirmationEvent
})()

const txType = getTransactionTrackingType(details, origin)
trackEvent({ ...event, label: txType })

// Immediate execution on creation
if (isCreation && isExecuted) {
trackEvent({ ...executionEvent, label: txType })
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { useMemo } from 'react'
import { Alert, AlertTitle, Box, SvgIcon, Typography } from '@mui/material'
import type { TransactionData } from '@safe-global/safe-gateway-typescript-sdk'
import InfoOutlinedIcon from '@/public/images/notifications/info.svg'
import NamedAddressInfo from '@/components/common/NamedAddressInfo'
import { extractMigrationL2MasterCopyAddress } from '@/utils/safe-migrations'

export const MigrateToL2Information = ({
variant,
newMasterCopy,
txData,
}: {
variant: 'history' | 'queue'
newMasterCopy?: string
txData?: TransactionData
}) => {
const newMasterCopy = useMemo(() => {
return txData && extractMigrationL2MasterCopyAddress(txData)
}, [txData])

return (
<Box>
<Alert severity="info" icon={<SvgIcon component={InfoOutlinedIcon} color="info" />}>
Expand Down
6 changes: 6 additions & 0 deletions src/components/tx/confirmation-views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
isExecTxData,
isOnChainConfirmationTxData,
isOrderTxInfo,
isSafeToL2MigrationTxData,
isSafeUpdateTxData,
isSwapOrderTxInfo,
} from '@/utils/transaction-guards'
Expand All @@ -24,6 +25,7 @@ import { type ReactElement } from 'react'
import SwapOrder from './SwapOrder'
import StakingTx from './StakingTx'
import UpdateSafe from './UpdateSafe'
import { MigrateToL2Information } from './MigrateToL2Information'

type ConfirmationViewProps = {
txDetails?: TransactionDetails
Expand Down Expand Up @@ -59,6 +61,10 @@ const getConfirmationViewComponent = ({

if (isCustomTxInfo(txInfo) && isSafeUpdateTxData(txDetails.txData)) return <UpdateSafe />

if (isCustomTxInfo(txInfo) && isSafeToL2MigrationTxData(txDetails.txData)) {
return <MigrateToL2Information variant="queue" txData={txDetails.txData} />
}

return null
}

Expand Down
Loading

0 comments on commit e452768

Please sign in to comment.