first commit
This commit is contained in:
119
docs/money/finance/cryptocurrency/src/gas/gas-estimator.md
Normal file
119
docs/money/finance/cryptocurrency/src/gas/gas-estimator.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# gas-estimator
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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 returning `GasEstimate` (gasLimit, gasPrice, maxFeePerGas, maxPriorityFeePerGas, totalCost). Honours an optional `legacyGasPrice` override 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% `bigint` arithmetic — no `Number` conversion anywhere on the hot path.
|
||||
- Universal — no `node:*` / `bun:*` / `fs` / `crypto` imports.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
interface GasEstimate {
|
||||
gasLimit: bigint;
|
||||
gasPrice: bigint; // legacy override or maxFeePerGas
|
||||
maxFeePerGas: bigint; // baseFee + priorityFee
|
||||
maxPriorityFeePerGas: bigint;
|
||||
totalCost: bigint; // gasLimit * gasPrice
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- `estimateGas`'s `maxFeePerGas` is computed as `baseFee + priorityFee` rather than the EIP-1559 ceiling (`2 * base + priority`) — the ceiling is computed separately via `calculateMaxFeePerGas` because some workflows want the conservative target (`base + priority`) while others want the worst-case ceiling. Callers wanting the ceiling can pass it via `legacyGasPrice` to override `gasPrice`.
|
||||
- `formatGwei` divides by `GWEI = 10^9n` and uses `padStart(9, "0")` to render the fractional part. Trailing zeros are trimmed with `/0+$/` so `1100000000n` becomes `"1.1"`, not `"1.100000000"`.
|
||||
- `estimateTxCostEth` divides by `10^18n` and uses `padStart(18, "0")` for the fractional ETH part. The same trailing-zero trim applies.
|
||||
- Negative wei values in `formatGwei` are supported — the absolute value drives the math and the sign is reapplied at the end.
|
||||
- `estimateTxCostEth` does 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 — `calculateBlobGasPrice` and friends land in `add-cryptocurrency-blob-gas` as called out in the enterprise audit (`enterprise/cryptocurrency.md` §3).
|
||||
- All arithmetic is `bigint`-pure; `formatGwei` and `estimateTxCostEth` are the only places where strings are produced, and even those use `BigInt.prototype.toString` exclusively.
|
||||
Reference in New Issue
Block a user