aboutsummaryrefslogblamecommitdiffstats
path: root/ui/app/selectors/custom-gas.js
blob: d5a3972df156c2883210bbbd6280081989bcea1f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12

                                          









                                            





                                                           



                                              
                   
                     


                    
                                           

                                   


                                  



                          

                                    

                                     


                                    
                                   

 











                                                   









                                                                                     









                                               
                                                                                  



                                                           
                     


    
                                                                         

                              
                                                                             



                       
 


























































                                                                                                    

                                                                           


































                                                                                                                  
 













                                                                           
























                                                                                                                    
import { pipe, partialRight } from 'ramda'
import {
  conversionUtil,
  multiplyCurrencies,
} from '../conversion-util'
import {
  getCurrentCurrency,
} from '../selectors'
import {
  formatCurrency,
} from '../helpers/confirm-transaction/util'
import {
  decEthToConvertedCurrency as ethTotalToConvertedCurrency,
} from '../helpers/conversions.util'
import {
  formatETHFee,
} from '../helpers/formatters'
import {
  calcGasTotal,
} from '../components/send/send.utils'
import { addHexPrefix } from 'ethereumjs-util'

const selectors = {
  getCustomGasErrors,
  getCustomGasLimit,
  getCustomGasPrice,
  getCustomGasTotal,
  getRenderableEstimateDataForSmallButtons,
  getRenderableBasicEstimateData,
  getBasicGasEstimateLoadingStatus,
  getAveragePriceEstimateInHexWEI,
  getDefaultActiveButtonIndex,
  priceEstimateToWei,
}

module.exports = selectors

const NUMBER_OF_DECIMALS_SM_BTNS = 5

function getCustomGasErrors (state) {
  return state.gas.errors
}

function getCustomGasLimit (state) {
  return state.gas.customData.limit
}

function getCustomGasPrice (state) {
  return state.gas.customData.price
}

function getCustomGasTotal (state) {
  return state.gas.customData.total
}

function getBasicGasEstimateLoadingStatus (state) {
  return state.gas.basicEstimateIsLoading
}

function getAveragePriceEstimateInHexWEI (state) {
  const averagePriceEstimate = state.gas.basicEstimates.average
  return getGasPriceInHexWei(averagePriceEstimate || '0x0')
}

function getDefaultActiveButtonIndex (gasButtonInfo, customGasPriceInHex, gasPrice) {
  return gasButtonInfo.findIndex(({ priceInHexWei }) => {
    return priceInHexWei === addHexPrefix(customGasPriceInHex || gasPrice)
  })
}

function apiEstimateModifiedToGWEI (estimate) {
  return multiplyCurrencies(estimate, 0.10, {
    toNumericBase: 'hex',
    multiplicandBase: 10,
    multiplierBase: 10,
    numberOfDecimals: 9,
  })
}

function basicPriceEstimateToETHTotal (estimate, gasLimit, numberOfDecimals = 9) {
  return conversionUtil(calcGasTotal(gasLimit, estimate), {
    fromNumericBase: 'hex',
    toNumericBase: 'dec',
    fromDenomination: 'GWEI',
    numberOfDecimals,
  })
}

function getRenderableEthFee (estimate, gasLimit, numberOfDecimals = 9) {
  return pipe(
    apiEstimateModifiedToGWEI,
    partialRight(basicPriceEstimateToETHTotal, [gasLimit, numberOfDecimals]),
    formatETHFee
  )(estimate, gasLimit)
}


function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) {
  return pipe(
    apiEstimateModifiedToGWEI,
    partialRight(basicPriceEstimateToETHTotal, [gasLimit]),
    partialRight(ethTotalToConvertedCurrency, [convertedCurrency, conversionRate]),
    partialRight(formatCurrency, [convertedCurrency])
  )(estimate, gasLimit, convertedCurrency, conversionRate)
}

function getTimeEstimateInSeconds (blockWaitEstimate, currentBlockTime) {
  return multiplyCurrencies(blockWaitEstimate, currentBlockTime, {
    toNumericBase: 'dec',
    multiplicandBase: 10,
    multiplierBase: 10,
    numberOfDecimals: 1,
  })
}

function formatTimeEstimate (totalSeconds) {
  const minutes = Math.floor(totalSeconds / 60)
  const seconds = Math.floor(totalSeconds % 60)
  const formattedMin = `${minutes ? minutes + ' min' : ''}`
  const formattedSec = `${seconds ? seconds + ' sec' : ''}`
  const formattedCombined = formattedMin && formattedSec
    ? `~${formattedMin} ${formattedSec}`
    : '~' + [formattedMin, formattedSec].find(t => t)

  return formattedCombined
}

function getRenderableTimeEstimate (blockWaitEstimate, currentBlockTime) {
  return pipe(
    getTimeEstimateInSeconds,
    formatTimeEstimate
  )(blockWaitEstimate, currentBlockTime)
}

function priceEstimateToWei (priceEstimate) {
  return conversionUtil(priceEstimate, {
    fromNumericBase: 'hex',
    toNumericBase: 'hex',
    fromDenomination: 'GWEI',
    toDenomination: 'WEI',
    numberOfDecimals: 9,
  })
}

function getGasPriceInHexWei (price) {
  return pipe(
    apiEstimateModifiedToGWEI,
    priceEstimateToWei,
    addHexPrefix
  )(price)
}

function getRenderableBasicEstimateData (state) {
  if (getBasicGasEstimateLoadingStatus(state)) {
    return []
  }
  const gasLimit = state.metamask.send.gasLimit || getCustomGasLimit(state)
  const conversionRate = state.metamask.conversionRate
  const currentCurrency = getCurrentCurrency(state)
  const {
    gas: {
      basicEstimates: {
        safeLow,
        average,
        fast,
        blockTime,
        safeLowWait,
        avgWait,
        fastWait,
      },
    },
  } = state

  return [
    {
      feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate),
      feeInSecondaryCurrency: getRenderableEthFee(fast, gasLimit),
      timeEstimate: getRenderableTimeEstimate(fastWait, blockTime),
      priceInHexWei: getGasPriceInHexWei(fast),
    },
    {
      feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(average, gasLimit, currentCurrency, conversionRate),
      feeInSecondaryCurrency: getRenderableEthFee(average, gasLimit),
      timeEstimate: getRenderableTimeEstimate(avgWait, blockTime),
      priceInHexWei: getGasPriceInHexWei(average),
    },
    {
      feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate),
      feeInSecondaryCurrency: getRenderableEthFee(safeLow, gasLimit),
      timeEstimate: getRenderableTimeEstimate(safeLowWait, blockTime),
      priceInHexWei: getGasPriceInHexWei(safeLow),
    },
  ]
}

function getRenderableEstimateDataForSmallButtons (state) {
  if (getBasicGasEstimateLoadingStatus(state)) {
    return []
  }
  const gasLimit = state.metamask.send.gasLimit || getCustomGasLimit(state)
  const conversionRate = state.metamask.conversionRate
  const currentCurrency = getCurrentCurrency(state)
  const {
    gas: {
      basicEstimates: {
        safeLow,
        average,
        fast,
      },
    },
  } = state

  return [
    {
      labelKey: 'fast',
      feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate),
      feeInPrimaryCurrency: getRenderableEthFee(fast, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS),
      priceInHexWei: getGasPriceInHexWei(fast),
    },
    {
      labelKey: 'average',
      feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(average, gasLimit, currentCurrency, conversionRate),
      feeInPrimaryCurrency: getRenderableEthFee(average, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS),
      priceInHexWei: getGasPriceInHexWei(average),
    },
    {
      labelKey: 'slow',
      feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate),
      feeInPrimaryCurrency: getRenderableEthFee(safeLow, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS),
      priceInHexWei: getGasPriceInHexWei(safeLow),
    },
  ]
}