5.4 KiB
gas-estimator
(no submodules)
Purpose
Provides EIP-1559 gas-estimation primitives for Ethereum-style chains. Every helper accepts and returns bigint values so callers never lose precision at the JavaScript number boundary — gas costs in wei routinely exceed Number.MAX_SAFE_INTEGER (2^53 - 1) so passing them as number is a bug waiting to happen. The module covers the four canonical operations: estimating a full GasEstimate from a single set of parameters, computing the EIP-1559 ceiling (2 * baseFee + priority), computing the effective gas price (min(maxFee, baseFee + priority)), and formatting wei values as human-readable gwei or ETH decimal strings.
This module is consumed by wallet UIs, transaction-builder libraries, and analytics dashboards. The bigint-everywhere contract is the headline guarantee.
Features
estimateGas(params)— full EIP-1559 estimator returningGasEstimate(gasLimit, gasPrice, maxFeePerGas, maxPriorityFeePerGas, totalCost). Honours an optionallegacyGasPriceoverride for non-EIP-1559 transactions.calculateMaxFeePerGas(baseFee, priorityFee)— EIP-1559 ceiling formula.calculateEffectiveGasPrice(baseFee, maxFee, priorityFee)—min(maxFee, baseFee + priorityFee).formatGwei(weiValue)— sign-preserving decimal gwei string with trailing-zero trim.estimateTxCostEth(gasLimit, gasPriceWei)— decimal ETH string (18-decimal contraction with trim).- 100%
bigintarithmetic — noNumberconversion anywhere on the hot path. - Universal — no
node:*/bun:*/fs/cryptoimports.
Usage: Basic
import { estimateGas, formatGwei } from "@suaveplan/cryptocurrency";
const estimate = estimateGas({
gasLimit: 21000n,
baseFeePerGas: 30000000000n, // 30 gwei
maxPriorityFeePerGas: 2000000000n, // 2 gwei
});
console.log(formatGwei(estimate.gasPrice)); // "32"
console.log(estimate.totalCost); // 672000000000000n wei = 0.000672 ETH
Usage: Advanced
import {
calculateEffectiveGasPrice,
calculateMaxFeePerGas,
estimateGas,
estimateTxCostEth,
} from "@suaveplan/cryptocurrency";
interface BlockHeader {
baseFeePerGas: bigint;
}
interface UserPreferences {
priorityFee: bigint;
gasLimit: bigint;
}
function quoteUserTransaction(header: BlockHeader, prefs: UserPreferences) {
// Cap our max-fee at 2x base + priority so we don't get gouged on
// sudden base-fee spikes
const maxFee = calculateMaxFeePerGas(header.baseFeePerGas, prefs.priorityFee);
const effective = calculateEffectiveGasPrice(
header.baseFeePerGas,
maxFee,
prefs.priorityFee
);
const estimate = estimateGas({
gasLimit: prefs.gasLimit,
baseFeePerGas: header.baseFeePerGas,
maxPriorityFeePerGas: prefs.priorityFee,
});
return {
...estimate,
capMaxFee: maxFee,
effectivePrice: effective,
humanCost: `${estimateTxCostEth(prefs.gasLimit, effective)} ETH`,
};
}
const quote = quoteUserTransaction(
{ baseFeePerGas: 50000000000n },
{ priorityFee: 2000000000n, gasLimit: 21000n }
);
// { ..., humanCost: "0.000021 * effectivePrice / 10^18 ETH" }
API Reference
| Export | Signature | Returns |
|---|---|---|
estimateGas |
(params: GasEstimateParams) => GasEstimate |
full estimate |
calculateMaxFeePerGas |
(baseFee: bigint, priorityFee: bigint) => bigint |
2 * base + priority |
calculateEffectiveGasPrice |
(baseFee: bigint, maxFee: bigint, priorityFee: bigint) => bigint |
min(maxFee, baseFee + priorityFee) |
formatGwei |
(weiValue: bigint) => string |
decimal gwei, signed, trimmed |
estimateTxCostEth |
(gasLimit: bigint, gasPriceWei: bigint) => string |
decimal ETH, trimmed |
GasEstimate shape
interface GasEstimate {
gasLimit: bigint;
gasPrice: bigint; // legacy override or maxFeePerGas
maxFeePerGas: bigint; // baseFee + priorityFee
maxPriorityFeePerGas: bigint;
totalCost: bigint; // gasLimit * gasPrice
}
Implementation Notes
estimateGas'smaxFeePerGasis computed asbaseFee + priorityFeerather than the EIP-1559 ceiling (2 * base + priority) — the ceiling is computed separately viacalculateMaxFeePerGasbecause some workflows want the conservative target (base + priority) while others want the worst-case ceiling. Callers wanting the ceiling can pass it vialegacyGasPriceto overridegasPrice.formatGweidivides byGWEI = 10^9nand usespadStart(9, "0")to render the fractional part. Trailing zeros are trimmed with/0+$/so1100000000nbecomes"1.1", not"1.100000000".estimateTxCostEthdivides by10^18nand usespadStart(18, "0")for the fractional ETH part. The same trailing-zero trim applies.- Negative wei values in
formatGweiare supported — the absolute value drives the math and the sign is reapplied at the end. estimateTxCostEthdoes not currently support negative inputs (gas refunds are out of scope for this primitive); the upstream library's behaviour is preserved bit-for-bit.- EIP-4844 blob-gas helpers are not included —
calculateBlobGasPriceand friends land inadd-cryptocurrency-blob-gasas called out in the enterprise audit (enterprise/cryptocurrency.md§3). - All arithmetic is
bigint-pure;formatGweiandestimateTxCostEthare the only places where strings are produced, and even those useBigInt.prototype.toStringexclusively.