diff --git a/packages/berajs/src/hooks/useContractWrite/useBeraContractWrite.ts b/packages/berajs/src/hooks/useContractWrite/useBeraContractWrite.ts index a5d00b952..9598d5081 100755 --- a/packages/berajs/src/hooks/useContractWrite/useBeraContractWrite.ts +++ b/packages/berajs/src/hooks/useContractWrite/useBeraContractWrite.ts @@ -4,13 +4,13 @@ import { usePublicClient, useSendTransaction, useWriteContract } from "wagmi"; import { getErrorMessage, getRevertReason } from "~/utils/errorMessages"; import { ActionEnum, initialState, reducer } from "~/utils/stateReducer"; import { useBeraJs } from "~/contexts"; +import { DEFAULT_METAMASK_GAS_LIMIT } from "~/utils"; import { usePollTransactionCount } from "../usePollTransactionCount"; import { type IContractWrite, type IUseContractWriteArgs, type useContractWriteApi, } from "./types"; -import { DEFAULT_METAMASK_GAS_LIMIT } from "~/utils"; const increaseByPercentage = (value: bigint, percentage: number) => { return value + (value * BigInt(percentage)) / BigInt(100); @@ -46,7 +46,7 @@ const useBeraContractWrite = ({ params, value = 0n, data, - gasLimit = DEFAULT_METAMASK_GAS_LIMIT, + gasLimit, ...rest }: IContractWrite): Promise => { dispatch({ type: ActionEnum.LOADING }); @@ -61,40 +61,67 @@ const useBeraContractWrite = ({ }); if (data) { + // Add gas estimation for direct transactions + const estimatedGas = + gasLimit ?? + (await publicClient + .estimateGas({ + account, + to: address, + data, + value, + }) + .catch(() => DEFAULT_METAMASK_GAS_LIMIT)); + receipt = await sendTransactionAsync({ data, to: address, value, - gas: gasLimit, - nonce: nonce + 1, + gas: estimatedGas, + nonce: nonce, }); } else { // Run simulation and gas estimation in parallel // TODO: figure out clean way to early detect errors and effectively show them on the UI - const [{ request }, wagmiPubEstimateContractGas] = await Promise.all([ - publicClient.simulateContract({ - address: address, - abi: abi, - functionName: functionName, - args: params, - value: value, - account: account, - }), - publicClient.estimateContractGas({ - address: address, - abi: abi, - functionName: functionName, - args: params, - value: value, - account: account, - }), - ]); + const [simulationResult, gasEstimateResult] = + await Promise.allSettled([ + publicClient.simulateContract({ + address: address, + abi: abi, + functionName: functionName, + args: params, + value: value, + account: account, + }), + // Only estimate gas if no gasLimit is provided + ...(!gasLimit + ? [ + publicClient.estimateContractGas({ + address: address, + abi: abi, + functionName: functionName, + args: params, + value: value, + account: account, + }), + ] + : []), + ]); + + if (simulationResult.status === "rejected") { + throw simulationResult.reason; + } + + const estimatedGas = + gasLimit ?? + (gasEstimateResult.status === "fulfilled" + ? increaseByPercentage(gasEstimateResult.value, 10) + : DEFAULT_METAMASK_GAS_LIMIT); receipt = await writeContractAsync({ - ...request, - gas: - increaseByPercentage(wagmiPubEstimateContractGas, 10) ?? gasLimit, - nonce: nonce + 1, + ...simulationResult.value.request, + gas: estimatedGas, + nonce: nonce, }); } diff --git a/packages/berajs/src/utils/const.ts b/packages/berajs/src/utils/const.ts index 64d7afc07..487c6ede3 100644 --- a/packages/berajs/src/utils/const.ts +++ b/packages/berajs/src/utils/const.ts @@ -1 +1,5 @@ -export const DEFAULT_METAMASK_GAS_LIMIT = 7920027n; // NOTE: this is the metamask gas limit, https://github.com/MetaMask/metamask-extension/blob/06cf7459b963e26d0ae60312d4f9a342d07ab89d/ui/pages/confirmations/send/send.constants.js#L8 +/** + * Default gas limit used by MetaMask + * @see {@link https://github.com/MetaMask/metamask-extension/blob/06cf7459b963e26d0ae60312d4f9a342d07ab89d/ui/pages/confirmations/send/send.constants.js#L8} + */ +export const DEFAULT_METAMASK_GAS_LIMIT = 7920027n;