public IEnumerator SuggestFee(BigInteger?maxPriorityFeePerGas = null)
        {
            yield return(_ethGetBlockWithTransactionsHashes.SendRequest(BlockParameter.CreateLatest()));

            if (_ethGetBlockWithTransactionsHashes.Exception == null)
            {
                var lastBlock = _ethGetBlockWithTransactionsHashes.Result;
                if (lastBlock.BaseFeePerGas == null)
                {
                    this.Result = MedianPriorityFeeHistorySuggestionStrategy.FallbackFeeSuggestion;
                    yield break;
                }
                else
                {
                    var baseFee = lastBlock.BaseFeePerGas;

                    if (maxPriorityFeePerGas == null)
                    {
                        BigInteger?estimatedPriorityFee;
                        if (baseFee.Value < MedianPriorityFeeHistorySuggestionStrategy.PRIORITY_FEE_ESTIMATION_TRIGGER)
                        {
                            estimatedPriorityFee = MedianPriorityFeeHistorySuggestionStrategy.DefaultPriorityFee;
                        }
                        else
                        {
                            yield return(_ethFeeHistory.SendRequest(new HexBigInteger(MedianPriorityFeeHistorySuggestionStrategy.FeeHistoryNumberOfBlocks), new BlockParameter(lastBlock.Number), new double[] {
                                MedianPriorityFeeHistorySuggestionStrategy.FEE_HISTORY_PERCENTILE
                            }));

                            if (_ethFeeHistory.Exception != null)
                            {
                                this.Exception = _ethFeeHistory.Exception;
                                yield break;
                            }
                            else
                            {
                                estimatedPriorityFee = _medianPriorityFeeHistorySuggestionStrategy.EstimatePriorityFee(_ethFeeHistory.Result);
                            }
                        }

                        if (estimatedPriorityFee == null)
                        {
                            this.Result = MedianPriorityFeeHistorySuggestionStrategy.FallbackFeeSuggestion;
                            yield break;
                        }

                        maxPriorityFeePerGas = BigInteger.Max(estimatedPriorityFee.Value, MedianPriorityFeeHistorySuggestionStrategy.DefaultPriorityFee);
                    }

                    this.Result = _medianPriorityFeeHistorySuggestionStrategy.SuggestMaxFeeUsingMultiplier(maxPriorityFeePerGas, baseFee);
                    yield break;
                }
            }
            else
            {
                this.Exception = _ethGetBlockWithTransactionsHashes.Exception;
                yield break;
            }
        }
        public IEnumerator SuggestTip(BigInteger firstBlock, decimal[] gasUsedRatio)
        {
            var ptr        = gasUsedRatio.Length - 1;
            var needBlocks = 5;
            var rewards    = new List <BigInteger>();

            while (needBlocks > 0 && ptr >= 0)
            {
                var blockCount = _timePreferenceFeeSuggestionStrategy.MaxBlockCount(gasUsedRatio, ptr, needBlocks);
                if (blockCount > 0)
                {
                    // feeHistory API call with reward percentile specified is expensive and therefore is only requested for a few non-full recent blocks.
                    yield return(_ethFeeHistory.SendRequest(blockCount.ToHexBigInteger(), new BlockParameter(new HexBigInteger(firstBlock + ptr)), new double[] { 0 }));

                    if (_ethFeeHistory.Exception == null)
                    {
                        for (var i = 0; i < _ethFeeHistory.Result.Reward.Length; i++)
                        {
                            rewards.Add(_ethFeeHistory.Result.Reward[i][0]);
                        }

                        if (_ethFeeHistory.Result.Reward.Length < blockCount)
                        {
                            break;
                        }
                    }
                    else
                    {
                        this.Exception = _ethFeeHistory.Exception;
                        yield break;
                    }

                    needBlocks -= blockCount;
                }
                ptr -= blockCount + 1;
            }

            if (rewards.Count == 0)
            {
                this.Result = FallbackTip;
            }
            else
            {
                rewards.Sort();
                this.Result = rewards[(int)Math.Truncate((double)(rewards.Count / 2))];
            }
        }