diff --git a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs index 2f5b9f2..1d4351e 100644 --- a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs @@ -228,6 +228,19 @@ public async Task EstimateTotalCosts_HigherThanGasCostsByValue() Assert.True(totalCosts.wei - gasCosts.wei == transaction.Input.Value.Value); } + [Fact] + public async Task EstimateGasFees_ReturnsCorrectly() + { + var transaction = await CreateSampleTransaction(); + _ = transaction.SetValue(new BigInteger(1000)); + _ = transaction.SetTo(Constants.ADDRESS_ZERO); + + (var maxFee, var maxPrio) = await ThirdwebTransaction.EstimateGasFees(transaction); + + Assert.NotEqual(BigInteger.Zero, maxFee); + Assert.NotEqual(BigInteger.Zero, maxPrio); + } + [Fact] public async Task EstimateGasPrice_BumpsCorrectly() { diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 8979dac..511545b 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -5,6 +5,7 @@ using Nethereum.Contracts; using Nethereum.ABI.FunctionEncoding; using Nethereum.Hex.HexConvertors.Extensions; +using Newtonsoft.Json.Linq; namespace Thirdweb { @@ -101,6 +102,44 @@ public static async Task EstimateTotalCosts(ThirdwebTransaction tran return new TotalCosts { ether = (value + gasCosts.wei).ToString().ToEth(18, false), wei = value + gasCosts.wei }; } + public static async Task<(BigInteger, BigInteger)> EstimateGasFees(ThirdwebTransaction transaction, bool withBump = true) + { + var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); + var chainId = transaction.Input.ChainId.Value; + var gasPrice = await EstimateGasPrice(transaction, withBump); + + try + { + var block = await rpc.SendRequestAsync("eth_getBlockByNumber", "latest", true); + var maxPriorityFeePerGas = await rpc.SendRequestAsync("eth_maxPriorityFeePerGas"); + var baseBlockFee = block["result"]?["baseFeePerGas"]?.ToObject() ?? new BigInteger(100); + + if (chainId == 42220 || chainId == 44787 || chainId == 62320) + { + return (gasPrice, gasPrice); + } + + if (!maxPriorityFeePerGas.HasValue) + { + maxPriorityFeePerGas = new BigInteger(2); + } + + var preferredMaxPriorityFeePerGas = maxPriorityFeePerGas.Value * 10 / 9; + var maxFeePerGas = (baseBlockFee * 2) + preferredMaxPriorityFeePerGas; + + if (withBump) + { + maxFeePerGas *= 10 / 9; + } + + return (maxFeePerGas, preferredMaxPriorityFeePerGas); + } + catch + { + return (gasPrice, gasPrice); + } + } + public static async Task EstimateGasPrice(ThirdwebTransaction transaction, bool withBump = true) { var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); @@ -145,10 +184,20 @@ public static async Task Send(ThirdwebTransaction transaction) transaction.Input.From ??= await transaction._wallet.GetAddress(); transaction.Input.Value ??= new HexBigInteger(0); transaction.Input.Data ??= "0x"; - transaction.Input.MaxFeePerGas = null; - transaction.Input.MaxPriorityFeePerGas = null; transaction.Input.Gas ??= new HexBigInteger(await EstimateGasLimit(transaction)); - transaction.Input.GasPrice ??= new HexBigInteger(await EstimateGasPrice(transaction)); + + if (transaction.Input.GasPrice == null) + { + (var maxFee, var maxPrio) = await EstimateGasFees(transaction); + transaction.Input.MaxFeePerGas ??= new HexBigInteger(maxFee); + transaction.Input.MaxPriorityFeePerGas ??= new HexBigInteger(maxPrio); + } + else + { + transaction.Input.MaxFeePerGas = null; + transaction.Input.MaxPriorityFeePerGas = null; + transaction.Input.GasPrice ??= new HexBigInteger(await EstimateGasPrice(transaction)); + } var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); string hash;