mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Switch gas price estimation in swaps to metaswap-api /gasPrices (#9599)
Adds swaps-gas-customization-modal and utilize in swaps Remove swaps specific code from gas-modal-page-container/ Remove slow estimate data from swaps-gas-customization-modal.container Use average as lower safe price limit in swaps-gas-customization-modal Lint fix Fix up unit tests Update ui/app/ducks/swaps/swaps.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> Remove stale properties from gas-modal-page-container.component.js Replace use of isCustomPrice safe with isCustomSwapsGasPriceSafe, in swaps-gas-customization-modal Remove use of averageIsSafe in isCustomPriceSafe function Stop calling resetCustomGasState in swaps Refactor 'setter' type actions and creators to 'event based', for swaps slice custom gas logic Replace use of advanced-tab-content.component with advanceGasInputs in swaps gas customization component Add validation for the gasPrices endpoint swaps custom gas price should be considered safe if >= to average Update renderDataSummary unit test Lint fix Remove customOnHideOpts for swapsGasCustomizationModal in modal.js Better handling for swaps gas price loading and failure states Improve semantics: isCustomSwapsGasPriceSafe renamed to isCustomSwapsGasPriceUnSafe Mutate state directly in swaps gas slice reducer Remove unused params More reliable tracking of speed setting for Gas Fees Changed metrics event Lint fix Throw error when fetchSwapsGasPrices response is invalid add disableSave and customTotalSupplement to swaps-gas-customization container return Update ui/app/ducks/swaps/swaps.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> Improve error handling in fetchMetaSwapsGasPriceEstimates Remove metricsEvent from swaps-gas-customization-modal context Base check of gas speed type in swaps-gas-customization-modal on gasEstimateType Improve naming of variable and functions use to set customPriceIsSafe prop of AdvancedGasInputs in swaps-gas-customization-modal Simplify sinon spy/stub code in gas-price-button-group-component.test.js Remove unnecessary getSwapsFallbackGasPrice call in swaps-gas-customization-modal Remove use of getSwapsTradeTxParams and clean up related gas price logic in swaps Improve validator of SWAP_GAS_PRICE_VALIDATOR Ensure default tradeValue
This commit is contained in:
parent
ad838df3e6
commit
a0d7c71011
@ -25,7 +25,7 @@ export default class AdvancedTabContent extends Component {
|
||||
isSpeedUp: PropTypes.bool,
|
||||
isEthereumNetwork: PropTypes.bool,
|
||||
customGasLimitMessage: PropTypes.string,
|
||||
minimumGasLimit: PropTypes.number.isRequired,
|
||||
minimumGasLimit: PropTypes.number,
|
||||
}
|
||||
|
||||
renderDataSummary(transactionFee, timeRemaining) {
|
||||
|
@ -103,7 +103,7 @@ describe('AdvancedTabContent Component', function () {
|
||||
const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(
|
||||
0,
|
||||
).args
|
||||
assert.deepEqual(renderDataSummaryArgs, ['$0.25', 21500])
|
||||
assert.deepEqual(renderDataSummaryArgs, ['$0.25', '21500'])
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -2,8 +2,6 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import PageContainer from '../../../ui/page-container'
|
||||
import { Tabs, Tab } from '../../../ui/tabs'
|
||||
import { calcGasTotal } from '../../../../pages/send/send.utils'
|
||||
import { sumHexWEIsToRenderableFiat } from '../../../../helpers/utils/conversions.util'
|
||||
import AdvancedTabContent from './advanced-tab-content'
|
||||
import BasicTabContent from './basic-tab-content'
|
||||
|
||||
@ -32,10 +30,6 @@ export default class GasModalPageContainer extends Component {
|
||||
newTotalEth: PropTypes.string,
|
||||
sendAmount: PropTypes.string,
|
||||
transactionFee: PropTypes.string,
|
||||
extraInfoRow: PropTypes.shape({
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
onSubmit: PropTypes.func,
|
||||
customModalGasPriceInHex: PropTypes.string,
|
||||
@ -47,16 +41,6 @@ export default class GasModalPageContainer extends Component {
|
||||
isRetry: PropTypes.bool,
|
||||
disableSave: PropTypes.bool,
|
||||
isEthereumNetwork: PropTypes.bool,
|
||||
customGasLimitMessage: PropTypes.string,
|
||||
customTotalSupplement: PropTypes.string,
|
||||
isSwap: PropTypes.bool,
|
||||
value: PropTypes.string,
|
||||
conversionRate: PropTypes.number,
|
||||
minimumGasLimit: PropTypes.number.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
selectedTab: 'Basic',
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -92,8 +76,6 @@ export default class GasModalPageContainer extends Component {
|
||||
isRetry,
|
||||
infoRowProps: { transactionFee },
|
||||
isEthereumNetwork,
|
||||
customGasLimitMessage,
|
||||
minimumGasLimit,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
@ -102,7 +84,6 @@ export default class GasModalPageContainer extends Component {
|
||||
updateCustomGasLimit={updateCustomGasLimit}
|
||||
customModalGasPriceInHex={customModalGasPriceInHex}
|
||||
customModalGasLimitInHex={customModalGasLimitInHex}
|
||||
customGasLimitMessage={customGasLimitMessage}
|
||||
timeRemaining={currentTimeEstimate}
|
||||
transactionFee={transactionFee}
|
||||
gasChartProps={gasChartProps}
|
||||
@ -112,18 +93,11 @@ export default class GasModalPageContainer extends Component {
|
||||
isSpeedUp={isSpeedUp}
|
||||
isRetry={isRetry}
|
||||
isEthereumNetwork={isEthereumNetwork}
|
||||
minimumGasLimit={minimumGasLimit}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderInfoRows(
|
||||
newTotalFiat,
|
||||
newTotalEth,
|
||||
sendAmount,
|
||||
transactionFee,
|
||||
extraInfoRow,
|
||||
) {
|
||||
renderInfoRows(newTotalFiat, newTotalEth, sendAmount, transactionFee) {
|
||||
return (
|
||||
<div className="gas-modal-content__info-row-wrapper">
|
||||
<div className="gas-modal-content__info-row">
|
||||
@ -143,16 +117,6 @@ export default class GasModalPageContainer extends Component {
|
||||
{transactionFee}
|
||||
</span>
|
||||
</div>
|
||||
{extraInfoRow && (
|
||||
<div className="gas-modal-content__info-row__transaction-info">
|
||||
<span className="gas-modal-content__info-row__transaction-info__label">
|
||||
{extraInfoRow.label}
|
||||
</span>
|
||||
<span className="gas-modal-content__info-row__transaction-info__value">
|
||||
{extraInfoRow.value}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="gas-modal-content__info-row__total-info">
|
||||
<span className="gas-modal-content__info-row__total-info__label">
|
||||
{this.context.t('newTotal')}
|
||||
@ -175,13 +139,7 @@ export default class GasModalPageContainer extends Component {
|
||||
const {
|
||||
gasPriceButtonGroupProps,
|
||||
hideBasic,
|
||||
infoRowProps: {
|
||||
newTotalFiat,
|
||||
newTotalEth,
|
||||
sendAmount,
|
||||
transactionFee,
|
||||
extraInfoRow,
|
||||
},
|
||||
infoRowProps: { newTotalFiat, newTotalEth, sendAmount, transactionFee },
|
||||
} = this.props
|
||||
|
||||
let tabsToRender = [
|
||||
@ -200,7 +158,7 @@ export default class GasModalPageContainer extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tabs onTabClick={(tabName) => this.setState({ selectedTab: tabName })}>
|
||||
<Tabs>
|
||||
{tabsToRender.map(({ name, content }, i) => (
|
||||
<Tab name={name} key={`gas-modal-tab-${i}`}>
|
||||
<div className="gas-modal-content">
|
||||
@ -210,7 +168,6 @@ export default class GasModalPageContainer extends Component {
|
||||
newTotalEth,
|
||||
sendAmount,
|
||||
transactionFee,
|
||||
extraInfoRow,
|
||||
)}
|
||||
</div>
|
||||
</Tab>
|
||||
@ -248,45 +205,7 @@ export default class GasModalPageContainer extends Component {
|
||||
},
|
||||
})
|
||||
}
|
||||
if (this.props.isSwap) {
|
||||
const newSwapGasTotal = calcGasTotal(
|
||||
customModalGasLimitInHex,
|
||||
customModalGasPriceInHex,
|
||||
)
|
||||
let speedSet = ''
|
||||
if (this.state.selectedTab === 'Basic') {
|
||||
const { gasButtonInfo } = this.props.gasPriceButtonGroupProps
|
||||
const selectedGasButtonInfo = gasButtonInfo.find(
|
||||
({ priceInHexWei }) =>
|
||||
priceInHexWei === customModalGasPriceInHex,
|
||||
)
|
||||
speedSet = selectedGasButtonInfo?.gasEstimateType || ''
|
||||
}
|
||||
|
||||
this.context.trackEvent({
|
||||
event: 'Gas Fees Changed',
|
||||
category: 'swaps',
|
||||
properties: {
|
||||
speed_set: speedSet,
|
||||
gas_mode: this.state.selectedTab,
|
||||
gas_fees: sumHexWEIsToRenderableFiat(
|
||||
[
|
||||
this.props.value,
|
||||
newSwapGasTotal,
|
||||
this.props.customTotalSupplement,
|
||||
],
|
||||
'usd',
|
||||
this.props.conversionRate,
|
||||
)?.slice(1),
|
||||
},
|
||||
})
|
||||
}
|
||||
onSubmit(
|
||||
customModalGasLimitInHex,
|
||||
customModalGasPriceInHex,
|
||||
this.state.selectedTab,
|
||||
this.context.mixPanelTrack,
|
||||
)
|
||||
onSubmit(customModalGasLimitInHex, customModalGasPriceInHex)
|
||||
}}
|
||||
submitText={this.context.t('save')}
|
||||
headerCloseText={this.context.t('close')}
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
updateSendAmount,
|
||||
setGasTotal,
|
||||
updateTransaction,
|
||||
setSwapsTxGasParams,
|
||||
} from '../../../../store/actions'
|
||||
import {
|
||||
setCustomGasPrice,
|
||||
@ -67,19 +66,9 @@ import GasModalPageContainer from './gas-modal-page-container.component'
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const { currentNetworkTxList, send } = state.metamask
|
||||
const { modalState: { props: modalProps } = {} } = state.appState.modal || {}
|
||||
const {
|
||||
txData = {},
|
||||
isSwap = false,
|
||||
customGasLimitMessage = '',
|
||||
customTotalSupplement = '',
|
||||
extraInfoRow = null,
|
||||
useFastestButtons = false,
|
||||
minimumGasLimit = Number(MIN_GAS_LIMIT_DEC),
|
||||
} = modalProps || {}
|
||||
const { txData = {} } = modalProps || {}
|
||||
const { transaction = {} } = ownProps
|
||||
const selectedTransaction = isSwap
|
||||
? txData
|
||||
: currentNetworkTxList.find(
|
||||
const selectedTransaction = currentNetworkTxList.find(
|
||||
({ id }) => id === (transaction.id || txData.id),
|
||||
)
|
||||
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
|
||||
@ -107,13 +96,12 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const gasButtonInfo = getRenderableBasicEstimateData(
|
||||
state,
|
||||
customModalGasLimitInHex,
|
||||
useFastestButtons,
|
||||
)
|
||||
|
||||
const currentCurrency = getCurrentCurrency(state)
|
||||
const conversionRate = getConversionRate(state)
|
||||
const newTotalFiat = sumHexWEIsToRenderableFiat(
|
||||
[value, customGasTotal, customTotalSupplement],
|
||||
[value, customGasTotal],
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
)
|
||||
@ -137,11 +125,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const newTotalEth =
|
||||
maxModeOn && !isSendTokenSet
|
||||
? sumHexWEIsToRenderableEth([balance, '0x0'])
|
||||
: sumHexWEIsToRenderableEth([
|
||||
value,
|
||||
customGasTotal,
|
||||
customTotalSupplement,
|
||||
])
|
||||
: sumHexWEIsToRenderableEth([value, customGasTotal])
|
||||
|
||||
const sendAmount =
|
||||
maxModeOn && !isSendTokenSet
|
||||
@ -171,7 +155,6 @@ const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
hideBasic,
|
||||
isConfirm: isConfirm(state),
|
||||
isSwap,
|
||||
customModalGasPriceInHex,
|
||||
customModalGasLimitInHex,
|
||||
customGasPrice,
|
||||
@ -180,7 +163,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
newTotalFiat,
|
||||
currentTimeEstimate,
|
||||
blockTime: getBasicGasEstimateBlockTime(state),
|
||||
customPriceIsSafe: isCustomPriceSafe(state, isSwap),
|
||||
customPriceIsSafe: isCustomPriceSafe(state),
|
||||
maxModeOn,
|
||||
gasPriceButtonGroupProps: {
|
||||
buttonDataLoading,
|
||||
@ -199,20 +182,15 @@ const mapStateToProps = (state, ownProps) => {
|
||||
},
|
||||
infoRowProps: {
|
||||
originalTotalFiat: sumHexWEIsToRenderableFiat(
|
||||
[value, customGasTotal, customTotalSupplement],
|
||||
[value, customGasTotal],
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
),
|
||||
originalTotalEth: sumHexWEIsToRenderableEth([
|
||||
value,
|
||||
customGasTotal,
|
||||
customTotalSupplement,
|
||||
]),
|
||||
originalTotalEth: sumHexWEIsToRenderableEth([value, customGasTotal]),
|
||||
newTotalFiat: showFiat ? newTotalFiat : '',
|
||||
newTotalEth,
|
||||
transactionFee: sumHexWEIsToRenderableEth(['0x0', customGasTotal]),
|
||||
sendAmount,
|
||||
extraInfoRow,
|
||||
},
|
||||
transaction: txData || transaction,
|
||||
isSpeedUp: transaction.status === 'submitted',
|
||||
@ -225,11 +203,8 @@ const mapStateToProps = (state, ownProps) => {
|
||||
sendToken,
|
||||
balance,
|
||||
tokenBalance: getTokenBalance(state),
|
||||
customGasLimitMessage,
|
||||
conversionRate,
|
||||
value,
|
||||
customTotalSupplement,
|
||||
minimumGasLimit,
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,9 +246,6 @@ const mapDispatchToProps = (dispatch) => {
|
||||
dispatch(updateSendErrors({ amount: null }))
|
||||
dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject)))
|
||||
},
|
||||
updateSwapTxGas: (gasLimit, gasPrice) => {
|
||||
dispatch(setSwapsTxGasParams(gasLimit, gasPrice))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +254,6 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
gasPriceButtonGroupProps,
|
||||
// eslint-disable-next-line no-shadow
|
||||
isConfirm,
|
||||
isSwap,
|
||||
txId,
|
||||
isSpeedUp,
|
||||
isRetry,
|
||||
@ -295,7 +266,6 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
tokenBalance,
|
||||
customGasLimit,
|
||||
transaction,
|
||||
minimumGasLimit,
|
||||
} = stateProps
|
||||
const {
|
||||
hideGasButtonGroup: dispatchHideGasButtonGroup,
|
||||
@ -307,7 +277,6 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
cancelAndClose: dispatchCancelAndClose,
|
||||
hideModal: dispatchHideModal,
|
||||
setAmountToMax: dispatchSetAmountToMax,
|
||||
updateSwapTxGas: dispatchUpdateSwapTxGas,
|
||||
...otherDispatchProps
|
||||
} = dispatchProps
|
||||
|
||||
@ -316,10 +285,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
...otherDispatchProps,
|
||||
...ownProps,
|
||||
onSubmit: (gasLimit, gasPrice) => {
|
||||
if (isSwap) {
|
||||
dispatchUpdateSwapTxGas(gasLimit, gasPrice)
|
||||
dispatchHideModal()
|
||||
} else if (isConfirm) {
|
||||
if (isConfirm) {
|
||||
const updatedTx = {
|
||||
...transaction,
|
||||
txParams: {
|
||||
@ -365,7 +331,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
disableSave:
|
||||
insufficientBalance ||
|
||||
(isSpeedUp && customGasPrice === 0) ||
|
||||
customGasLimit < minimumGasLimit,
|
||||
customGasLimit < Number(MIN_GAS_LIMIT_DEC),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,14 +194,12 @@ describe('GasModalPageContainer Component', function () {
|
||||
'mockNewTotalEth',
|
||||
'mockSendAmount',
|
||||
'mockTransactionFee',
|
||||
{ label: 'mockLabel', value: 'mockValue' },
|
||||
])
|
||||
assert.deepEqual(GP.renderInfoRows.getCall(1).args, [
|
||||
'mockNewTotalFiat',
|
||||
'mockNewTotalEth',
|
||||
'mockSendAmount',
|
||||
'mockTransactionFee',
|
||||
{ label: 'mockLabel', value: 'mockValue' },
|
||||
])
|
||||
})
|
||||
|
||||
|
@ -63,8 +63,6 @@ describe('gas-modal-page-container container', function () {
|
||||
txData: {
|
||||
id: 34,
|
||||
},
|
||||
extraInfoRow: { label: 'mockLabel', value: 'mockValue' },
|
||||
minimumGasLimit: 21000,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -131,8 +129,6 @@ describe('gas-modal-page-container container', function () {
|
||||
newTotalFiat: '637.41',
|
||||
blockTime: 12,
|
||||
conversionRate: 50,
|
||||
customGasLimitMessage: '',
|
||||
customTotalSupplement: '',
|
||||
customModalGasLimitInHex: 'aaaaaaaa',
|
||||
customModalGasPriceInHex: 'ffffffff',
|
||||
customGasTotal: 'aaaaaaa955555556',
|
||||
@ -152,7 +148,6 @@ describe('gas-modal-page-container container', function () {
|
||||
gasEstimatesLoading: false,
|
||||
hideBasic: true,
|
||||
infoRowProps: {
|
||||
extraInfoRow: { label: 'mockLabel', value: 'mockValue' },
|
||||
originalTotalFiat: '637.41',
|
||||
originalTotalEth: '12.748189 ETH',
|
||||
newTotalFiat: '637.41',
|
||||
@ -163,7 +158,6 @@ describe('gas-modal-page-container container', function () {
|
||||
insufficientBalance: true,
|
||||
isSpeedUp: false,
|
||||
isRetry: false,
|
||||
isSwap: false,
|
||||
txId: 34,
|
||||
isEthereumNetwork: true,
|
||||
isMainnet: true,
|
||||
@ -174,7 +168,6 @@ describe('gas-modal-page-container container', function () {
|
||||
id: 34,
|
||||
},
|
||||
value: '0x640000000000000',
|
||||
minimumGasLimit: 21000,
|
||||
}
|
||||
const baseMockOwnProps = { transaction: { id: 34 } }
|
||||
const tests = [
|
||||
|
@ -93,7 +93,12 @@ export default class GasPriceButtonGroup extends Component {
|
||||
) {
|
||||
return (
|
||||
<Button
|
||||
onClick={() => handleGasPriceSelection(priceInHexWei)}
|
||||
onClick={() =>
|
||||
handleGasPriceSelection(
|
||||
priceInHexWei,
|
||||
renderableGasInfo.gasEstimateType,
|
||||
)
|
||||
}
|
||||
key={`gas-price-button-${index}`}
|
||||
>
|
||||
{this.renderButtonContent(
|
||||
|
@ -3,6 +3,7 @@ import React from 'react'
|
||||
import sinon from 'sinon'
|
||||
import shallow from '../../../../../../lib/shallow-with-context'
|
||||
import GasPriceButtonGroup from '../gas-price-button-group.component'
|
||||
import { GAS_ESTIMATE_TYPES } from '../../../../../helpers/constants/common'
|
||||
|
||||
import ButtonGroup from '../../../../ui/button-group'
|
||||
|
||||
@ -17,18 +18,21 @@ describe('GasPriceButtonGroup Component', function () {
|
||||
className: 'gas-price-button-group',
|
||||
gasButtonInfo: [
|
||||
{
|
||||
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
||||
feeInPrimaryCurrency: '$0.52',
|
||||
feeInSecondaryCurrency: '0.0048 ETH',
|
||||
timeEstimate: '~ 1 min 0 sec',
|
||||
priceInHexWei: '0xa1b2c3f',
|
||||
},
|
||||
{
|
||||
gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE,
|
||||
feeInPrimaryCurrency: '$0.39',
|
||||
feeInSecondaryCurrency: '0.004 ETH',
|
||||
timeEstimate: '~ 1 min 30 sec',
|
||||
priceInHexWei: '0xa1b2c39',
|
||||
},
|
||||
{
|
||||
gasEstimateType: GAS_ESTIMATE_TYPES.FAST,
|
||||
feeInPrimaryCurrency: '$0.30',
|
||||
feeInSecondaryCurrency: '0.00354 ETH',
|
||||
timeEstimate: '~ 2 min 1 sec',
|
||||
@ -105,7 +109,9 @@ describe('GasPriceButtonGroup Component', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
GasPriceButtonGroup.prototype.renderButtonContent.resetHistory()
|
||||
const renderButtonResult = GasPriceButtonGroup.prototype.renderButton(
|
||||
const renderButtonResult = wrapper
|
||||
.instance()
|
||||
.renderButton(
|
||||
{ ...mockGasPriceButtonGroupProps.gasButtonInfo[0] },
|
||||
mockButtonPropsAndFlags,
|
||||
)
|
||||
@ -128,7 +134,10 @@ describe('GasPriceButtonGroup Component', function () {
|
||||
)
|
||||
assert.deepEqual(
|
||||
mockGasPriceButtonGroupProps.handleGasPriceSelection.getCall(0).args,
|
||||
[mockGasPriceButtonGroupProps.gasButtonInfo[0].priceInHexWei],
|
||||
[
|
||||
mockGasPriceButtonGroupProps.gasButtonInfo[0].priceInHexWei,
|
||||
mockGasPriceButtonGroupProps.gasButtonInfo[0].gasEstimateType,
|
||||
],
|
||||
)
|
||||
})
|
||||
|
||||
@ -141,12 +150,14 @@ describe('GasPriceButtonGroup Component', function () {
|
||||
feeInPrimaryCurrency,
|
||||
feeInSecondaryCurrency,
|
||||
timeEstimate,
|
||||
gasEstimateType,
|
||||
} = mockGasPriceButtonGroupProps.gasButtonInfo[0]
|
||||
const { showCheck, className } = mockGasPriceButtonGroupProps
|
||||
assert.deepEqual(
|
||||
GasPriceButtonGroup.prototype.renderButtonContent.getCall(0).args,
|
||||
[
|
||||
{
|
||||
gasEstimateType,
|
||||
feeInPrimaryCurrency,
|
||||
feeInSecondaryCurrency,
|
||||
timeEstimate,
|
||||
|
@ -10,6 +10,7 @@ import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums'
|
||||
|
||||
// Modal Components
|
||||
import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container'
|
||||
import SwapsGasCustomizationModal from '../../../pages/swaps/swaps-gas-customization-modal'
|
||||
import DepositEtherModal from './deposit-ether-modal'
|
||||
import AccountDetailsModal from './account-details-modal'
|
||||
import ExportPrivateKeyModal from './export-private-key-modal'
|
||||
@ -272,6 +273,31 @@ const MODALS = {
|
||||
},
|
||||
},
|
||||
|
||||
CUSTOMIZE_METASWAP_GAS: {
|
||||
contents: <SwapsGasCustomizationModal />,
|
||||
mobileModalStyle: {
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
top: '0',
|
||||
transform: 'none',
|
||||
left: '0',
|
||||
right: '0',
|
||||
margin: '0 auto',
|
||||
},
|
||||
laptopModalStyle: {
|
||||
width: 'auto',
|
||||
height: '0px',
|
||||
top: '80px',
|
||||
left: '0px',
|
||||
transform: 'none',
|
||||
margin: '0 auto',
|
||||
position: 'relative',
|
||||
},
|
||||
contentStyle: {
|
||||
borderRadius: '8px',
|
||||
},
|
||||
},
|
||||
|
||||
EDIT_APPROVAL_PERMISSION: {
|
||||
contents: <EditApprovalPermission />,
|
||||
mobileModalStyle: {
|
||||
|
@ -2,6 +2,10 @@ import { createSlice } from '@reduxjs/toolkit'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import log from 'loglevel'
|
||||
|
||||
import {
|
||||
loadLocalStorageData,
|
||||
saveLocalStorageData,
|
||||
} from '../../../lib/local-storage-helpers'
|
||||
import {
|
||||
addToken,
|
||||
addUnapprovedTransaction,
|
||||
@ -27,7 +31,10 @@ import {
|
||||
SWAPS_ERROR_ROUTE,
|
||||
SWAPS_MAINTENANCE_ROUTE,
|
||||
} from '../../helpers/constants/routes'
|
||||
import { fetchSwapsFeatureLiveness } from '../../pages/swaps/swaps.util'
|
||||
import {
|
||||
fetchSwapsFeatureLiveness,
|
||||
fetchSwapsGasPrices,
|
||||
} from '../../pages/swaps/swaps.util'
|
||||
import { calcGasTotal } from '../../pages/send/send.utils'
|
||||
import {
|
||||
decimalToHex,
|
||||
@ -37,9 +44,9 @@ import {
|
||||
hexToDecimal,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../helpers/utils/conversions.util'
|
||||
import { conversionLessThan } from '../../helpers/utils/conversion-util'
|
||||
import { calcTokenAmount } from '../../helpers/utils/token-util'
|
||||
import {
|
||||
getFastPriceEstimateInHexWEI,
|
||||
getSelectedAccount,
|
||||
getTokenExchangeRates,
|
||||
conversionRateSelector as getConversionRate,
|
||||
@ -51,14 +58,16 @@ import {
|
||||
SWAP_FAILED_ERROR,
|
||||
SWAPS_FETCH_ORDER_CONFLICT,
|
||||
} from '../../helpers/constants/swaps'
|
||||
import {
|
||||
fetchBasicGasAndTimeEstimates,
|
||||
fetchGasEstimates,
|
||||
resetCustomGasState,
|
||||
} from '../gas/gas.duck'
|
||||
import { formatCurrency } from '../../helpers/utils/confirm-tx.util'
|
||||
import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'
|
||||
|
||||
const GAS_PRICES_LOADING_STATES = {
|
||||
INITIAL: 'INITIAL',
|
||||
LOADING: 'LOADING',
|
||||
FAILED: 'FAILED',
|
||||
COMPLETED: 'COMPLETED',
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
aggregatorMetadata: null,
|
||||
approveTxId: null,
|
||||
@ -68,6 +77,14 @@ const initialState = {
|
||||
quotesFetchStartTime: null,
|
||||
topAssets: {},
|
||||
toToken: null,
|
||||
customGas: {
|
||||
price: null,
|
||||
limit: null,
|
||||
loading: GAS_PRICES_LOADING_STATES.INITIAL,
|
||||
priceEstimates: {},
|
||||
priceEstimatesLastRetrieved: 0,
|
||||
fallBackPrice: null,
|
||||
},
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
@ -106,6 +123,27 @@ const slice = createSlice({
|
||||
setToToken: (state, action) => {
|
||||
state.toToken = action.payload
|
||||
},
|
||||
swapCustomGasModalPriceEdited: (state, action) => {
|
||||
state.customGas.price = action.payload
|
||||
},
|
||||
swapCustomGasModalLimitEdited: (state, action) => {
|
||||
state.customGas.limit = action.payload
|
||||
},
|
||||
swapGasPriceEstimatesFetchStarted: (state) => {
|
||||
state.customGas.loading = GAS_PRICES_LOADING_STATES.LOADING
|
||||
},
|
||||
swapGasPriceEstimatesFetchFailed: (state) => {
|
||||
state.customGas.loading = GAS_PRICES_LOADING_STATES.FAILED
|
||||
},
|
||||
swapGasPriceEstimatesFetchCompleted: (state, action) => {
|
||||
state.customGas.priceEstimates = action.payload.priceEstimates
|
||||
state.customGas.loading = GAS_PRICES_LOADING_STATES.COMPLETED
|
||||
state.customGas.priceEstimatesLastRetrieved =
|
||||
action.payload.priceEstimatesLastRetrieved
|
||||
},
|
||||
retrievedFallbackSwapsGasPrice: (state, action) => {
|
||||
state.customGas.fallBackPrice = action.payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -130,6 +168,49 @@ export const getFetchingQuotes = (state) => state.swaps.fetchingQuotes
|
||||
export const getQuotesFetchStartTime = (state) =>
|
||||
state.swaps.quotesFetchStartTime
|
||||
|
||||
export const getSwapsCustomizationModalPrice = (state) =>
|
||||
state.swaps.customGas.price
|
||||
|
||||
export const getSwapsCustomizationModalLimit = (state) =>
|
||||
state.swaps.customGas.limit
|
||||
|
||||
export const swapGasPriceEstimateIsLoading = (state) =>
|
||||
state.swaps.customGas.loading === GAS_PRICES_LOADING_STATES.LOADING
|
||||
|
||||
export const swapGasEstimateLoadingHasFailed = (state) =>
|
||||
state.swaps.customGas.loading === GAS_PRICES_LOADING_STATES.INITIAL
|
||||
|
||||
export const getSwapGasPriceEstimateData = (state) =>
|
||||
state.swaps.customGas.priceEstimates
|
||||
|
||||
export const getSwapsPriceEstimatesLastRetrieved = (state) =>
|
||||
state.swaps.customGas.priceEstimatesLastRetrieved
|
||||
|
||||
export const getSwapsFallbackGasPrice = (state) =>
|
||||
state.swaps.customGas.fallBackPrice
|
||||
|
||||
export function shouldShowCustomPriceTooLowWarning(state) {
|
||||
const { average } = getSwapGasPriceEstimateData(state)
|
||||
|
||||
const customGasPrice = getSwapsCustomizationModalPrice(state)
|
||||
|
||||
if (!customGasPrice || average === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
const customPriceRisksSwapFailure = conversionLessThan(
|
||||
{
|
||||
value: customGasPrice,
|
||||
fromNumericBase: 'hex',
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'GWEI',
|
||||
},
|
||||
{ value: average, fromNumericBase: 'dec' },
|
||||
)
|
||||
|
||||
return customPriceRisksSwapFailure
|
||||
}
|
||||
|
||||
// Background selectors
|
||||
|
||||
const getSwapsState = (state) => state.metamask.swapsState
|
||||
@ -185,17 +266,8 @@ export const getUsedQuote = (state) =>
|
||||
export const getDestinationTokenInfo = (state) =>
|
||||
getFetchParams(state)?.metaData?.destinationTokenInfo
|
||||
|
||||
export const getSwapsTradeTxParams = (state) => {
|
||||
const { selectedAggId, topAggId, quotes } = getSwapsState(state)
|
||||
const usedQuote = selectedAggId ? quotes[selectedAggId] : quotes[topAggId]
|
||||
if (!usedQuote) {
|
||||
return null
|
||||
}
|
||||
const { trade } = usedQuote
|
||||
const gas = getCustomSwapsGas(state) || trade.gas
|
||||
const gasPrice = getCustomSwapsGasPrice(state) || trade.gasPrice
|
||||
return { ...trade, gas, gasPrice }
|
||||
}
|
||||
export const getUsedSwapsGasPrice = (state) =>
|
||||
getCustomSwapsGasPrice(state) || getSwapsFallbackGasPrice(state)
|
||||
|
||||
export const getApproveTxParams = (state) => {
|
||||
const { approvalNeeded } = getSelectedQuote(state) || getTopQuote(state) || {}
|
||||
@ -215,6 +287,9 @@ const {
|
||||
clearSwapsState,
|
||||
navigatedBackToBuildQuote,
|
||||
retriedGetQuotes,
|
||||
swapGasPriceEstimatesFetchCompleted,
|
||||
swapGasPriceEstimatesFetchStarted,
|
||||
swapGasPriceEstimatesFetchFailed,
|
||||
setAggregatorMetadata,
|
||||
setBalanceError,
|
||||
setFetchingQuotes,
|
||||
@ -222,6 +297,9 @@ const {
|
||||
setQuotesFetchStartTime,
|
||||
setTopAssets,
|
||||
setToToken,
|
||||
swapCustomGasModalPriceEdited,
|
||||
swapCustomGasModalLimitEdited,
|
||||
retrievedFallbackSwapsGasPrice,
|
||||
} = actions
|
||||
|
||||
export {
|
||||
@ -233,6 +311,8 @@ export {
|
||||
setQuotesFetchStartTime as setSwapQuotesFetchStartTime,
|
||||
setTopAssets,
|
||||
setToToken as setSwapToToken,
|
||||
swapCustomGasModalPriceEdited,
|
||||
swapCustomGasModalLimitEdited,
|
||||
}
|
||||
|
||||
export const navigateBackToBuildQuote = (history) => {
|
||||
@ -255,7 +335,6 @@ export const prepareForRetryGetQuotes = () => {
|
||||
|
||||
export const prepareToLeaveSwaps = () => {
|
||||
return async (dispatch) => {
|
||||
dispatch(resetCustomGasState())
|
||||
dispatch(clearSwapsState())
|
||||
await dispatch(resetBackgroundSwapsState())
|
||||
}
|
||||
@ -263,9 +342,11 @@ export const prepareToLeaveSwaps = () => {
|
||||
|
||||
export const fetchAndSetSwapsGasPriceInfo = () => {
|
||||
return async (dispatch) => {
|
||||
const basicEstimates = await dispatch(fetchBasicGasAndTimeEstimates())
|
||||
dispatch(setSwapsTxGasPrice(decGWEIToHexWEI(basicEstimates.fastest)))
|
||||
await dispatch(fetchGasEstimates(basicEstimates.blockTime))
|
||||
const basicEstimates = await dispatch(fetchMetaSwapsGasPriceEstimates())
|
||||
|
||||
if (basicEstimates?.fast) {
|
||||
dispatch(setSwapsTxGasPrice(decGWEIToHexWEI(basicEstimates.fast)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,6 +557,7 @@ export const fetchQuotesAndSetQuoteState = (
|
||||
}
|
||||
// TODO: Check for any errors we should expect to occur in production, and report others to Sentry
|
||||
log.error(`Error fetching quotes: `, e)
|
||||
|
||||
dispatch(setSwapsErrorKey(ERROR_FETCHING_QUOTES))
|
||||
}
|
||||
|
||||
@ -507,6 +589,8 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
||||
await dispatch(stopPollingForQuotes())
|
||||
history.push(AWAITING_SWAP_ROUTE)
|
||||
|
||||
const { fast: fastGasEstimate } = getSwapGasPriceEstimateData(state)
|
||||
|
||||
const usedQuote = getUsedQuote(state)
|
||||
const usedTradeTxParams = usedQuote.trade
|
||||
|
||||
@ -524,13 +608,9 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
||||
`0x${decimalToHex(usedQuote?.maxGas || 0)}`,
|
||||
estimatedGasLimitWithMultiplier,
|
||||
)
|
||||
usedTradeTxParams.gas = maxGasLimit
|
||||
|
||||
const customConvertGasPrice = getCustomSwapsGasPrice(state)
|
||||
const tradeTxParams = getSwapsTradeTxParams(state)
|
||||
const fastGasEstimate = getFastPriceEstimateInHexWEI(state)
|
||||
const usedGasPrice =
|
||||
customConvertGasPrice || tradeTxParams?.gasPrice || fastGasEstimate
|
||||
const usedGasPrice = getUsedSwapsGasPrice(state)
|
||||
usedTradeTxParams.gas = maxGasLimit
|
||||
usedTradeTxParams.gasPrice = usedGasPrice
|
||||
|
||||
const conversionRate = getConversionRate(state)
|
||||
@ -568,8 +648,8 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
||||
: usedQuote.aggregator,
|
||||
gas_fees: formatCurrency(gasEstimateTotalInEth, 'usd')?.slice(1),
|
||||
estimated_gas: estimatedGasLimit.toString(10),
|
||||
suggested_gas_price: hexWEIToDecGWEI(usedGasPrice),
|
||||
used_gas_price: hexWEIToDecGWEI(fastGasEstimate),
|
||||
suggested_gas_price: fastGasEstimate,
|
||||
used_gas_price: hexWEIToDecGWEI(usedGasPrice),
|
||||
average_savings: usedQuote.savings?.performance,
|
||||
}
|
||||
|
||||
@ -645,3 +725,68 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
||||
await forceUpdateMetamaskState(dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchMetaSwapsGasPriceEstimates() {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState()
|
||||
const priceEstimatesLastRetrieved = getSwapsPriceEstimatesLastRetrieved(
|
||||
state,
|
||||
)
|
||||
const timeLastRetrieved =
|
||||
priceEstimatesLastRetrieved ||
|
||||
loadLocalStorageData('METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED') ||
|
||||
0
|
||||
|
||||
dispatch(swapGasPriceEstimatesFetchStarted())
|
||||
|
||||
let priceEstimates
|
||||
try {
|
||||
if (Date.now() - timeLastRetrieved > 30000) {
|
||||
priceEstimates = await fetchSwapsGasPrices()
|
||||
} else {
|
||||
const cachedPriceEstimates = loadLocalStorageData(
|
||||
'METASWAP_GAS_PRICE_ESTIMATES',
|
||||
)
|
||||
priceEstimates = cachedPriceEstimates || (await fetchSwapsGasPrices())
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn('Fetching swaps gas prices failed:', e)
|
||||
|
||||
if (!e.message?.match(/NetworkError|Fetch failed with status:/u)) {
|
||||
throw e
|
||||
}
|
||||
|
||||
dispatch(swapGasPriceEstimatesFetchFailed())
|
||||
|
||||
try {
|
||||
const gasPrice = await global.ethQuery.gasPrice()
|
||||
const gasPriceInDecGWEI = hexWEIToDecGWEI(gasPrice.toString(10))
|
||||
|
||||
dispatch(retrievedFallbackSwapsGasPrice(gasPriceInDecGWEI))
|
||||
return null
|
||||
} catch (networkGasPriceError) {
|
||||
console.error(
|
||||
`Failed to retrieve fallback gas price: `,
|
||||
networkGasPriceError,
|
||||
)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const timeRetrieved = Date.now()
|
||||
|
||||
saveLocalStorageData(priceEstimates, 'METASWAP_GAS_PRICE_ESTIMATES')
|
||||
saveLocalStorageData(
|
||||
timeRetrieved,
|
||||
'METASWAP_GAS_PRICE_ESTIMATES_LAST_RETRIEVED',
|
||||
)
|
||||
|
||||
dispatch(
|
||||
swapGasPriceEstimatesFetchCompleted({
|
||||
priceEstimates,
|
||||
priceEstimatesLastRetrieved: timeRetrieved,
|
||||
}),
|
||||
)
|
||||
return priceEstimates
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
getUsedQuote,
|
||||
getFetchParams,
|
||||
getApproveTxParams,
|
||||
getSwapsTradeTxParams,
|
||||
getUsedSwapsGasPrice,
|
||||
fetchQuotesAndSetQuoteState,
|
||||
navigateBackToBuildQuote,
|
||||
prepareForRetryGetQuotes,
|
||||
@ -67,7 +67,7 @@ export default function AwaitingSwap({
|
||||
const { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {}
|
||||
const usedQuote = useSelector(getUsedQuote)
|
||||
const approveTxParams = useSelector(getApproveTxParams)
|
||||
const tradeTxParams = useSelector(getSwapsTradeTxParams)
|
||||
const swapsGasPrice = useSelector(getUsedSwapsGasPrice)
|
||||
const currentCurrency = useSelector(getCurrentCurrency)
|
||||
const conversionRate = useSelector(conversionRateSelector)
|
||||
|
||||
@ -77,14 +77,15 @@ export default function AwaitingSwap({
|
||||
)
|
||||
|
||||
let feeinFiat
|
||||
if (usedQuote && tradeTxParams) {
|
||||
|
||||
if (usedQuote && swapsGasPrice) {
|
||||
const renderableNetworkFees = getRenderableNetworkFeesForQuote(
|
||||
usedQuote.gasEstimateWithRefund || usedQuote.averageGas,
|
||||
approveTxParams?.gas || '0x0',
|
||||
tradeTxParams.gasPrice,
|
||||
swapsGasPrice,
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
tradeTxParams.value,
|
||||
usedQuote?.trade?.value,
|
||||
sourceTokenInfo?.symbol,
|
||||
usedQuote.sourceAmount,
|
||||
)
|
||||
|
@ -21,9 +21,8 @@ import {
|
||||
getApproveTxId,
|
||||
getFetchingQuotes,
|
||||
setBalanceError,
|
||||
getCustomSwapsGasPrice,
|
||||
setTopAssets,
|
||||
getSwapsTradeTxParams,
|
||||
getUsedSwapsGasPrice,
|
||||
getFetchParams,
|
||||
setAggregatorMetadata,
|
||||
getAggregatorMetadata,
|
||||
@ -33,7 +32,6 @@ import {
|
||||
prepareToLeaveSwaps,
|
||||
fetchAndSetSwapsGasPriceInfo,
|
||||
} from '../../ducks/swaps/swaps'
|
||||
import { resetCustomGasState } from '../../ducks/gas/gas.duck'
|
||||
import {
|
||||
AWAITING_SWAP_ROUTE,
|
||||
BUILD_QUOTE_ROUTE,
|
||||
@ -59,7 +57,6 @@ import {
|
||||
setSwapsErrorKey,
|
||||
} from '../../store/actions'
|
||||
import {
|
||||
getFastPriceEstimateInHexWEI,
|
||||
currentNetworkTxListSelector,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
} from '../../selectors'
|
||||
@ -96,11 +93,9 @@ export default function Swap() {
|
||||
const [maxSlippage, setMaxSlippage] = useState(fetchParams?.slippage || 2)
|
||||
|
||||
const routeState = useSelector(getBackgroundSwapRouteState)
|
||||
const tradeTxParams = useSelector(getSwapsTradeTxParams)
|
||||
const usedGasPrice = useSelector(getUsedSwapsGasPrice)
|
||||
const selectedAccount = useSelector(getSelectedAccount)
|
||||
const quotes = useSelector(getQuotes)
|
||||
const fastGasEstimate = useSelector(getFastPriceEstimateInHexWEI)
|
||||
const customConvertGasPrice = useSelector(getCustomSwapsGasPrice)
|
||||
const txList = useSelector(currentNetworkTxListSelector)
|
||||
const tradeTxId = useSelector(getTradeTxId)
|
||||
const approveTxId = useSelector(getApproveTxId)
|
||||
@ -131,8 +126,6 @@ export default function Swap() {
|
||||
useSelector(getFromToken) || fetchParamsFromToken || {}
|
||||
const { destinationTokenAddedForSwap } = fetchParams || {}
|
||||
|
||||
const usedGasPrice =
|
||||
customConvertGasPrice || tradeTxParams?.gasPrice || fastGasEstimate
|
||||
const approveTxData =
|
||||
approveTxId && txList.find(({ id }) => approveTxId === id)
|
||||
const tradeTxData = tradeTxId && txList.find(({ id }) => tradeTxId === id)
|
||||
@ -197,7 +190,6 @@ export default function Swap() {
|
||||
dispatch(setAggregatorMetadata(newAggregatorMetadata))
|
||||
})
|
||||
|
||||
dispatch(resetCustomGasState())
|
||||
dispatch(fetchAndSetSwapsGasPriceInfo())
|
||||
|
||||
return () => {
|
||||
|
@ -0,0 +1 @@
|
||||
export { default } from './swaps-gas-customization-modal.container'
|
@ -0,0 +1,269 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import PageContainer from '../../../components/ui/page-container'
|
||||
import { Tabs, Tab } from '../../../components/ui/tabs'
|
||||
import { calcGasTotal } from '../../send/send.utils'
|
||||
import { sumHexWEIsToRenderableFiat } from '../../../helpers/utils/conversions.util'
|
||||
import AdvancedGasInputs from '../../../components/app/gas-customization/advanced-gas-inputs'
|
||||
import BasicTabContent from '../../../components/app/gas-customization/gas-modal-page-container/basic-tab-content'
|
||||
import { GAS_ESTIMATE_TYPES } from '../../../helpers/constants/common'
|
||||
|
||||
export default class GasModalPageContainer extends Component {
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
trackEvent: PropTypes.func,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
insufficientBalance: PropTypes.bool,
|
||||
gasPriceButtonGroupProps: PropTypes.object,
|
||||
infoRowProps: PropTypes.shape({
|
||||
originalTotalFiat: PropTypes.string,
|
||||
originalTotalEth: PropTypes.string,
|
||||
newTotalFiat: PropTypes.string,
|
||||
newTotalEth: PropTypes.string,
|
||||
sendAmount: PropTypes.string,
|
||||
transactionFee: PropTypes.string,
|
||||
extraInfoRow: PropTypes.shape({
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
onSubmit: PropTypes.func,
|
||||
cancelAndClose: PropTypes.func,
|
||||
showCustomPriceTooLowWarning: PropTypes.bool,
|
||||
disableSave: PropTypes.bool,
|
||||
customGasLimitMessage: PropTypes.string,
|
||||
customTotalSupplement: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
conversionRate: PropTypes.string,
|
||||
customGasPrice: PropTypes.string,
|
||||
customGasLimit: PropTypes.string,
|
||||
setSwapsCustomizationModalPrice: PropTypes.func,
|
||||
setSwapsCustomizationModalLimit: PropTypes.func,
|
||||
gasEstimateLoadingHasFailed: PropTypes.bool,
|
||||
}
|
||||
|
||||
state = {
|
||||
gasSpeedType: '',
|
||||
}
|
||||
|
||||
setGasSpeedType(gasEstimateType) {
|
||||
if (gasEstimateType === GAS_ESTIMATE_TYPES.AVERAGE) {
|
||||
this.setState({ gasSpeedType: 'average' })
|
||||
} else {
|
||||
this.setState({ gasSpeedType: 'fast' })
|
||||
}
|
||||
}
|
||||
|
||||
renderBasicTabContent(gasPriceButtonGroupProps) {
|
||||
return (
|
||||
<BasicTabContent
|
||||
gasPriceButtonGroupProps={{
|
||||
...gasPriceButtonGroupProps,
|
||||
handleGasPriceSelection: (gasPriceInHexWei, gasEstimateType) => {
|
||||
this.setGasSpeedType(gasEstimateType)
|
||||
this.props.setSwapsCustomizationModalPrice(gasPriceInHexWei)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
renderAdvancedTabContent() {
|
||||
const {
|
||||
insufficientBalance,
|
||||
showCustomPriceTooLowWarning,
|
||||
infoRowProps: { transactionFee },
|
||||
customGasLimitMessage,
|
||||
setSwapsCustomizationModalPrice,
|
||||
setSwapsCustomizationModalLimit,
|
||||
customGasPrice,
|
||||
customGasLimit,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className="advanced-tab">
|
||||
<div className="advanced-tab__transaction-data-summary">
|
||||
<div className="advanced-tab__transaction-data-summary__titles">
|
||||
<span>{this.context.t('newTransactionFee')}</span>
|
||||
</div>
|
||||
<div className="advanced-tab__transaction-data-summary__container">
|
||||
<div className="advanced-tab__transaction-data-summary__fee">
|
||||
{transactionFee}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="advanced-tab__fee-chart">
|
||||
<div className="advanced-tab__gas-inputs">
|
||||
<AdvancedGasInputs
|
||||
updateCustomGasPrice={(updatedPrice) => {
|
||||
this.setState({ gasSpeedType: 'custom' })
|
||||
setSwapsCustomizationModalPrice(updatedPrice)
|
||||
}}
|
||||
updateCustomGasLimit={(updatedLimit) => {
|
||||
this.setState({ gasSpeedType: 'custom' })
|
||||
setSwapsCustomizationModalLimit(updatedLimit)
|
||||
}}
|
||||
customGasPrice={customGasPrice}
|
||||
customGasLimit={customGasLimit}
|
||||
insufficientBalance={insufficientBalance}
|
||||
customPriceIsSafe={!showCustomPriceTooLowWarning}
|
||||
customGasLimitMessage={customGasLimitMessage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderInfoRows(
|
||||
newTotalFiat,
|
||||
newTotalEth,
|
||||
sendAmount,
|
||||
transactionFee,
|
||||
extraInfoRow,
|
||||
) {
|
||||
return (
|
||||
<div className="gas-modal-content__info-row-wrapper">
|
||||
<div className="gas-modal-content__info-row">
|
||||
<div className="gas-modal-content__info-row__send-info">
|
||||
<span className="gas-modal-content__info-row__send-info__label">
|
||||
{this.context.t('sendAmount')}
|
||||
</span>
|
||||
<span className="gas-modal-content__info-row__send-info__value">
|
||||
{sendAmount}
|
||||
</span>
|
||||
</div>
|
||||
<div className="gas-modal-content__info-row__transaction-info">
|
||||
<span className="gas-modal-content__info-row__transaction-info__label">
|
||||
{this.context.t('transactionFee')}
|
||||
</span>
|
||||
<span className="gas-modal-content__info-row__transaction-info__value">
|
||||
{transactionFee}
|
||||
</span>
|
||||
</div>
|
||||
{extraInfoRow && (
|
||||
<div className="gas-modal-content__info-row__transaction-info">
|
||||
<span className="gas-modal-content__info-row__transaction-info__label">
|
||||
{extraInfoRow.label}
|
||||
</span>
|
||||
<span className="gas-modal-content__info-row__transaction-info__value">
|
||||
{extraInfoRow.value}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="gas-modal-content__info-row__total-info">
|
||||
<span className="gas-modal-content__info-row__total-info__label">
|
||||
{this.context.t('newTotal')}
|
||||
</span>
|
||||
<span className="gas-modal-content__info-row__total-info__value">
|
||||
{newTotalEth}
|
||||
</span>
|
||||
</div>
|
||||
<div className="gas-modal-content__info-row__fiat-total-info">
|
||||
<span className="gas-modal-content__info-row__fiat-total-info__value">
|
||||
{newTotalFiat}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderTabs() {
|
||||
const {
|
||||
gasPriceButtonGroupProps,
|
||||
infoRowProps: {
|
||||
newTotalFiat,
|
||||
newTotalEth,
|
||||
sendAmount,
|
||||
transactionFee,
|
||||
extraInfoRow,
|
||||
},
|
||||
gasEstimateLoadingHasFailed,
|
||||
} = this.props
|
||||
|
||||
const basicTabInfo = {
|
||||
name: this.context.t('basic'),
|
||||
content: this.renderBasicTabContent({
|
||||
...gasPriceButtonGroupProps,
|
||||
handleGasPriceSelection: this.props.setSwapsCustomizationModalPrice,
|
||||
}),
|
||||
}
|
||||
const advancedTabInfo = {
|
||||
name: this.context.t('advanced'),
|
||||
content: this.renderAdvancedTabContent(),
|
||||
}
|
||||
|
||||
const tabsToRender = gasEstimateLoadingHasFailed
|
||||
? [advancedTabInfo]
|
||||
: [basicTabInfo, advancedTabInfo]
|
||||
|
||||
return (
|
||||
<Tabs>
|
||||
{tabsToRender.map(({ name, content }, i) => (
|
||||
<Tab name={name} key={`gas-modal-tab-${i}`}>
|
||||
<div className="gas-modal-content">
|
||||
{content}
|
||||
{this.renderInfoRows(
|
||||
newTotalFiat,
|
||||
newTotalEth,
|
||||
sendAmount,
|
||||
transactionFee,
|
||||
extraInfoRow,
|
||||
)}
|
||||
</div>
|
||||
</Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
cancelAndClose,
|
||||
onSubmit,
|
||||
disableSave,
|
||||
customGasPrice,
|
||||
customGasLimit,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className="gas-modal-page-container">
|
||||
<PageContainer
|
||||
title={this.context.t('customGas')}
|
||||
subtitle={this.context.t('customGasSubTitle')}
|
||||
tabsComponent={this.renderTabs()}
|
||||
disabled={disableSave}
|
||||
onCancel={() => cancelAndClose()}
|
||||
onClose={() => cancelAndClose()}
|
||||
onSubmit={() => {
|
||||
const newSwapGasTotal = calcGasTotal(customGasLimit, customGasPrice)
|
||||
|
||||
this.context.trackEvent({
|
||||
event: 'Gas Fees Changed',
|
||||
category: 'swaps',
|
||||
properties: {
|
||||
speed_set: this.state.gasSpeedType,
|
||||
gas_fees: sumHexWEIsToRenderableFiat(
|
||||
[
|
||||
this.props.value,
|
||||
newSwapGasTotal,
|
||||
this.props.customTotalSupplement,
|
||||
],
|
||||
'usd',
|
||||
this.props.conversionRate,
|
||||
)?.slice(1),
|
||||
},
|
||||
})
|
||||
onSubmit(customGasLimit, customGasPrice)
|
||||
}}
|
||||
submitText={this.context.t('save')}
|
||||
headerCloseText={this.context.t('close')}
|
||||
hideCancel
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
import { connect } from 'react-redux'
|
||||
import { hideModal, customSwapsGasParamsUpdated } from '../../../store/actions'
|
||||
import {
|
||||
conversionRateSelector as getConversionRate,
|
||||
getCurrentCurrency,
|
||||
getCurrentEthBalance,
|
||||
getDefaultActiveButtonIndex,
|
||||
getRenderableGasButtonData,
|
||||
} from '../../../selectors'
|
||||
|
||||
import {
|
||||
getSwapsCustomizationModalPrice,
|
||||
getSwapsCustomizationModalLimit,
|
||||
swapGasEstimateLoadingHasFailed,
|
||||
swapGasPriceEstimateIsLoading,
|
||||
getSwapGasPriceEstimateData,
|
||||
swapCustomGasModalPriceEdited,
|
||||
swapCustomGasModalLimitEdited,
|
||||
shouldShowCustomPriceTooLowWarning,
|
||||
} from '../../../ducks/swaps/swaps'
|
||||
|
||||
import {
|
||||
addHexes,
|
||||
getValueFromWeiHex,
|
||||
sumHexWEIsToRenderableFiat,
|
||||
} from '../../../helpers/utils/conversions.util'
|
||||
import { formatETHFee } from '../../../helpers/utils/formatters'
|
||||
import { calcGasTotal, isBalanceSufficient } from '../../send/send.utils'
|
||||
import SwapsGasCustomizationModalComponent from './swaps-gas-customization-modal.component'
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const currentCurrency = getCurrentCurrency(state)
|
||||
const conversionRate = getConversionRate(state)
|
||||
|
||||
const { modalState: { props: modalProps } = {} } = state.appState.modal || {}
|
||||
const {
|
||||
value,
|
||||
customGasLimitMessage = '',
|
||||
customTotalSupplement = '',
|
||||
extraInfoRow = null,
|
||||
initialGasPrice,
|
||||
initialGasLimit,
|
||||
} = modalProps || {}
|
||||
const buttonDataLoading = swapGasPriceEstimateIsLoading(state)
|
||||
|
||||
const swapsCustomizationModalPrice = getSwapsCustomizationModalPrice(state)
|
||||
const swapsCustomizationModalLimit = getSwapsCustomizationModalLimit(state)
|
||||
|
||||
const customGasPrice = swapsCustomizationModalPrice || initialGasPrice
|
||||
const customGasLimit = swapsCustomizationModalLimit || initialGasLimit
|
||||
|
||||
const customGasTotal = calcGasTotal(customGasLimit, customGasPrice)
|
||||
|
||||
const swapsGasPriceEstimates = getSwapGasPriceEstimateData(state)
|
||||
|
||||
const { averageEstimateData, fastEstimateData } = getRenderableGasButtonData(
|
||||
swapsGasPriceEstimates,
|
||||
customGasLimit,
|
||||
true,
|
||||
conversionRate,
|
||||
currentCurrency,
|
||||
)
|
||||
const gasButtonInfo = [averageEstimateData, fastEstimateData]
|
||||
|
||||
const newTotalFiat = sumHexWEIsToRenderableFiat(
|
||||
[value, customGasTotal, customTotalSupplement],
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
)
|
||||
|
||||
const balance = getCurrentEthBalance(state)
|
||||
|
||||
const newTotalEth = sumHexWEIsToRenderableEth([
|
||||
value,
|
||||
customGasTotal,
|
||||
customTotalSupplement,
|
||||
])
|
||||
|
||||
const sendAmount = sumHexWEIsToRenderableEth([value, '0x0'])
|
||||
|
||||
const insufficientBalance = !isBalanceSufficient({
|
||||
amount: value,
|
||||
gasTotal: customGasTotal,
|
||||
balance,
|
||||
conversionRate,
|
||||
})
|
||||
|
||||
return {
|
||||
customGasPrice,
|
||||
customGasLimit,
|
||||
showCustomPriceTooLowWarning: shouldShowCustomPriceTooLowWarning(state),
|
||||
gasPriceButtonGroupProps: {
|
||||
buttonDataLoading,
|
||||
defaultActiveButtonIndex: getDefaultActiveButtonIndex(
|
||||
gasButtonInfo,
|
||||
customGasPrice,
|
||||
),
|
||||
gasButtonInfo,
|
||||
},
|
||||
infoRowProps: {
|
||||
originalTotalFiat: sumHexWEIsToRenderableFiat(
|
||||
[value, customGasTotal, customTotalSupplement],
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
),
|
||||
originalTotalEth: sumHexWEIsToRenderableEth([
|
||||
value,
|
||||
customGasTotal,
|
||||
customTotalSupplement,
|
||||
]),
|
||||
newTotalFiat,
|
||||
newTotalEth,
|
||||
transactionFee: sumHexWEIsToRenderableEth(['0x0', customGasTotal]),
|
||||
sendAmount,
|
||||
extraInfoRow,
|
||||
},
|
||||
gasEstimateLoadingHasFailed: swapGasEstimateLoadingHasFailed(state),
|
||||
insufficientBalance,
|
||||
customGasLimitMessage,
|
||||
customTotalSupplement,
|
||||
conversionRate,
|
||||
value,
|
||||
disableSave: insufficientBalance,
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
cancelAndClose: () => {
|
||||
dispatch(hideModal())
|
||||
},
|
||||
onSubmit: (gasLimit, gasPrice) => {
|
||||
dispatch(customSwapsGasParamsUpdated(gasLimit, gasPrice))
|
||||
dispatch(hideModal())
|
||||
},
|
||||
setSwapsCustomizationModalPrice: (newPrice) => {
|
||||
dispatch(swapCustomGasModalPriceEdited(newPrice))
|
||||
},
|
||||
setSwapsCustomizationModalLimit: (newLimit) => {
|
||||
dispatch(swapCustomGasModalLimitEdited(newLimit))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(SwapsGasCustomizationModalComponent)
|
||||
|
||||
function sumHexWEIsToRenderableEth(hexWEIs) {
|
||||
const hexWEIsSum = hexWEIs.filter((n) => n).reduce(addHexes)
|
||||
return formatETHFee(
|
||||
getValueFromWeiHex({
|
||||
value: hexWEIsSum,
|
||||
toCurrency: 'ETH',
|
||||
numberOfDecimals: 6,
|
||||
}),
|
||||
)
|
||||
}
|
@ -36,6 +36,8 @@ const getBaseApi = function (type) {
|
||||
return `https://api.metaswap.codefi.network/featureFlag`
|
||||
case 'aggregatorMetadata':
|
||||
return `https://api.metaswap.codefi.network/aggregatorMetadata`
|
||||
case 'gasPrices':
|
||||
return `https://api.metaswap.codefi.network/gasPrices`
|
||||
default:
|
||||
throw new Error('getBaseApi requires an api call type')
|
||||
}
|
||||
@ -150,6 +152,27 @@ const AGGREGATOR_METADATA_VALIDATORS = [
|
||||
},
|
||||
]
|
||||
|
||||
const isValidDecimalNumber = (string) =>
|
||||
!isNaN(string) && string.match(/^[.0-9]+$/u) && !isNaN(parseFloat(string))
|
||||
|
||||
const SWAP_GAS_PRICE_VALIDATOR = [
|
||||
{
|
||||
property: 'SafeGasPrice',
|
||||
type: 'string',
|
||||
validator: isValidDecimalNumber,
|
||||
},
|
||||
{
|
||||
property: 'ProposeGasPrice',
|
||||
type: 'string',
|
||||
validator: isValidDecimalNumber,
|
||||
},
|
||||
{
|
||||
property: 'FastGasPrice',
|
||||
type: 'string',
|
||||
validator: isValidDecimalNumber,
|
||||
},
|
||||
]
|
||||
|
||||
function validateData(validators, object, urlUsed) {
|
||||
return validators.every(({ property, type, validator }) => {
|
||||
const types = type.split('|')
|
||||
@ -320,6 +343,36 @@ export async function fetchTokenBalance(address, userAddress) {
|
||||
return usersToken
|
||||
}
|
||||
|
||||
export async function fetchSwapsGasPrices() {
|
||||
const gasPricesUrl = getBaseApi('gasPrices')
|
||||
const response = await fetchWithCache(
|
||||
gasPricesUrl,
|
||||
{ method: 'GET' },
|
||||
{ cacheRefreshTime: 15000 },
|
||||
)
|
||||
const responseIsValid = validateData(
|
||||
SWAP_GAS_PRICE_VALIDATOR,
|
||||
response,
|
||||
gasPricesUrl,
|
||||
)
|
||||
|
||||
if (!responseIsValid) {
|
||||
throw new Error(`${gasPricesUrl} response is invalid`)
|
||||
}
|
||||
|
||||
const {
|
||||
SafeGasPrice: safeLow,
|
||||
ProposeGasPrice: average,
|
||||
FastGasPrice: fast,
|
||||
} = response
|
||||
|
||||
return {
|
||||
safeLow,
|
||||
average,
|
||||
fast,
|
||||
}
|
||||
}
|
||||
|
||||
export function getRenderableNetworkFeesForQuote(
|
||||
tradeGas,
|
||||
approveGas,
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
getBalanceError,
|
||||
getCustomSwapsGas,
|
||||
getDestinationTokenInfo,
|
||||
getSwapsTradeTxParams,
|
||||
getUsedSwapsGasPrice,
|
||||
getTopQuote,
|
||||
navigateBackToBuildQuote,
|
||||
signAndSendTransactions,
|
||||
@ -101,8 +101,7 @@ export default function ViewQuote() {
|
||||
const quotesLastFetched = useSelector(getQuotesLastFetched)
|
||||
|
||||
// Select necessary data
|
||||
const tradeTxParams = useSelector(getSwapsTradeTxParams)
|
||||
const { gasPrice, value: tradeValue } = tradeTxParams || {}
|
||||
const gasPrice = useSelector(getUsedSwapsGasPrice)
|
||||
const customMaxGas = useSelector(getCustomSwapsGas)
|
||||
const tokenConversionRates = useSelector(getTokenExchangeRates)
|
||||
const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates)
|
||||
@ -116,6 +115,7 @@ export default function ViewQuote() {
|
||||
const selectedQuote = useSelector(getSelectedQuote)
|
||||
const topQuote = useSelector(getTopQuote)
|
||||
const usedQuote = selectedQuote || topQuote
|
||||
const { value: tradeValue = '0x0' } = usedQuote?.trade?.value || {}
|
||||
|
||||
const fetchParamsSourceToken = fetchParams?.sourceToken
|
||||
|
||||
@ -454,9 +454,8 @@ export default function ViewQuote() {
|
||||
const onFeeCardMaxRowClick = () =>
|
||||
dispatch(
|
||||
showModal({
|
||||
name: 'CUSTOMIZE_GAS',
|
||||
txData: { txParams: { ...tradeTxParams, gas: maxGasLimit } },
|
||||
isSwap: true,
|
||||
name: 'CUSTOMIZE_METASWAP_GAS',
|
||||
value: usedQuote.value,
|
||||
customGasLimitMessage: approveGas
|
||||
? t('extraApprovalGas', [hexToDecimal(approveGas)])
|
||||
: '',
|
||||
@ -467,8 +466,8 @@ export default function ViewQuote() {
|
||||
value: t('amountInEth', [extraNetworkFeeTotalInEth]),
|
||||
}
|
||||
: null,
|
||||
useFastestButtons: true,
|
||||
minimumGasLimit: Number(hexToDecimal(nonCustomMaxGasLimit)),
|
||||
initialGasPrice: gasPrice,
|
||||
initialGasLimit: maxGasLimit,
|
||||
}),
|
||||
)
|
||||
|
||||
@ -605,7 +604,7 @@ export default function ViewQuote() {
|
||||
}}
|
||||
submitText={t('swap')}
|
||||
onCancel={async () => await dispatch(navigateBackToBuildQuote(history))}
|
||||
disabled={balanceError}
|
||||
disabled={balanceError || gasPrice === null || gasPrice === undefined}
|
||||
showTermsOfService
|
||||
showTopBorder
|
||||
/>
|
||||
|
@ -80,20 +80,8 @@ export function getSafeLowEstimate(state) {
|
||||
return safeLow
|
||||
}
|
||||
|
||||
export function getAverageEstimate(state) {
|
||||
const {
|
||||
gas: {
|
||||
basicEstimates: { average },
|
||||
},
|
||||
} = state
|
||||
|
||||
return average
|
||||
}
|
||||
|
||||
export function isCustomPriceSafe(state, averageIsSafe) {
|
||||
export function isCustomPriceSafe(state) {
|
||||
const safeLow = getSafeLowEstimate(state)
|
||||
const average = getAverageEstimate(state)
|
||||
const safeMinimumPrice = averageIsSafe ? average : safeLow
|
||||
|
||||
const customGasPrice = getCustomGasPrice(state)
|
||||
|
||||
@ -101,7 +89,7 @@ export function isCustomPriceSafe(state, averageIsSafe) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (safeMinimumPrice === null) {
|
||||
if (safeLow === null) {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -112,7 +100,7 @@ export function isCustomPriceSafe(state, averageIsSafe) {
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'GWEI',
|
||||
},
|
||||
{ value: safeMinimumPrice, fromNumericBase: 'dec' },
|
||||
{ value: safeLow, fromNumericBase: 'dec' },
|
||||
)
|
||||
|
||||
return customPriceSafe
|
||||
@ -219,23 +207,14 @@ export function getGasPriceInHexWei(price) {
|
||||
return addHexPrefix(priceEstimateToWei(value))
|
||||
}
|
||||
|
||||
export function getRenderableBasicEstimateData(
|
||||
state,
|
||||
export function getRenderableGasButtonData(
|
||||
estimates,
|
||||
gasLimit,
|
||||
useFastestButtons,
|
||||
showFiat,
|
||||
conversionRate,
|
||||
currentCurrency,
|
||||
) {
|
||||
if (getBasicGasEstimateLoadingStatus(state)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const { showFiatInTestnets } = getPreferences(state)
|
||||
const isMainnet = getIsMainnet(state)
|
||||
const showFiat = isMainnet || Boolean(showFiatInTestnets)
|
||||
const { conversionRate } = state.metamask
|
||||
const currentCurrency = getCurrentCurrency(state)
|
||||
const {
|
||||
gas: {
|
||||
basicEstimates: {
|
||||
safeLow,
|
||||
average,
|
||||
fast,
|
||||
@ -244,9 +223,7 @@ export function getRenderableBasicEstimateData(
|
||||
fastWait,
|
||||
fastest,
|
||||
fastestWait,
|
||||
},
|
||||
},
|
||||
} = state
|
||||
} = estimates
|
||||
|
||||
const slowEstimateData = {
|
||||
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
||||
@ -305,9 +282,38 @@ export function getRenderableBasicEstimateData(
|
||||
priceInHexWei: getGasPriceInHexWei(fastest),
|
||||
}
|
||||
|
||||
return useFastestButtons
|
||||
? [fastEstimateData, fastestEstimateData]
|
||||
: [slowEstimateData, averageEstimateData, fastEstimateData]
|
||||
return {
|
||||
slowEstimateData,
|
||||
averageEstimateData,
|
||||
fastEstimateData,
|
||||
fastestEstimateData,
|
||||
}
|
||||
}
|
||||
|
||||
export function getRenderableBasicEstimateData(state, gasLimit) {
|
||||
if (getBasicGasEstimateLoadingStatus(state)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const { showFiatInTestnets } = getPreferences(state)
|
||||
const isMainnet = getIsMainnet(state)
|
||||
const showFiat = isMainnet || Boolean(showFiatInTestnets)
|
||||
const { conversionRate } = state.metamask
|
||||
const currentCurrency = getCurrentCurrency(state)
|
||||
|
||||
const {
|
||||
slowEstimateData,
|
||||
averageEstimateData,
|
||||
fastEstimateData,
|
||||
} = getRenderableGasButtonData(
|
||||
state.gas.basicEstimates,
|
||||
gasLimit,
|
||||
showFiat,
|
||||
conversionRate,
|
||||
currentCurrency,
|
||||
)
|
||||
|
||||
return [slowEstimateData, averageEstimateData, fastEstimateData]
|
||||
}
|
||||
|
||||
export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) {
|
||||
|
@ -348,53 +348,6 @@ describe('custom-gas selectors', function () {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedResult: [
|
||||
{
|
||||
gasEstimateType: 'FAST',
|
||||
feeInSecondaryCurrency: '$0.54',
|
||||
feeInPrimaryCurrency: '0.00021 ETH',
|
||||
timeEstimate: '~6 min 36 sec',
|
||||
priceInHexWei: '0x2540be400',
|
||||
},
|
||||
{
|
||||
feeInPrimaryCurrency: '0.00042 ETH',
|
||||
feeInSecondaryCurrency: '$1.07',
|
||||
gasEstimateType: 'FASTEST',
|
||||
priceInHexWei: '0x4a817c800',
|
||||
timeEstimate: '~1 min',
|
||||
},
|
||||
],
|
||||
mockState: {
|
||||
metamask: {
|
||||
conversionRate: 2557.1,
|
||||
currentCurrency: 'usd',
|
||||
send: {
|
||||
gasLimit: '0x5208',
|
||||
},
|
||||
preferences: {
|
||||
showFiatInTestnets: true,
|
||||
},
|
||||
provider: {
|
||||
type: 'mainnet',
|
||||
},
|
||||
},
|
||||
gas: {
|
||||
basicEstimates: {
|
||||
blockTime: 14.16326530612245,
|
||||
safeLow: 5,
|
||||
safeLowWait: 13.2,
|
||||
average: 7,
|
||||
avgWait: 10.1,
|
||||
fast: 10,
|
||||
fastWait: 6.6,
|
||||
fastest: 20,
|
||||
fastestWait: 1.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
useFastestButtons: true,
|
||||
},
|
||||
]
|
||||
it('should return renderable data about basic estimates', function () {
|
||||
tests.forEach((test) => {
|
||||
|
@ -2288,7 +2288,7 @@ export function setSwapsTxGasLimit(gasLimit) {
|
||||
}
|
||||
}
|
||||
|
||||
export function setSwapsTxGasParams(gasLimit, gasPrice) {
|
||||
export function customSwapsGasParamsUpdated(gasLimit, gasPrice) {
|
||||
return async (dispatch) => {
|
||||
await promisifiedBackground.setSwapsTxGasPrice(gasPrice)
|
||||
await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true)
|
||||
|
Loading…
Reference in New Issue
Block a user