1import { NETWORK_TYPES } from './network';
2import { DEFAULT_GAS_PRICE_GWEI, MAX_GAS_PRICE_GWEI } from './constants';
3import Web3 from 'web3';
5// ethgasstation returns values in floating point, one order of magitude
6// more than gwei. see: https://docs.ethgasstation.info
7// we don't want to charge users more than the gas tank funds
8const minGas = gas => Math.min(gas, MAX_GAS_PRICE_GWEI);
10const feeToWei = fee => Web3.utils.toHex(Web3.utils.toWei(String(fee), 'gwei'));
12// Gwei with milligwei precision, rounded up so we never underpay
13const roundGwei = gwei => Math.ceil(gwei * 1000) / 1000;
15const weiToGwei = wei => roundGwei(wei / 1_000_000_000);
17const calculateMaxFee = (baseFee, maxPriorityFee) =>
18 feeToWei(Math.round(2 * baseFee + maxPriorityFee));
20// Convert seconds to minutes prettily
21const formatWait = wait => Math.round((wait * 100) / 60) / 100;
23export const defaultGasValues = value => ({
28 maxPriorityFeePerGas: Math.min(1, value),
29 suggestedBaseFeePerGas: value > 2 ? value - 1 : 1,
35 maxPriorityFeePerGas: Math.min(1, value),
36 suggestedBaseFeePerGas: value > 2 ? value - 1 : 1,
42 maxPriorityFeePerGas: Math.min(1, value),
43 suggestedBaseFeePerGas: value > 2 ? value - 1 : 1,
47const median = values => {
48 const sorted = [...values].sort((a, b) => a - b);
49 const mid = Math.floor(sorted.length / 2);
50 return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
53// Number of recent blocks to sample, and the priority fee percentiles
54// used for the low, average and fast tiers respectively
55const FEE_HISTORY_BLOCKS = 20;
56const REWARD_PERCENTILES = [10, 50, 90];
57// Floor for the priority fee, since zero tip transactions may never be mined
58const MIN_PRIORITY_FEE_GWEI = 0.001;
60const tierFor = (baseFeeGwei, priorityFeeWei, wait) => {
61 const maxPriorityFeePerGas = Math.max(
62 weiToGwei(priorityFeeWei),
65 const maxFeePerGas = roundGwei(baseFeeGwei + maxPriorityFeePerGas);
67 price: minGas(maxFeePerGas),
68 wait: formatWait(wait),
71 suggestedBaseFeePerGas: baseFeeGwei,
75// Estimates fees from the connected node via eth_feeHistory, in the same
76// manner as wallets do. See: https://docs.alchemy.com/docs/how-to-build-a-gas-fee-estimator-using-eip-1559
77const getGasForNetwork = async web3 => {
79 const history = await web3.eth.getFeeHistory(
85 // baseFeePerGas includes one extra entry: the base fee of the next block
86 const nextBaseFeeWei = Number(history.baseFeePerGas.at(-1));
87 const baseFeeGwei = nextBaseFeeWei / 1_000_000_000;
89 const [low, average, fast] = REWARD_PERCENTILES.map((_, i) =>
90 median(history.reward.map(rewards => Number(rewards[i])))
94 fast: tierFor(baseFeeGwei, fast, 15),
95 average: tierFor(baseFeeGwei, average, 60),
96 low: tierFor(baseFeeGwei, low, 180),
100 return defaultGasValues(DEFAULT_GAS_PRICE_GWEI);
104export default async function getSuggestedGasPrice(networkType, web3) {
105 if (networkType === NETWORK_TYPES.OFFLINE || !web3) {
106 return defaultGasValues(DEFAULT_GAS_PRICE_GWEI);
109 return getGasForNetwork(web3);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list