Skip to main content

Try it Live

Run MaxFeePerGas examples in the interactive playground

MaxFeePerGas

EIP-1559 maximum fee per gas representing the maximum total gas price a user is willing to pay for transaction inclusion. Must be >= baseFeePerGas + maxPriorityFeePerGas for transaction to be included.

Overview

Branded bigint type representing max fee in Wei. Acts as a cap on total gas spending. Excess (maxFee - actualPrice) is refunded to sender.

Quick Start

import * as MaxFeePerGas from './primitives/MaxFeePerGas/index.js';

// Set maximum fee
const maxFee = MaxFeePerGas.fromGwei(100n); // Willing to pay up to 100 Gwei
console.log(MaxFeePerGas.toWei(maxFee)); // 100000000000n

// From hex (RPC format)
const fee = MaxFeePerGas.from("0x174876e800");
console.log(MaxFeePerGas.toGwei(fee)); // 100n

Type Definition

type MaxFeePerGasType = bigint & { readonly [brand]: "MaxFeePerGas" };
Branded bigint preventing confusion with other fee types. All values in Wei.

API

Construction

from(value)

Create from bigint, number, or hex string.
const fee1 = MaxFeePerGas.from(100000000000n);
const fee2 = MaxFeePerGas.from("0x174876e800");
const fee3 = MaxFeePerGas.from(100000000000);

fromGwei(gwei)

Create from Gwei value.
const fee = MaxFeePerGas.fromGwei(100n); // 100000000000n Wei

fromWei(wei)

Create from Wei value (alias for from).
const fee = MaxFeePerGas.fromWei(100000000000n);

Conversion

toGwei(maxFee)

Convert to Gwei.
const fee = MaxFeePerGas.from(100000000000n);
MaxFeePerGas.toGwei(fee); // 100n

toWei(maxFee)

Convert to Wei (identity).
MaxFeePerGas.toWei(fee); // 100000000000n

toNumber(maxFee)

Convert to number. Warning: precision loss on large values.
MaxFeePerGas.toNumber(fee); // 100000000000

toBigInt(maxFee)

Convert to bigint (identity).
MaxFeePerGas.toBigInt(fee); // 100000000000n

Comparison

equals(maxFee1, maxFee2)

Check equality.
const fee1 = MaxFeePerGas.from(100000000000n);
const fee2 = MaxFeePerGas.from(100000000000n);
MaxFeePerGas.equals(fee1, fee2); // true

compare(maxFee1, maxFee2)

Compare values. Returns -1, 0, or 1.
const fee1 = MaxFeePerGas.from(100000000000n);
const fee2 = MaxFeePerGas.from(120000000000n);
MaxFeePerGas.compare(fee1, fee2); // -1

Fee Setting Strategies

Conservative

Set maxFee slightly above current base fee:
const baseFee = BaseFeePerGas.fromGwei(25n);
const buffer = 1.2; // 20% buffer
const maxFee = MaxFeePerGas.fromGwei(
  BigInt(Math.ceil(Number(BaseFeePerGas.toGwei(baseFee)) * buffer))
);
// maxFee = 30 Gwei

Normal

Set maxFee with reasonable headroom:
const baseFee = BaseFeePerGas.fromGwei(25n);
const maxFee = MaxFeePerGas.fromGwei(
  BaseFeePerGas.toGwei(baseFee) * 2n
);
// maxFee = 50 Gwei

Aggressive

Set high maxFee for guaranteed inclusion:
const maxFee = MaxFeePerGas.fromGwei(200n);
// Will be included even if base fee spikes

Real-world Examples

Transaction Submission

import * as BaseFeePerGas from './primitives/BaseFeePerGas/index.js';
import * as MaxFeePerGas from './primitives/MaxFeePerGas/index.js';
import * as MaxPriorityFeePerGas from './primitives/MaxPriorityFeePerGas/index.js';

// Get current base fee
const block = await provider.getBlock('latest');
const baseFee = BaseFeePerGas.from(block.baseFeePerGas);

// Set fees with buffer
const priorityFee = MaxPriorityFeePerGas.fromGwei(2n);
const maxFee = MaxFeePerGas.fromGwei(
  BaseFeePerGas.toGwei(baseFee) * 2n + 2n
);

// Build transaction
const tx = {
  to: '0x...',
  value: 0n,
  maxFeePerGas: MaxFeePerGas.toWei(maxFee),
  maxPriorityFeePerGas: MaxPriorityFeePerGas.toWei(priorityFee),
  gasLimit: 21000n,
};

Fee Validation

// Ensure maxFee can cover base + priority
const baseFee = BaseFeePerGas.fromGwei(25n);
const maxFee = MaxFeePerGas.fromGwei(100n);
const priorityFee = MaxPriorityFeePerGas.fromGwei(2n);

const minRequired = baseFee + priorityFee;
if (maxFee < minRequired) {
  throw new Error('maxFee too low for inclusion');
}

Fee Estimation

// Historical base fee analysis
async function estimateMaxFee(provider, blocks = 10): Promise<bigint> {
  const fees: bigint[] = [];

  for (let i = 0; i < blocks; i++) {
    const block = await provider.getBlock(-i); // Last N blocks
    fees.push(BaseFeePerGas.from(block.baseFeePerGas));
  }

  // Use 95th percentile + buffer
  fees.sort((a, b) => Number(a - b));
  const p95 = fees[Math.floor(fees.length * 0.95)];

  return MaxFeePerGas.fromGwei(
    BaseFeePerGas.toGwei(p95) * 2n
  );
}

Common Patterns

Fee Levels

// Priority levels
const fees = {
  slow: MaxFeePerGas.fromGwei(50n),      // 30min+
  normal: MaxFeePerGas.fromGwei(100n),    // ~5min
  fast: MaxFeePerGas.fromGwei(150n),      // ~1min
  instant: MaxFeePerGas.fromGwei(300n),   // Next block
};

Dynamic Adjustment

// Adjust based on network conditions
async function getRecommendedMaxFee(urgency: 'low' | 'medium' | 'high') {
  const block = await provider.getBlock('latest');
  const baseFee = BaseFeePerGas.from(block.baseFeePerGas);

  const multipliers = { low: 1.5, medium: 2, high: 3 };
  const multiplier = multipliers[urgency];

  return MaxFeePerGas.fromGwei(
    BaseFeePerGas.toGwei(baseFee) * BigInt(multiplier)
  );
}

Refund Mechanics

Unused portion of maxFee is refunded:
const maxFee = MaxFeePerGas.fromGwei(100n);
const actualPrice = EffectiveGasPrice.fromGwei(27n); // base 25 + tip 2
const gasUsed = 21000n;

const charged = maxFee * gasUsed;        // 2100000000000000n
const actualCost = actualPrice * gasUsed; // 567000000000000n
const refund = charged - actualCost;      // 1533000000000000n refunded

Specification