aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/selectors/custom-gas.js
diff options
context:
space:
mode:
authorThomas Huang <tmashuang@users.noreply.github.com>2018-12-12 06:56:47 +0800
committerDan Finlay <542863+danfinlay@users.noreply.github.com>2018-12-12 06:56:47 +0800
commit2f5abd9ad8ac64c16edcc0d9fff923e62c5ca984 (patch)
tree16d323cd3325b1b9121434e86c3047dc333c2b1d /ui/app/selectors/custom-gas.js
parented9bfdcebd5eed1d749f275f9d388ea0dd8f8275 (diff)
downloadtangerine-wallet-browser-2f5abd9ad8ac64c16edcc0d9fff923e62c5ca984.tar.gz
tangerine-wallet-browser-2f5abd9ad8ac64c16edcc0d9fff923e62c5ca984.tar.zst
tangerine-wallet-browser-2f5abd9ad8ac64c16edcc0d9fff923e62c5ca984.zip
Version Bump (#5909)v5.2.0
* Adds new gas customization modal container (without content) * Adds the content of the advanced tab - w/o chart or dynamic content - to gas customize modal. * Use correct message key in gas-modal-page-container.component.js * Use BEM for css in gas-modal-page-container * Split advanced-tab-content.component.js render() method into smaller pieces; add translations to the same file. * Remove gas slider from advance-tab-content.component * Add tests for advanced-tab-component.js and subcomponents. * Improve styling of advanced-tab-content gasInput row * Adds basic tab content to gas customizer, with styled button group (static, for now). * Connect the gas-button-group component to redux and a live api. * Improvements to propdefaults in button-group.component and basic-tab-content.component * Styling fixes for gas customization advanced tab content. * Adds gas-duck.test.js tests. * Connects remained of the gas customization component to redux. * Integrate gas buttons with the send screen. * Test updates and additions for button integration with send screen. * Adds redesign for the customize gas advanced tab. * Adds not yet functional gas price chart. * Gas price chart improvements, redesign, bug fixes, and set up to receive external data * Read only connection of gas price chart to redux * Clean up for advanced gas tab customization changes. * Complete integration of gas chart with redux. * Add control arrows to advanced gas tab inputs. * Lint and unit test fixes. * Clean up gas chart code. * Update tests, plus some lint fixes, for gas-price-chart * Improve data management and tests for gas-modal-page-container price estimates. * Clean up for mmui-i11-custom-gas-price-chart branch * Redesign of gas customization basic tab. * Adds createSpeedUpTransaction to txController * Connect gas price chart to gas station api. * Adds speed up slide-in gas customization sidebar * Update e2e tests for new gas customization modal. * Fixes for components that break e2e gas customization tests, plus unit test updates. * Remove gas customization integration tests (in favour of e2e tests) * Add gas data to integration test json data set. * Add c3 and d3 to the separate dependencies bundle. * Make gas customization modal responsive. * Fix "fastest" translation message; change to sentence case * Uses more reliable api on main send screen; caches basic api results in modal * Add loading spinners when waiting for APIs in the gas customization modal * Modify results of API data to better fit gas chart: remove outliers, pad data * Clear custom gas data on hiding of gas customization modal. * Improve responsiveness of customize speed up slider. * Final gas customization fixes * Fix styling of send screen in extension view when hex data on. * Replace height: 100% rule with workaround for flexbox quirks * Fill in more Polish message translations * Update lockfile to fix errors npm has informed me that the lockfile has "errors": npm ERR! code ELOCKVERIFY npm ERR! Errors were found in your package-lock.json, run npm install to fix them. npm ERR! Missing: c3@^0.6.7 npm ERR! Invalid: lock file's d3@3.5.17 does not satisfy d3@^5.7.0 * circleci: Disable npm audit when installing packages Auditing packages when installing here doesn't help anyone as the summary isn't visible and vulnerabilities don't produce a non-zero exit code. We will have `npm audit` as an extra CI job. * npm audit fix * circleci: Replace nsp with npm audit Refs #4751 * Remove beefy dependency and its usages Refs #4768 Refs #5389 This changeset removes the beefy package that: 1. Was last published 2 yrs ago 2. Brought with it 1 moderate and 1 critical vulnerability 3. Was only used in scripts that no longer work * npm uninstall open * Update ganache-core to mitigate vuln === npm audit security report === > # Run npm install --save-dev ganache-core@2.3.1 to resolve 1 vulnerability ┌───────────────┬──────────────────────────────────────────────────────────────┐ │ Moderate │ Memory Exposure │ ├───────────────┼──────────────────────────────────────────────────────────────┤ │ Package │ bl │ ├───────────────┼──────────────────────────────────────────────────────────────┤ │ Dependency of │ ganache-core [dev] │ ├───────────────┼──────────────────────────────────────────────────────────────┤ │ Path │ ganache-core > level-sublevel > levelup > bl │ ├───────────────┼──────────────────────────────────────────────────────────────┤ │ More info │ https://nodesecurity.io/advisories/596 │ └───────────────┴──────────────────────────────────────────────────────────────┘ * Deduplicate package.json file From `npm install`: > npm WARN The package css-loader is included as both a dev and production dependency. > npm WARN The package eslint-plugin-react is included as both a dev and production dependency. > npm WARN The package file-loader is included as both a dev and production dependency. > npm WARN The package gulp is included as both a dev and production dependency. It's also worth noting that the Gulp version we were using was inconsistent and there is a published v4 release on GitHub. * Fix race condition in network controller lookup() method. * Group transactions by nonce (#5886) * fix formatting of 32-byte strings in personal_sign (#5878) * Bump json-rpc-engine to v4.0.0 * Bump package lock, mostly to https links * Improve ux for low gas price set (#5862) * Show user warning if they set gas price below safelow minimum, error if 0. * Properly cache basic price estimate data. * Default retry price to recommended price if original price was 0x0 * Use mock fetch in send-new-ui integration tests. * Show Failed transaction in the browser notification for on-chain failures (#5904) * Changelog and version bump for 5.2.0
Diffstat (limited to 'ui/app/selectors/custom-gas.js')
-rw-r--r--ui/app/selectors/custom-gas.js306
1 files changed, 306 insertions, 0 deletions
diff --git a/ui/app/selectors/custom-gas.js b/ui/app/selectors/custom-gas.js
new file mode 100644
index 000000000..91c9109a5
--- /dev/null
+++ b/ui/app/selectors/custom-gas.js
@@ -0,0 +1,306 @@
+import { pipe, partialRight } from 'ramda'
+import {
+ conversionUtil,
+ multiplyCurrencies,
+ conversionGreaterThan,
+} 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 = {
+ formatTimeEstimate,
+ getAveragePriceEstimateInHexWEI,
+ getFastPriceEstimateInHexWEI,
+ getBasicGasEstimateLoadingStatus,
+ getBasicGasEstimateBlockTime,
+ getCustomGasErrors,
+ getCustomGasLimit,
+ getCustomGasPrice,
+ getCustomGasTotal,
+ getDefaultActiveButtonIndex,
+ getEstimatedGasPrices,
+ getEstimatedGasTimes,
+ getGasEstimatesLoadingStatus,
+ getPriceAndTimeEstimates,
+ getRenderableBasicEstimateData,
+ getRenderableEstimateDataForSmallButtonsFromGWEI,
+ priceEstimateToWei,
+ getSafeLowEstimate,
+ isCustomPriceSafe,
+}
+
+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 getGasEstimatesLoadingStatus (state) {
+ return state.gas.gasEstimatesLoading
+}
+
+function getPriceAndTimeEstimates (state) {
+ return state.gas.priceAndTimeEstimates
+}
+
+function getEstimatedGasPrices (state) {
+ return getPriceAndTimeEstimates(state).map(({ gasprice }) => gasprice)
+}
+
+function getEstimatedGasTimes (state) {
+ return getPriceAndTimeEstimates(state).map(({ expectedTime }) => expectedTime)
+}
+
+function getAveragePriceEstimateInHexWEI (state) {
+ const averagePriceEstimate = state.gas.basicEstimates.average
+ return getGasPriceInHexWei(averagePriceEstimate || '0x0')
+}
+
+function getFastPriceEstimateInHexWEI (state) {
+ const fastPriceEstimate = state.gas.basicEstimates.fast
+ return getGasPriceInHexWei(fastPriceEstimate || '0x0')
+}
+
+function getDefaultActiveButtonIndex (gasButtonInfo, customGasPriceInHex, gasPrice) {
+ return gasButtonInfo.findIndex(({ priceInHexWei }) => {
+ return priceInHexWei === addHexPrefix(customGasPriceInHex || gasPrice)
+ })
+}
+
+function getSafeLowEstimate (state) {
+ const {
+ gas: {
+ basicEstimates: {
+ safeLow,
+ },
+ },
+ } = state
+
+ return safeLow
+}
+
+function isCustomPriceSafe (state) {
+ const safeLow = getSafeLowEstimate(state)
+ const customGasPrice = getCustomGasPrice(state)
+
+ if (!customGasPrice) {
+ return true
+ }
+
+ const customPriceSafe = conversionGreaterThan(
+ {
+ value: customGasPrice,
+ fromNumericBase: 'hex',
+ fromDenomination: 'WEI',
+ toDenomination: 'GWEI',
+ },
+ { value: safeLow, fromNumericBase: 'dec' }
+ )
+
+ return customPriceSafe
+}
+
+function getBasicGasEstimateBlockTime (state) {
+ return state.gas.basicEstimates.blockTime
+}
+
+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(
+ x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }),
+ partialRight(basicPriceEstimateToETHTotal, [gasLimit, numberOfDecimals]),
+ formatETHFee
+ )(estimate, gasLimit)
+}
+
+
+function getRenderableConvertedCurrencyFee (estimate, gasLimit, convertedCurrency, conversionRate) {
+ return pipe(
+ x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }),
+ partialRight(basicPriceEstimateToETHTotal, [gasLimit]),
+ partialRight(ethTotalToConvertedCurrency, [convertedCurrency, conversionRate]),
+ partialRight(formatCurrency, [convertedCurrency])
+ )(estimate, gasLimit, convertedCurrency, conversionRate)
+}
+
+function getTimeEstimateInSeconds (blockWaitEstimate) {
+ return multiplyCurrencies(blockWaitEstimate, 60, {
+ toNumericBase: 'dec',
+ multiplicandBase: 10,
+ multiplierBase: 10,
+ numberOfDecimals: 1,
+ })
+}
+
+function formatTimeEstimate (totalSeconds, greaterThanMax, lessThanMin) {
+ const minutes = Math.floor(totalSeconds / 60)
+ const seconds = Math.floor(totalSeconds % 60)
+
+ if (!minutes && !seconds) {
+ return '...'
+ }
+
+ let symbol = '~'
+ if (greaterThanMax) {
+ symbol = '< '
+ } else if (lessThanMin) {
+ symbol = '> '
+ }
+
+ const formattedMin = `${minutes ? minutes + ' min' : ''}`
+ const formattedSec = `${seconds ? seconds + ' sec' : ''}`
+ const formattedCombined = formattedMin && formattedSec
+ ? `${symbol}${formattedMin} ${formattedSec}`
+ : symbol + [formattedMin, formattedSec].find(t => t)
+
+ return formattedCombined
+}
+
+function getRenderableTimeEstimate (blockWaitEstimate) {
+ return pipe(
+ getTimeEstimateInSeconds,
+ formatTimeEstimate
+ )(blockWaitEstimate)
+}
+
+function priceEstimateToWei (priceEstimate) {
+ return conversionUtil(priceEstimate, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'hex',
+ fromDenomination: 'GWEI',
+ toDenomination: 'WEI',
+ numberOfDecimals: 9,
+ })
+}
+
+function getGasPriceInHexWei (price) {
+ return pipe(
+ x => conversionUtil(x, { fromNumericBase: 'dec', toNumericBase: 'hex' }),
+ 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,
+ fast,
+ fastest,
+ safeLowWait,
+ fastestWait,
+ fastWait,
+ },
+ },
+ } = state
+
+ return [
+ {
+ labelKey: 'fastest',
+ feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fastest, gasLimit, currentCurrency, conversionRate),
+ feeInSecondaryCurrency: getRenderableEthFee(fastest, gasLimit),
+ timeEstimate: fastestWait && getRenderableTimeEstimate(fastestWait),
+ priceInHexWei: getGasPriceInHexWei(fastest),
+ },
+ {
+ labelKey: 'fast',
+ feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate),
+ feeInSecondaryCurrency: getRenderableEthFee(fast, gasLimit),
+ timeEstimate: fastWait && getRenderableTimeEstimate(fastWait),
+ priceInHexWei: getGasPriceInHexWei(fast),
+ },
+ {
+ labelKey: 'slow',
+ feeInPrimaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate),
+ feeInSecondaryCurrency: getRenderableEthFee(safeLow, gasLimit),
+ timeEstimate: safeLowWait && getRenderableTimeEstimate(safeLowWait),
+ priceInHexWei: getGasPriceInHexWei(safeLow),
+ },
+ ]
+}
+
+function getRenderableEstimateDataForSmallButtonsFromGWEI (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,
+ fast,
+ fastest,
+ },
+ },
+ } = state
+
+ return [
+ {
+ labelKey: 'fastest',
+ feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fastest, gasLimit, currentCurrency, conversionRate),
+ feeInPrimaryCurrency: getRenderableEthFee(fastest, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true),
+ priceInHexWei: getGasPriceInHexWei(fastest, true),
+ },
+ {
+ labelKey: 'fast',
+ feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(fast, gasLimit, currentCurrency, conversionRate),
+ feeInPrimaryCurrency: getRenderableEthFee(fast, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true),
+ priceInHexWei: getGasPriceInHexWei(fast, true),
+ },
+ {
+ labelKey: 'slow',
+ feeInSecondaryCurrency: getRenderableConvertedCurrencyFee(safeLow, gasLimit, currentCurrency, conversionRate),
+ feeInPrimaryCurrency: getRenderableEthFee(safeLow, gasLimit, NUMBER_OF_DECIMALS_SM_BTNS, true),
+ priceInHexWei: getGasPriceInHexWei(safeLow, true),
+ },
+ ]
+}