Docs

eth_feeHistory - Celo RPC Method

Get historical gas fee data on Celo including base fees and priority fee percentiles. Essential for gas price prediction, fee estimation UIs, and network congestion monitoring.

Returns historical gas fee data on Celo, including base fees per gas and priority fee percentiles for a range of recent blocks. This data is essential for building accurate fee estimation algorithms for EIP-1559 transactions.

Why Celo? Build on the mobile-first L2 powering 500K+ daily active users and $2B+ monthly stablecoin volume with phone number-based addressing, sub-cent fees, 150+ country adoption, Nightfall privacy layer, and Opera browser integration.

When to Use This Method

The eth_feeHistory method serves these key scenarios for mobile payment developers, fintech builders, and teams targeting emerging markets:

  • Calculate optimal EIP-1559 fee parameters - Derive maxPriorityFeePerGas from reward percentiles and maxFeePerGas from base fee trends for mobile stablecoin payments (MiniPay 10M+ wallets), remittances, humanitarian aid, and local currency stablecoins (cUSD, cNGN, cEUR)
  • Analyze fee market trends - Inspect historical base fees and gas utilization ratios to forecast fee direction and time transactions for lower costs
  • Build intelligent gas pricing strategies - Create automated fee estimation that adapts to network congestion on Celo without manual intervention
  • Predict future base fees - Use the trailing baseFeePerGas value (index blockCount in the array) to anticipate the next block's base fee using EIP-1559 elasticity math

Common Use Cases

1. Calculate Optimal EIP-1559 Fee Parameters

Derive maxPriorityFeePerGas from reward percentile data and set maxFeePerGas with a safety margin above the predicted next base fee. This approach gives you fee parameters tuned to real network conditions on Celo.

JavaScript
import { JsonRpcProvider, formatUnits } from 'ethers';

const provider = new JsonRpcProvider('https://api-celo-mainnet-archive.n.dwellir.com/YOUR_API_KEY');

async function getEIP1559Fees(blockCount = 10) {
  const feeHistory = await provider.send('eth_feeHistory', [
    '0x' + blockCount.toString(16),
    'latest',
    [50, 90]
  ]);

  const nextBaseFee = BigInt(feeHistory.baseFeePerGas[blockCount]);
  const rewards50th = feeHistory.reward.map(r => BigInt(r[0]));
  const rewards90th = feeHistory.reward.map(r => BigInt(r[1]));

  const avg50th = rewards50th.reduce((s, r) => s + r, 0n) / BigInt(blockCount);
  const avg90th = rewards90th.reduce((s, r) => s + r, 0n) / BigInt(blockCount);

  return {
    medium: {
      maxPriorityFeePerGas: avg50th,
      maxFeePerGas: nextBaseFee * 2n + avg50th
    },
    fast: {
      maxPriorityFeePerGas: avg90th,
      maxFeePerGas: nextBaseFee * 2n + avg90th
    }
  };
}

const fees = await getEIP1559Fees();
console.log('Medium priority fee:', formatUnits(fees.medium.maxPriorityFeePerGas, 'gwei'), 'Gwei');
console.log('Fast priority fee:', formatUnits(fees.fast.maxPriorityFeePerGas, 'gwei'), 'Gwei');

2. Build Fee Estimation UI

Display recent base fee trends and provide low/medium/high fee estimates to end users. This pattern powers gas estimation widgets in wallets and dApp interfaces.

JavaScript
import { JsonRpcProvider, formatUnits } from 'ethers';

const provider = new JsonRpcProvider('https://api-celo-mainnet-archive.n.dwellir.com/YOUR_API_KEY');

async function getFeeEstimateUI(blockRange = 20) {
  const feeHistory = await provider.send('eth_feeHistory', [
    '0x' + blockRange.toString(16),
    'latest',
    [10, 50, 90]
  ]);

  const baseFees = feeHistory.baseFeePerGas.map(f => Number(BigInt(f)) / 1e9);
  const rewardAvgs = [0, 1, 2].map(idx => {
    const fees = feeHistory.reward.map(r => Number(BigInt(r[idx])) / 1e9);
    return fees.reduce((s, f) => s + f, 0) / fees.length;
  });

  const nextBaseFee = baseFees[baseFees.length - 1];

  return {
    currentBaseFee: nextBaseFee,
    baseFeeTrend: baseFees.slice(-5),
    fees: {
      low: { maxPriority: rewardAvgs[0], max: nextBaseFee + rewardAvgs[0] },
      medium: { maxPriority: rewardAvgs[1], max: nextBaseFee * 2 + rewardAvgs[1] },
      high: { maxPriority: rewardAvgs[2], max: nextBaseFee * 3 + rewardAvgs[2] }
    }
  };
}

const estimate = await getFeeEstimateUI();
console.log('Base fee:', estimate.currentBaseFee, 'Gwei');
console.log('Low:', estimate.fees.low);
console.log('Medium:', estimate.fees.medium);
console.log('High:', estimate.fees.high);

3. Implement Adaptive Gas Pricing

Build a pricing engine that automatically adjusts fee parameters based on real-time network congestion. When gas utilization ratios spike above 80%, the system shifts to higher priority fees to maintain inclusion speed.

JavaScript
import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-celo-mainnet-archive.n.dwellir.com/YOUR_API_KEY');

async function adaptiveFeeParams(window = 10) {
  const feeHistory = await provider.send('eth_feeHistory', [
    '0x' + window.toString(16),
    'latest',
    [25, 50, 75, 90]
  ]);

  const recentUtilization = feeHistory.gasUsedRatio.slice(-3);
  const avgUtilization = recentUtilization.reduce((s, r) => s + r, 0) / recentUtilization.length;
  const baseFeePerGas = BigInt(feeHistory.baseFeePerGas[window]);

  let priorityFeePercentile;
  let baseFeeMultiplier;

  if (avgUtilization > 0.8) {
    priorityFeePercentile = 3;
    baseFeeMultiplier = 3;
    console.log('High congestion detected, using premium fees');
  } else if (avgUtilization > 0.5) {
    priorityFeePercentile = 2;
    baseFeeMultiplier = 2;
    console.log('Moderate congestion, using standard fees');
  } else {
    priorityFeePercentile = 1;
    baseFeeMultiplier = 2;
    console.log('Low congestion, using economy fees');
  }

  const maxPriorityFeePerGas = feeHistory.reward.reduce(
    (sum, r) => sum + BigInt(r[priorityFeePercentile]), 0n
  ) / BigInt(window);

  return {
    maxPriorityFeePerGas,
    maxFeePerGas: baseFeePerGas * BigInt(baseFeeMultiplier) + maxPriorityFeePerGas,
    congestionLevel: avgUtilization > 0.8 ? 'high' : avgUtilization > 0.5 ? 'moderate' : 'low'
  };
}

const params = await adaptiveFeeParams();
console.log('Adaptive fee params:', params);

Best Practices

  • Use 5-20 blocks of history for accurate fee estimation: fewer blocks miss recent trends, more blocks dilute signal with stale data
  • Calculate maxPriorityFeePerGas from reward percentiles: use the 50th percentile for normal confirmation and the 90th for fast inclusion
  • Multiply baseFeePerGas by 2x as a safety margin for maxFeePerGas: this covers a 12.5% base fee increase per full block over 6 consecutive blocks
  • Cache fee history results with a short TTL of 12 seconds (roughly one block on Celo) to balance freshness with API call efficiency
  • Fall back to eth_gasPrice if eth_feeHistory returns a "method not found" error, indicating the node does not support EIP-1559

Code Examples

Error Handling

Common errors and solutions:

Error CodeDescriptionSolution
-32602Invalid paramsEnsure blockCount is 1-1024, rewardPercentiles is sorted ascending, and values are 0-100
-32601Method not foundThe node may not support EIP-1559: fall back to eth_gasPrice
-32603Internal errorRetry with exponential backoff
-32005Rate limit exceededReduce blockCount or implement caching
-32000Block range unavailableRequested blocks may be pruned: use a smaller range or more recent newestBlock
JavaScript
async function safeFeeHistory(provider, blockCount = 10, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await provider.send('eth_feeHistory', [
        '0x' + blockCount.toString(16),
        'latest',
        [25, 50, 75]
      ]);
    } catch (error) {
      if (error.code === -32602 && blockCount > 1) {
        // Reduce block count and retry
        blockCount = Math.max(1, Math.floor(blockCount / 2));
        continue;
      }
      if (error.code === -32005) {
        await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
        continue;
      }
      if (i === maxRetries - 1) throw error;
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
    }
  }
}