Skip to content

Commit

Permalink
feat(tx builder): use cgw for simulation configs
Browse files Browse the repository at this point in the history
Instead of using a hardcoded list of chains where simulation isn't supported, use CGW
  • Loading branch information
katspaugh committed Apr 18, 2024
1 parent 28c1a3e commit bb17343
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 19 deletions.
1 change: 1 addition & 0 deletions apps/tx-builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@material-ui/lab": "^4.0.0-alpha.60",
"@safe-global/safe-apps-provider": "^0.18.0",
"@safe-global/safe-deployments": "^1.26.0",
"@safe-global/safe-gateway-typescript-sdk": "^3.19.0",
"axios": "^1.6.0",
"evm-proxy-detection": "1.0.0",
"localforage": "^1.10.0",
Expand Down
53 changes: 53 additions & 0 deletions apps/tx-builder/src/hooks/useAsync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useCallback, useEffect, useState } from 'react'
import { asError } from '@/services/exceptions/utils'

export type AsyncResult<T> = [result: T | undefined, error: Error | undefined, loading: boolean]

const useAsync = <T>(
asyncCall: () => Promise<T> | undefined,
dependencies: unknown[],
clearData = true,
): AsyncResult<T> => {
const [data, setData] = useState<T | undefined>()
const [error, setError] = useState<Error>()
const [loading, setLoading] = useState<boolean>(false)

// eslint-disable-next-line react-hooks/exhaustive-deps
const callback = useCallback(asyncCall, dependencies)

useEffect(() => {
setError(undefined)

const promise = callback()

// Not a promise, exit early
if (!promise) {
setData(undefined)
setLoading(false)
return
}

let isCurrent = true
clearData && setData(undefined)
setLoading(true)

promise
.then((val: T) => {
isCurrent && setData(val)
})
.catch(err => {
isCurrent && setError(asError(err))
})
.finally(() => {
isCurrent && setLoading(false)
})

return () => {
isCurrent = false
}
}, [callback, clearData])

return [data, error, loading]
}

export default useAsync
6 changes: 5 additions & 1 deletion apps/tx-builder/src/hooks/useSimulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { useNetwork } from '../store/networkContext'
import { useTransactions } from '../store'
import { FETCH_STATUS } from '../utils'
import useAsync from './useAsync'

type UseSimulationReturn =
| {
Expand Down Expand Up @@ -38,7 +39,10 @@ const useSimulation = (): UseSimulationReturn => {
[simulation],
)
const { safe, web3 } = useNetwork()
const simulationSupported = useMemo(() => isSimulationSupported(safe.chainId.toString()), [safe])
const [simulationSupported = false] = useAsync(
() => isSimulationSupported(safe.chainId.toString()),
[safe.chainId],
)

const simulateTransaction = useCallback(async () => {
if (!web3) return
Expand Down
23 changes: 5 additions & 18 deletions apps/tx-builder/src/lib/simulation/simulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Web3 from 'web3'
import { BaseTransaction } from '@safe-global/safe-apps-sdk'
import { TenderlySimulatePayload, TenderlySimulation, StateObject } from './types'
import { encodeMultiSendCall, getMultiSendCallOnlyAddress } from './multisend'
import { getChainConfig, FEATURES } from '@safe-global/safe-gateway-typescript-sdk'

type OptionalExceptFor<T, TRequired extends keyof T = keyof T> = Partial<
Pick<T, Exclude<keyof T, TRequired>>
Expand All @@ -14,24 +15,10 @@ const TENDERLY_SIMULATE_ENDPOINT_URL = process.env.REACT_APP_TENDERLY_SIMULATE_E
const TENDERLY_PROJECT_NAME = process.env.REACT_APP_TENDERLY_PROJECT_NAME || ''
const TENDERLY_ORG_NAME = process.env.REACT_APP_TENDERLY_ORG_NAME || ''

const NON_SUPPORTED_CHAINS = [
// Energy web chain
'246',
// zkSync Era Testnet
'280',
//zkSync Era Mainnet
'324',
// Polygon zkEVM
'1101',
// Celo
'42220',
// Volta
'73799',
// Aurora
'1313161554',
]

const isSimulationSupported = (chainId: string) => !NON_SUPPORTED_CHAINS.includes(chainId)
const isSimulationSupported = async (chainId: string) => {
const config = await getChainConfig(chainId)
return config.features.includes(FEATURES.TX_SIMULATION)
}

const getSimulation = async (tx: TenderlySimulatePayload): Promise<TenderlySimulation> => {
const response = await axios.post<TenderlySimulation>(TENDERLY_SIMULATE_ENDPOINT_URL, tx)
Expand Down

0 comments on commit bb17343

Please sign in to comment.