diff options
author | Thomas Huang <tmashuang@users.noreply.github.com> | 2018-12-12 06:56:47 +0800 |
---|---|---|
committer | Dan Finlay <542863+danfinlay@users.noreply.github.com> | 2018-12-12 06:56:47 +0800 |
commit | 2f5abd9ad8ac64c16edcc0d9fff923e62c5ca984 (patch) | |
tree | 16d323cd3325b1b9121434e86c3047dc333c2b1d /ui/app/selectors/custom-gas.js | |
parent | ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275 (diff) | |
download | tangerine-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.js | 306 |
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), + }, + ] +} |