From bb17343f30b6ead9756490fc7c5d9649747e25ca Mon Sep 17 00:00:00 2001 From: katspaugh Date: Thu, 18 Apr 2024 11:05:33 +0200 Subject: [PATCH] feat(tx builder): use cgw for simulation configs Instead of using a hardcoded list of chains where simulation isn't supported, use CGW --- apps/tx-builder/package.json | 1 + apps/tx-builder/src/hooks/useAsync.ts | 53 +++++++++++++++++++ apps/tx-builder/src/hooks/useSimulation.ts | 6 ++- .../src/lib/simulation/simulation.ts | 23 ++------ 4 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 apps/tx-builder/src/hooks/useAsync.ts diff --git a/apps/tx-builder/package.json b/apps/tx-builder/package.json index 961b66120..851b5bf6f 100644 --- a/apps/tx-builder/package.json +++ b/apps/tx-builder/package.json @@ -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", diff --git a/apps/tx-builder/src/hooks/useAsync.ts b/apps/tx-builder/src/hooks/useAsync.ts new file mode 100644 index 000000000..62215492c --- /dev/null +++ b/apps/tx-builder/src/hooks/useAsync.ts @@ -0,0 +1,53 @@ +import { useCallback, useEffect, useState } from 'react' +import { asError } from '@/services/exceptions/utils' + +export type AsyncResult = [result: T | undefined, error: Error | undefined, loading: boolean] + +const useAsync = ( + asyncCall: () => Promise | undefined, + dependencies: unknown[], + clearData = true, +): AsyncResult => { + const [data, setData] = useState() + const [error, setError] = useState() + const [loading, setLoading] = useState(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 diff --git a/apps/tx-builder/src/hooks/useSimulation.ts b/apps/tx-builder/src/hooks/useSimulation.ts index c0adccad1..a42403eb1 100644 --- a/apps/tx-builder/src/hooks/useSimulation.ts +++ b/apps/tx-builder/src/hooks/useSimulation.ts @@ -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 = | { @@ -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 diff --git a/apps/tx-builder/src/lib/simulation/simulation.ts b/apps/tx-builder/src/lib/simulation/simulation.ts index 1047d4779..7efd25ac4 100644 --- a/apps/tx-builder/src/lib/simulation/simulation.ts +++ b/apps/tx-builder/src/lib/simulation/simulation.ts @@ -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 = Partial< Pick> @@ -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 => { const response = await axios.post(TENDERLY_SIMULATE_ENDPOINT_URL, tx)