CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wagmi

React Hooks for Ethereum providing reactive primitives for wallet connections, smart contract interactions, and blockchain data

Pending
Overview
Eval results
Files

gas-fees.mddocs/

Gas & Fee Estimation

Gas price monitoring and transaction fee estimation with support for EIP-1559 fee markets. This module provides comprehensive gas and fee estimation functionality for optimal transaction pricing and network cost management.

Capabilities

useEstimateGas

Hook to estimate gas required for a transaction before sending it.

/**
 * Hook to estimate gas for transaction
 * @param parameters - Gas estimation parameters
 * @returns Estimated gas amount required for the transaction
 */
function useEstimateGas<config = Config, selectData = UseEstimateGasReturnType>(
  parameters: UseEstimateGasParameters<config, selectData>
): UseEstimateGasReturnType<selectData>;

interface UseEstimateGasParameters<config = Config, selectData = UseEstimateGasReturnType> {
  /** Recipient address */
  to: Address;
  /** Transaction value */
  value?: bigint;
  /** Transaction data */
  data?: Hex;
  /** Account to estimate from */
  account?: Address;
  /** Block number to estimate at */
  blockNumber?: bigint;
  blockTag?: 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized';
  /** Chain to use */
  chainId?: config['chains'][number]['id'];
  /** Gas price for estimation */
  gasPrice?: bigint;
  /** Max fee per gas */
  maxFeePerGas?: bigint;
  /** Max priority fee per gas */
  maxPriorityFeePerGas?: bigint;
  /** Nonce */
  nonce?: number;
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    select?: (data: UseEstimateGasReturnType) => selectData;
  };
}

type UseEstimateGasReturnType = bigint;

Usage Example:

import { useEstimateGas, useSendTransaction } from "wagmi";
import { parseEther, formatGwei } from "viem";

function GasEstimationExample() {
  const transactionParams = {
    to: '0x742d35Cc6634C0532925a3b8D' as const,
    value: parseEther('0.1'),
  };

  const { data: gasEstimate, isLoading } = useEstimateGas(transactionParams);
  const { sendTransaction } = useSendTransaction();

  const handleSend = () => {
    sendTransaction({
      ...transactionParams,
      gas: gasEstimate, // Use estimated gas
    });
  };

  return (
    <div>
      {isLoading ? (
        <p>Estimating gas...</p>
      ) : (
        <div>
          <p>Estimated gas: {gasEstimate?.toString()}</p>
          <button onClick={handleSend}>Send with estimated gas</button>
        </div>
      )}
    </div>
  );
}

useGasPrice

Hook to get current network gas price for legacy transactions.

/**
 * Hook to get current gas price
 * @param parameters - Gas price query parameters
 * @returns Current network gas price in wei
 */
function useGasPrice<config = Config, selectData = UseGasPriceReturnType>(
  parameters?: UseGasPriceParameters<config, selectData>
): UseGasPriceReturnType<selectData>;

interface UseGasPriceParameters<config = Config, selectData = UseGasPriceReturnType> {
  /** Chain to get gas price for */
  chainId?: config['chains'][number]['id'];
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    refetchInterval?: number;
    select?: (data: UseGasPriceReturnType) => selectData;
  };
}

type UseGasPriceReturnType = bigint;

useEstimateFeesPerGas

Hook to estimate fees per gas for EIP-1559 transactions (replaces legacy gas price).

/**
 * Hook to estimate fees per gas (replaces useFeeData)
 * @param parameters - Fee estimation parameters
 * @returns Fee estimates for EIP-1559 transactions
 */
function useEstimateFeesPerGas<config = Config, selectData = UseEstimateFeesPerGasReturnType>(
  parameters?: UseEstimateFeesPerGasParameters<config, selectData>
): UseEstimateFeesPerGasReturnType<selectData>;

interface UseEstimateFeesPerGasParameters<config = Config, selectData = UseEstimateFeesPerGasReturnType> {
  /** Fee multiplier for priority adjustment */
  formatUnits?: 'wei' | 'gwei';
  /** Transaction type hint */
  type?: 'legacy' | 'eip1559';
  /** Chain to estimate fees for */
  chainId?: config['chains'][number]['id'];
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    refetchInterval?: number;
    select?: (data: UseEstimateFeesPerGasReturnType) => selectData;
  };
}

interface UseEstimateFeesPerGasReturnType {
  /** Legacy gas price */
  gasPrice?: bigint;
  /** Max fee per gas (EIP-1559) */
  maxFeePerGas?: bigint;
  /** Max priority fee per gas (EIP-1559) */
  maxPriorityFeePerGas?: bigint;
}

Usage Example:

import { useEstimateFeesPerGas } from "wagmi";
import { formatGwei } from "viem";

function FeeEstimation() {
  const { data: feeData, isLoading } = useEstimateFeesPerGas();

  if (isLoading) return <div>Loading fee estimates...</div>;

  return (
    <div>
      <h3>Current Fee Estimates</h3>
      {feeData?.gasPrice && (
        <p>Gas Price: {formatGwei(feeData.gasPrice)} gwei</p>
      )}
      {feeData?.maxFeePerGas && (
        <p>Max Fee: {formatGwei(feeData.maxFeePerGas)} gwei</p>
      )}
      {feeData?.maxPriorityFeePerGas && (
        <p>Max Priority Fee: {formatGwei(feeData.maxPriorityFeePerGas)} gwei</p>
      )}
    </div>
  );
}

useEstimateMaxPriorityFeePerGas

Hook to estimate the maximum priority fee per gas for EIP-1559 transactions.

/**
 * Hook to estimate max priority fee per gas
 * @param parameters - Max priority fee estimation parameters
 * @returns Estimated maximum priority fee per gas
 */
function useEstimateMaxPriorityFeePerGas<config = Config, selectData = UseEstimateMaxPriorityFeePerGasReturnType>(
  parameters?: UseEstimateMaxPriorityFeePerGasParameters<config, selectData>
): UseEstimateMaxPriorityFeePerGasReturnType<selectData>;

interface UseEstimateMaxPriorityFeePerGasParameters<config = Config, selectData = UseEstimateMaxPriorityFeePerGasReturnType> {
  /** Chain to estimate for */
  chainId?: config['chains'][number]['id'];
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    refetchInterval?: number;
    select?: (data: UseEstimateMaxPriorityFeePerGasReturnType) => selectData;
  };
}

type UseEstimateMaxPriorityFeePerGasReturnType = bigint;

useFeeHistory

Hook to get historical fee data for analysis and prediction.

/**
 * Hook to get fee history
 * @param parameters - Fee history query parameters
 * @returns Historical fee data for the specified block range
 */
function useFeeHistory<config = Config, selectData = UseFeeHistoryReturnType>(
  parameters: UseFeeHistoryParameters<config, selectData>
): UseFeeHistoryReturnType<selectData>;

interface UseFeeHistoryParameters<config = Config, selectData = UseFeeHistoryReturnType> {
  /** Number of blocks to fetch history for */
  blockCount: number;
  /** Newest block number or tag */
  newestBlock?: bigint | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized';
  /** Reward percentiles to calculate */
  rewardPercentiles?: number[];
  /** Chain to get history for */
  chainId?: config['chains'][number]['id'];
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    select?: (data: UseFeeHistoryReturnType) => selectData;
  };
}

interface UseFeeHistoryReturnType {
  /** Base fee per gas for each block */
  baseFeePerGas: bigint[];
  /** Gas used ratio for each block */
  gasUsedRatio: number[];
  /** Oldest block number in the range */
  oldestBlock: bigint;
  /** Reward percentiles for each block */
  reward?: bigint[][];
}

Usage Example:

import { useFeeHistory } from "wagmi";
import { formatGwei } from "viem";

function FeeAnalytics() {
  const { data: feeHistory, isLoading } = useFeeHistory({
    blockCount: 10, // Last 10 blocks
    rewardPercentiles: [25, 50, 75], // 25th, 50th, 75th percentiles
  });

  if (isLoading) return <div>Loading fee history...</div>;

  const avgBaseFee = feeHistory?.baseFeePerGas.reduce((sum, fee) => sum + fee, 0n) 
    / BigInt(feeHistory?.baseFeePerGas.length || 1);

  return (
    <div>
      <h3>Fee Analytics</h3>
      <p>Average Base Fee: {formatGwei(avgBaseFee || 0n)} gwei</p>
      <p>Latest Block: {feeHistory?.oldestBlock.toString()}</p>
      
      <h4>Recent Base Fees</h4>
      {feeHistory?.baseFeePerGas.map((fee, i) => (
        <div key={i}>
          Block {(feeHistory.oldestBlock + BigInt(i)).toString()}: {formatGwei(fee)} gwei
        </div>
      ))}
    </div>
  );
}

Advanced Fee Management

Dynamic Fee Calculator

import { 
  useEstimateFeesPerGas, 
  useFeeHistory, 
  useEstimateGas 
} from "wagmi";
import { formatGwei, parseGwei } from "viem";

interface FeeSpeed {
  name: string;
  multiplier: number;
  description: string;
}

const FEE_SPEEDS: FeeSpeed[] = [
  { name: 'Slow', multiplier: 0.9, description: '~5 min' },
  { name: 'Standard', multiplier: 1.0, description: '~2 min' },
  { name: 'Fast', multiplier: 1.1, description: '~30 sec' },
  { name: 'Urgent', multiplier: 1.25, description: '~15 sec' },
];

function DynamicFeeCalculator({ 
  transactionParams 
}: { 
  transactionParams: { to: Address; value?: bigint; data?: Hex } 
}) {
  const { data: currentFees } = useEstimateFeesPerGas();
  const { data: gasEstimate } = useEstimateGas(transactionParams);
  
  const { data: feeHistory } = useFeeHistory({
    blockCount: 5,
    rewardPercentiles: [10, 50, 90],
  });

  const calculateFeeOptions = () => {
    if (!currentFees?.maxFeePerGas || !currentFees?.maxPriorityFeePerGas) {
      return [];
    }

    return FEE_SPEEDS.map(speed => {
      const maxPriorityFee = currentFees.maxPriorityFeePerGas! * BigInt(Math.floor(speed.multiplier * 100)) / 100n;
      const maxFee = currentFees.maxFeePerGas! * BigInt(Math.floor(speed.multiplier * 100)) / 100n;
      
      const estimatedCost = gasEstimate ? (gasEstimate * maxFee) : 0n;

      return {
        ...speed,
        maxFeePerGas: maxFee,
        maxPriorityFeePerGas: maxPriorityFee,
        estimatedCost,
      };
    });
  };

  const feeOptions = calculateFeeOptions();

  return (
    <div>
      <h3>Transaction Fee Options</h3>
      {feeOptions.map((option, i) => (
        <div key={i} className="fee-option">
          <h4>{option.name} ({option.description})</h4>
          <p>Max Fee: {formatGwei(option.maxFeePerGas)} gwei</p>
          <p>Priority Fee: {formatGwei(option.maxPriorityFeePerGas)} gwei</p>
          {option.estimatedCost > 0n && (
            <p>Est. Cost: {formatEther(option.estimatedCost)} ETH</p>
          )}
        </div>
      ))}
    </div>
  );
}

Fee Monitoring Component

import { useEstimateFeesPerGas, useGasPrice } from "wagmi";
import { formatGwei } from "viem";
import { useEffect, useState } from "react";

function FeeMonitor() {
  const [feeHistory, setFeeHistory] = useState<bigint[]>([]);
  
  const { data: currentFees } = useEstimateFeesPerGas({
    query: { refetchInterval: 10000 } // Update every 10 seconds
  });

  const { data: gasPrice } = useGasPrice({
    query: { refetchInterval: 10000 }
  });

  useEffect(() => {
    if (currentFees?.maxFeePerGas) {
      setFeeHistory(prev => [...prev.slice(-19), currentFees.maxFeePerGas!]);
    }
  }, [currentFees]);

  const avgFee = feeHistory.length > 0 
    ? feeHistory.reduce((sum, fee) => sum + fee, 0n) / BigInt(feeHistory.length)
    : 0n;

  const minFee = feeHistory.length > 0 ? feeHistory.reduce((min, fee) => fee < min ? fee : min) : 0n;
  const maxFee = feeHistory.length > 0 ? feeHistory.reduce((max, fee) => fee > max ? fee : max) : 0n;

  return (
    <div className="fee-monitor">
      <h3>Network Fee Monitor</h3>
      
      <div className="current-fees">
        <h4>Current Fees</h4>
        {gasPrice && <p>Gas Price: {formatGwei(gasPrice)} gwei</p>}
        {currentFees?.maxFeePerGas && (
          <p>Max Fee: {formatGwei(currentFees.maxFeePerGas)} gwei</p>
        )}
        {currentFees?.maxPriorityFeePerGas && (
          <p>Priority Fee: {formatGwei(currentFees.maxPriorityFeePerGas)} gwei</p>
        )}
      </div>

      {feeHistory.length > 0 && (
        <div className="fee-stats">
          <h4>Fee Statistics (Last {feeHistory.length} updates)</h4>
          <p>Average: {formatGwei(avgFee)} gwei</p>
          <p>Min: {formatGwei(minFee)} gwei</p>
          <p>Max: {formatGwei(maxFee)} gwei</p>
        </div>
      )}
    </div>
  );
}

Common Types

type Address = `0x${string}`;
type Hex = `0x${string}`;

interface GasEstimate {
  /** Estimated gas units */
  gas: bigint;
  /** Estimated cost in wei */
  cost: bigint;
}

interface FeeData {
  /** Legacy gas price */
  gasPrice?: bigint;
  /** EIP-1559 max fee per gas */
  maxFeePerGas?: bigint;
  /** EIP-1559 max priority fee per gas */
  maxPriorityFeePerGas?: bigint;
  /** Last base fee per gas */
  lastBaseFeePerGas?: bigint;
}

interface FeeSuggestion {
  /** Suggested priority fee */
  maxPriorityFeePerGas: bigint;
  /** Suggested max fee */
  maxFeePerGas: bigint;
  /** Expected confirmation time */
  estimatedTime: string;
  /** Confidence level */
  confidence: 'low' | 'medium' | 'high';
}

Install with Tessl CLI

npx tessl i tessl/npm-wagmi

docs

account.md

advanced.md

batch.md

blockchain.md

contracts.md

ens.md

gas-fees.md

index.md

signing.md

transactions.md

watch.md

tile.json