gas-price-oracle/README.md

7.7 KiB

Gas Price Oracle library for Ethereum dApps GitHub Workflow Status npm

This is a library with a collection of onchain and offchain gas price oracle URLs

Supported networks

Ethereum Mainnet

Current offchain list:

Current onchain list:

Binance Smart Chain

Current offchain list:

Gnosis Chain

Current offchain list:

Polygon (Matic) Network

Current offchain list:

Avalanche C Network

Current offchain list:

Installation

npm i gas-price-oracle or yarn add gas-price-oracle

Import

const { GasPriceOracle } = require('gas-price-oracle')
or
import { GasPriceOracle } from 'gas-price-oracle'

Usage

Configuration

type GasPrice = Record<'instant' | 'fast' | 'standard' | 'low', number>

type EstimatedGasPrice = {
  maxFeePerGas: number
  baseFee: number | undefined
  maxPriorityFeePerGas: number
}

type FallbackGasPrices = {
  gasPrices?: GasPrice
  estimated?: EstimatedGasPrice
}

type GasOracleOptions = {
  chainId?: number
  timeout?: number
  defaultRpc?: string
  blocksCount?: number
  percentile?: number
  blockTime?: number // seconds
  shouldCache?: boolean
  fallbackGasPrices?: FallbackGasPrices
}

const options: GasOracleOptions = {
  chainId: 1,
  percentile: 5, // Which percentile of effective priority fees to include
  blocksCount: 10, // How many blocks to consider for priority fee estimation
  defaultRpc: 'https://api.mycryptoapi.com/eth',
  blockTime: 10, // seconds
  shouldCache: false,
  timeout: 10000, // specifies the number of milliseconds before the request times out.
  minPriority: 0, // specifies the min maxPriorityFeePerGas.
  fallbackGasPrices: {
    gasPrices: {
      instant: 28,
      fast: 22,
      standard: 17,
      low: 11,
    },
    estimated: {
      maxFeePerGas: 20,
      maxPriorityFeePerGas: 3,
    },
  },
}

The Oracle can cache rpc calls

For caching needs to provide to GasOracleOptions

shouldCache: true

blockTime: <Chain block time duration>

EIP-1559 (estimated) gasPrice only

const oracle = new GasPriceOracle({ chainId: 1 })

type EstimatedGasPrice = {
  maxFeePerGas: number
  baseFee: number | undefined
  maxPriorityFeePerGas: number
}

fallbackGasPrices: EstimatedGasPrice = {
  maxFeePerGas: 20,
  maxPriorityFeePerGas: 3,
}

oracle.eip1559.estimateFees(fallbackGasPrices).then((gasPrices: EstimatedGasPrice) => {
  console.log(gasPrices) // { baseFee: 14, maxFeePerGas: 17, maxPriorityFeePerGas: 3 }
})

Legacy gasPrice only

const oracle = new GasPriceOracle({ chainId: 1 })

type GasPrice = Record<'instant' | 'fast' | 'standard' | 'low', number>

fallbackGasPrices: GasPrice = {
  instant: 28,
  fast: 22,
  standard: 17,
  low: 11,
}

oracle.legacy.gasPrices(fallbackGasPrices).then((gasPrices: GasPrice) => {
  console.log(gasPrices) // { instant: 21.5, fast: 19, standard: 17, low: 15 }
})

The oracle.legacy.gasPrices method also accepts shouldGetMedian argument (true) by default. For more details see below. Under the hood it's a combination of fetchMedianGasPriceOffChain(fetchGasPricesOffChain) and fetchGasPricesOnChain methods.

Estimated gasPrices (EIP-1559) and Legacy gasPrice

const oracle = new GasPriceOracle(options)

type GasPriceWithEstimate = {
  gasPrices: GasPrice
  estimate: EstimatedGasPrice
}

type GasPricesWithEstimateInput = {
  shouldGetMedian?: boolean
  fallbackGasPrices?: FallbackGasPrices
}

// optional fallbackGasPrices
const fallbackGasPrices: FallbackGasPrices = {
  gasPrices: {
    instant: 28,
    fast: 22,
    standard: 17,
    low: 11,
  },
  estimated: {
    maxFeePerGas: 20,
    maxPriorityFeePerGas: 3,
  },
}

oracle.gasPricesWithEstimate({ fallbackGasPrices, shouldGetMedian: true }).then((gasPrices: GasPriceWithEstimate) => {
  console.log(gasPrices) // {
  // estimated: { baseFee: 14, maxFeePerGas: 17, maxPriorityFeePerGas: 3 },
  // gasPrices: { instant: 21.5, fast: 19, standard: 17, low: 15 }
  // }}
})

Estimated gasPrices (EIP-1559) or Legacy gasPrice

const oracle = new GasPriceOracle(options)

type GetGasPriceInput = {
  isLegacy?: boolean
  shouldGetMedian?: boolean
  fallbackGasPrices?: GasPrice
}

// optional fallbackGasPrices
const fallbackGasPrices: FallbackGasPrices = {
  gasPrices: {
    instant: 28,
    fast: 22,
    standard: 17,
    low: 11,
  },
  estimated: {
    maxFeePerGas: 20,
    maxPriorityFeePerGas: 3,
  },
}

oracle.gasPrices({ fallbackGasPrices, shouldGetMedian: true }).then((gasPrices: GasPrice | EstimatedGasPrice) => {
  console.log(gasPrices) // {
  // baseFee: 14, maxFeePerGas: 17, maxPriorityFeePerGas: 3 ||
  // instant: 21.5, fast: 19, standard: 17, low: 15
  // }}
})

The gasPrices method also accepts isLegacy argument (false) by default. If isLegacy: true - legacy gasPrice will be provided. If the estimate Gas crashes, legacy gas Price will be provided.

Get transaction gasPrice params

const oracle = new GasPriceOracle(options)

type GetTxGasParamsInput = {
  bumpPercent?: number
  legacySpeed?: GasPriceKey
  isLegacy?: boolean
  shouldGetMedian?: boolean
  fallbackGasPrices?: FallbackGasPrices
}

type GetTxGasParamsRes =
  | {
      gasPrice: number
    }
  | {
      maxFeePerGas: number
      maxPriorityFeePerGas: number
    }

const gasParams: GetTxGasParamsRes = await oracle.getTxGasParams({ legacySpeed: 'fast', bumpPercent: 30 })
console.log(gasParams) // { maxFeePerGas: 17, maxPriorityFeePerGas: 3 } || { gasPrice: 19 }

web3.eth.sendTransaction({
  from: '0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8',
  to: '0xac03bb73b6a9e108530aff4df5077c2b3d481e5a',
  nonce: '0',
  gasLimit: '21000',
  value: '10000000000',
  ...gasParams,
})

bumpPercent argument (0 by default) - response data will increase by bumpPercent%. legacySpeed argument (fast by default) - select the speed of legacy gasPrice.

Offchain oracles only

const oracle = new GasPriceOracle({ chainId: 1 })

// shouldGetMedian: boolean | undefined
oracle.legacy.fetchGasPricesOffChain((shouldGetMedian = true)).then((gasPrices: GasPrice) => {
  console.log(gasPrices) // { instant: 50, fast: 21, standard: 10, low: 3 }
})

Offchain oracles only (get median price)

const oracle = new GasPriceOracle({ chainId: 1 })

oracle.legacy.fetchMedianGasPriceOffChain().then((gasPrices: GasPrice) => {
  console.log(gasPrices) // { instant: 50, fast: 21, standard: 10, low: 3 }
})

This command provides the median gas price of all configured oracles.

Custom RPC URL for onchain oracles

const defaultRpc = 'https://mainnet.infura.io/v3/<API_KEY>'
const oracle = new GasPriceOracle({ defaultRpc, chainId: 1 })

oracle.legacy.fetchGasPricesOnChain().then((gasPrices: number) => {
  console.log(gasPrices) // 21
})

To get gasPrices from a chain outside of the application's chain list (Binance, Gnosis, Polygon, Avalanche), you should enter the rpcUrl into initial GasPriceOracle options_

const defaultRpc = 'https://rpc.goerli.mudit.blog/' // goerli public rpcUrl
const oracle = new GasPriceOracle({ defaultRpc, chainId: 5 })

oracle.gasPrices()