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,
|
isSpeedUp: PropTypes.bool,
|
||||||
isEthereumNetwork: PropTypes.bool,
|
isEthereumNetwork: PropTypes.bool,
|
||||||
customGasLimitMessage: PropTypes.string,
|
customGasLimitMessage: PropTypes.string,
|
||||||
minimumGasLimit: PropTypes.number.isRequired,
|
minimumGasLimit: PropTypes.number,
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDataSummary(transactionFee, timeRemaining) {
|
renderDataSummary(transactionFee, timeRemaining) {
|
||||||
|
@ -103,7 +103,7 @@ describe('AdvancedTabContent Component', function () {
|
|||||||
const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(
|
const renderDataSummaryArgs = AdvancedTabContent.prototype.renderDataSummary.getCall(
|
||||||
0,
|
0,
|
||||||
).args
|
).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 PropTypes from 'prop-types'
|
||||||
import PageContainer from '../../../ui/page-container'
|
import PageContainer from '../../../ui/page-container'
|
||||||
import { Tabs, Tab } from '../../../ui/tabs'
|
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 AdvancedTabContent from './advanced-tab-content'
|
||||||
import BasicTabContent from './basic-tab-content'
|
import BasicTabContent from './basic-tab-content'
|
||||||
|
|
||||||
@ -32,10 +30,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
newTotalEth: PropTypes.string,
|
newTotalEth: PropTypes.string,
|
||||||
sendAmount: PropTypes.string,
|
sendAmount: PropTypes.string,
|
||||||
transactionFee: PropTypes.string,
|
transactionFee: PropTypes.string,
|
||||||
extraInfoRow: PropTypes.shape({
|
|
||||||
label: PropTypes.string,
|
|
||||||
value: PropTypes.string,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
onSubmit: PropTypes.func,
|
onSubmit: PropTypes.func,
|
||||||
customModalGasPriceInHex: PropTypes.string,
|
customModalGasPriceInHex: PropTypes.string,
|
||||||
@ -47,16 +41,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
isRetry: PropTypes.bool,
|
isRetry: PropTypes.bool,
|
||||||
disableSave: PropTypes.bool,
|
disableSave: PropTypes.bool,
|
||||||
isEthereumNetwork: 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() {
|
componentDidMount() {
|
||||||
@ -92,8 +76,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
isRetry,
|
isRetry,
|
||||||
infoRowProps: { transactionFee },
|
infoRowProps: { transactionFee },
|
||||||
isEthereumNetwork,
|
isEthereumNetwork,
|
||||||
customGasLimitMessage,
|
|
||||||
minimumGasLimit,
|
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -102,7 +84,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
updateCustomGasLimit={updateCustomGasLimit}
|
updateCustomGasLimit={updateCustomGasLimit}
|
||||||
customModalGasPriceInHex={customModalGasPriceInHex}
|
customModalGasPriceInHex={customModalGasPriceInHex}
|
||||||
customModalGasLimitInHex={customModalGasLimitInHex}
|
customModalGasLimitInHex={customModalGasLimitInHex}
|
||||||
customGasLimitMessage={customGasLimitMessage}
|
|
||||||
timeRemaining={currentTimeEstimate}
|
timeRemaining={currentTimeEstimate}
|
||||||
transactionFee={transactionFee}
|
transactionFee={transactionFee}
|
||||||
gasChartProps={gasChartProps}
|
gasChartProps={gasChartProps}
|
||||||
@ -112,18 +93,11 @@ export default class GasModalPageContainer extends Component {
|
|||||||
isSpeedUp={isSpeedUp}
|
isSpeedUp={isSpeedUp}
|
||||||
isRetry={isRetry}
|
isRetry={isRetry}
|
||||||
isEthereumNetwork={isEthereumNetwork}
|
isEthereumNetwork={isEthereumNetwork}
|
||||||
minimumGasLimit={minimumGasLimit}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInfoRows(
|
renderInfoRows(newTotalFiat, newTotalEth, sendAmount, transactionFee) {
|
||||||
newTotalFiat,
|
|
||||||
newTotalEth,
|
|
||||||
sendAmount,
|
|
||||||
transactionFee,
|
|
||||||
extraInfoRow,
|
|
||||||
) {
|
|
||||||
return (
|
return (
|
||||||
<div className="gas-modal-content__info-row-wrapper">
|
<div className="gas-modal-content__info-row-wrapper">
|
||||||
<div className="gas-modal-content__info-row">
|
<div className="gas-modal-content__info-row">
|
||||||
@ -143,16 +117,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
{transactionFee}
|
{transactionFee}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</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">
|
<div className="gas-modal-content__info-row__total-info">
|
||||||
<span className="gas-modal-content__info-row__total-info__label">
|
<span className="gas-modal-content__info-row__total-info__label">
|
||||||
{this.context.t('newTotal')}
|
{this.context.t('newTotal')}
|
||||||
@ -175,13 +139,7 @@ export default class GasModalPageContainer extends Component {
|
|||||||
const {
|
const {
|
||||||
gasPriceButtonGroupProps,
|
gasPriceButtonGroupProps,
|
||||||
hideBasic,
|
hideBasic,
|
||||||
infoRowProps: {
|
infoRowProps: { newTotalFiat, newTotalEth, sendAmount, transactionFee },
|
||||||
newTotalFiat,
|
|
||||||
newTotalEth,
|
|
||||||
sendAmount,
|
|
||||||
transactionFee,
|
|
||||||
extraInfoRow,
|
|
||||||
},
|
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
let tabsToRender = [
|
let tabsToRender = [
|
||||||
@ -200,7 +158,7 @@ export default class GasModalPageContainer extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs onTabClick={(tabName) => this.setState({ selectedTab: tabName })}>
|
<Tabs>
|
||||||
{tabsToRender.map(({ name, content }, i) => (
|
{tabsToRender.map(({ name, content }, i) => (
|
||||||
<Tab name={name} key={`gas-modal-tab-${i}`}>
|
<Tab name={name} key={`gas-modal-tab-${i}`}>
|
||||||
<div className="gas-modal-content">
|
<div className="gas-modal-content">
|
||||||
@ -210,7 +168,6 @@ export default class GasModalPageContainer extends Component {
|
|||||||
newTotalEth,
|
newTotalEth,
|
||||||
sendAmount,
|
sendAmount,
|
||||||
transactionFee,
|
transactionFee,
|
||||||
extraInfoRow,
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</Tab>
|
||||||
@ -248,45 +205,7 @@ export default class GasModalPageContainer extends Component {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (this.props.isSwap) {
|
onSubmit(customModalGasLimitInHex, customModalGasPriceInHex)
|
||||||
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,
|
|
||||||
)
|
|
||||||
}}
|
}}
|
||||||
submitText={this.context.t('save')}
|
submitText={this.context.t('save')}
|
||||||
headerCloseText={this.context.t('close')}
|
headerCloseText={this.context.t('close')}
|
||||||
|
@ -11,7 +11,6 @@ import {
|
|||||||
updateSendAmount,
|
updateSendAmount,
|
||||||
setGasTotal,
|
setGasTotal,
|
||||||
updateTransaction,
|
updateTransaction,
|
||||||
setSwapsTxGasParams,
|
|
||||||
} from '../../../../store/actions'
|
} from '../../../../store/actions'
|
||||||
import {
|
import {
|
||||||
setCustomGasPrice,
|
setCustomGasPrice,
|
||||||
@ -67,21 +66,11 @@ import GasModalPageContainer from './gas-modal-page-container.component'
|
|||||||
const mapStateToProps = (state, ownProps) => {
|
const mapStateToProps = (state, ownProps) => {
|
||||||
const { currentNetworkTxList, send } = state.metamask
|
const { currentNetworkTxList, send } = state.metamask
|
||||||
const { modalState: { props: modalProps } = {} } = state.appState.modal || {}
|
const { modalState: { props: modalProps } = {} } = state.appState.modal || {}
|
||||||
const {
|
const { txData = {} } = modalProps || {}
|
||||||
txData = {},
|
|
||||||
isSwap = false,
|
|
||||||
customGasLimitMessage = '',
|
|
||||||
customTotalSupplement = '',
|
|
||||||
extraInfoRow = null,
|
|
||||||
useFastestButtons = false,
|
|
||||||
minimumGasLimit = Number(MIN_GAS_LIMIT_DEC),
|
|
||||||
} = modalProps || {}
|
|
||||||
const { transaction = {} } = ownProps
|
const { transaction = {} } = ownProps
|
||||||
const selectedTransaction = isSwap
|
const selectedTransaction = currentNetworkTxList.find(
|
||||||
? txData
|
({ id }) => id === (transaction.id || txData.id),
|
||||||
: currentNetworkTxList.find(
|
)
|
||||||
({ id }) => id === (transaction.id || txData.id),
|
|
||||||
)
|
|
||||||
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
|
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
|
||||||
const gasEstimatesLoading = getGasEstimatesLoadingStatus(state)
|
const gasEstimatesLoading = getGasEstimatesLoadingStatus(state)
|
||||||
const sendToken = getSendToken(state)
|
const sendToken = getSendToken(state)
|
||||||
@ -107,13 +96,12 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const gasButtonInfo = getRenderableBasicEstimateData(
|
const gasButtonInfo = getRenderableBasicEstimateData(
|
||||||
state,
|
state,
|
||||||
customModalGasLimitInHex,
|
customModalGasLimitInHex,
|
||||||
useFastestButtons,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const currentCurrency = getCurrentCurrency(state)
|
const currentCurrency = getCurrentCurrency(state)
|
||||||
const conversionRate = getConversionRate(state)
|
const conversionRate = getConversionRate(state)
|
||||||
const newTotalFiat = sumHexWEIsToRenderableFiat(
|
const newTotalFiat = sumHexWEIsToRenderableFiat(
|
||||||
[value, customGasTotal, customTotalSupplement],
|
[value, customGasTotal],
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
)
|
)
|
||||||
@ -137,11 +125,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const newTotalEth =
|
const newTotalEth =
|
||||||
maxModeOn && !isSendTokenSet
|
maxModeOn && !isSendTokenSet
|
||||||
? sumHexWEIsToRenderableEth([balance, '0x0'])
|
? sumHexWEIsToRenderableEth([balance, '0x0'])
|
||||||
: sumHexWEIsToRenderableEth([
|
: sumHexWEIsToRenderableEth([value, customGasTotal])
|
||||||
value,
|
|
||||||
customGasTotal,
|
|
||||||
customTotalSupplement,
|
|
||||||
])
|
|
||||||
|
|
||||||
const sendAmount =
|
const sendAmount =
|
||||||
maxModeOn && !isSendTokenSet
|
maxModeOn && !isSendTokenSet
|
||||||
@ -171,7 +155,6 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
return {
|
return {
|
||||||
hideBasic,
|
hideBasic,
|
||||||
isConfirm: isConfirm(state),
|
isConfirm: isConfirm(state),
|
||||||
isSwap,
|
|
||||||
customModalGasPriceInHex,
|
customModalGasPriceInHex,
|
||||||
customModalGasLimitInHex,
|
customModalGasLimitInHex,
|
||||||
customGasPrice,
|
customGasPrice,
|
||||||
@ -180,7 +163,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
newTotalFiat,
|
newTotalFiat,
|
||||||
currentTimeEstimate,
|
currentTimeEstimate,
|
||||||
blockTime: getBasicGasEstimateBlockTime(state),
|
blockTime: getBasicGasEstimateBlockTime(state),
|
||||||
customPriceIsSafe: isCustomPriceSafe(state, isSwap),
|
customPriceIsSafe: isCustomPriceSafe(state),
|
||||||
maxModeOn,
|
maxModeOn,
|
||||||
gasPriceButtonGroupProps: {
|
gasPriceButtonGroupProps: {
|
||||||
buttonDataLoading,
|
buttonDataLoading,
|
||||||
@ -199,20 +182,15 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
},
|
},
|
||||||
infoRowProps: {
|
infoRowProps: {
|
||||||
originalTotalFiat: sumHexWEIsToRenderableFiat(
|
originalTotalFiat: sumHexWEIsToRenderableFiat(
|
||||||
[value, customGasTotal, customTotalSupplement],
|
[value, customGasTotal],
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
),
|
),
|
||||||
originalTotalEth: sumHexWEIsToRenderableEth([
|
originalTotalEth: sumHexWEIsToRenderableEth([value, customGasTotal]),
|
||||||
value,
|
|
||||||
customGasTotal,
|
|
||||||
customTotalSupplement,
|
|
||||||
]),
|
|
||||||
newTotalFiat: showFiat ? newTotalFiat : '',
|
newTotalFiat: showFiat ? newTotalFiat : '',
|
||||||
newTotalEth,
|
newTotalEth,
|
||||||
transactionFee: sumHexWEIsToRenderableEth(['0x0', customGasTotal]),
|
transactionFee: sumHexWEIsToRenderableEth(['0x0', customGasTotal]),
|
||||||
sendAmount,
|
sendAmount,
|
||||||
extraInfoRow,
|
|
||||||
},
|
},
|
||||||
transaction: txData || transaction,
|
transaction: txData || transaction,
|
||||||
isSpeedUp: transaction.status === 'submitted',
|
isSpeedUp: transaction.status === 'submitted',
|
||||||
@ -225,11 +203,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
sendToken,
|
sendToken,
|
||||||
balance,
|
balance,
|
||||||
tokenBalance: getTokenBalance(state),
|
tokenBalance: getTokenBalance(state),
|
||||||
customGasLimitMessage,
|
|
||||||
conversionRate,
|
conversionRate,
|
||||||
value,
|
value,
|
||||||
customTotalSupplement,
|
|
||||||
minimumGasLimit,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,9 +246,6 @@ const mapDispatchToProps = (dispatch) => {
|
|||||||
dispatch(updateSendErrors({ amount: null }))
|
dispatch(updateSendErrors({ amount: null }))
|
||||||
dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject)))
|
dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject)))
|
||||||
},
|
},
|
||||||
updateSwapTxGas: (gasLimit, gasPrice) => {
|
|
||||||
dispatch(setSwapsTxGasParams(gasLimit, gasPrice))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +254,6 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
gasPriceButtonGroupProps,
|
gasPriceButtonGroupProps,
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow
|
||||||
isConfirm,
|
isConfirm,
|
||||||
isSwap,
|
|
||||||
txId,
|
txId,
|
||||||
isSpeedUp,
|
isSpeedUp,
|
||||||
isRetry,
|
isRetry,
|
||||||
@ -295,7 +266,6 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
tokenBalance,
|
tokenBalance,
|
||||||
customGasLimit,
|
customGasLimit,
|
||||||
transaction,
|
transaction,
|
||||||
minimumGasLimit,
|
|
||||||
} = stateProps
|
} = stateProps
|
||||||
const {
|
const {
|
||||||
hideGasButtonGroup: dispatchHideGasButtonGroup,
|
hideGasButtonGroup: dispatchHideGasButtonGroup,
|
||||||
@ -307,7 +277,6 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
cancelAndClose: dispatchCancelAndClose,
|
cancelAndClose: dispatchCancelAndClose,
|
||||||
hideModal: dispatchHideModal,
|
hideModal: dispatchHideModal,
|
||||||
setAmountToMax: dispatchSetAmountToMax,
|
setAmountToMax: dispatchSetAmountToMax,
|
||||||
updateSwapTxGas: dispatchUpdateSwapTxGas,
|
|
||||||
...otherDispatchProps
|
...otherDispatchProps
|
||||||
} = dispatchProps
|
} = dispatchProps
|
||||||
|
|
||||||
@ -316,10 +285,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
...otherDispatchProps,
|
...otherDispatchProps,
|
||||||
...ownProps,
|
...ownProps,
|
||||||
onSubmit: (gasLimit, gasPrice) => {
|
onSubmit: (gasLimit, gasPrice) => {
|
||||||
if (isSwap) {
|
if (isConfirm) {
|
||||||
dispatchUpdateSwapTxGas(gasLimit, gasPrice)
|
|
||||||
dispatchHideModal()
|
|
||||||
} else if (isConfirm) {
|
|
||||||
const updatedTx = {
|
const updatedTx = {
|
||||||
...transaction,
|
...transaction,
|
||||||
txParams: {
|
txParams: {
|
||||||
@ -365,7 +331,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
|||||||
disableSave:
|
disableSave:
|
||||||
insufficientBalance ||
|
insufficientBalance ||
|
||||||
(isSpeedUp && customGasPrice === 0) ||
|
(isSpeedUp && customGasPrice === 0) ||
|
||||||
customGasLimit < minimumGasLimit,
|
customGasLimit < Number(MIN_GAS_LIMIT_DEC),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,14 +194,12 @@ describe('GasModalPageContainer Component', function () {
|
|||||||
'mockNewTotalEth',
|
'mockNewTotalEth',
|
||||||
'mockSendAmount',
|
'mockSendAmount',
|
||||||
'mockTransactionFee',
|
'mockTransactionFee',
|
||||||
{ label: 'mockLabel', value: 'mockValue' },
|
|
||||||
])
|
])
|
||||||
assert.deepEqual(GP.renderInfoRows.getCall(1).args, [
|
assert.deepEqual(GP.renderInfoRows.getCall(1).args, [
|
||||||
'mockNewTotalFiat',
|
'mockNewTotalFiat',
|
||||||
'mockNewTotalEth',
|
'mockNewTotalEth',
|
||||||
'mockSendAmount',
|
'mockSendAmount',
|
||||||
'mockTransactionFee',
|
'mockTransactionFee',
|
||||||
{ label: 'mockLabel', value: 'mockValue' },
|
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -63,8 +63,6 @@ describe('gas-modal-page-container container', function () {
|
|||||||
txData: {
|
txData: {
|
||||||
id: 34,
|
id: 34,
|
||||||
},
|
},
|
||||||
extraInfoRow: { label: 'mockLabel', value: 'mockValue' },
|
|
||||||
minimumGasLimit: 21000,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -131,8 +129,6 @@ describe('gas-modal-page-container container', function () {
|
|||||||
newTotalFiat: '637.41',
|
newTotalFiat: '637.41',
|
||||||
blockTime: 12,
|
blockTime: 12,
|
||||||
conversionRate: 50,
|
conversionRate: 50,
|
||||||
customGasLimitMessage: '',
|
|
||||||
customTotalSupplement: '',
|
|
||||||
customModalGasLimitInHex: 'aaaaaaaa',
|
customModalGasLimitInHex: 'aaaaaaaa',
|
||||||
customModalGasPriceInHex: 'ffffffff',
|
customModalGasPriceInHex: 'ffffffff',
|
||||||
customGasTotal: 'aaaaaaa955555556',
|
customGasTotal: 'aaaaaaa955555556',
|
||||||
@ -152,7 +148,6 @@ describe('gas-modal-page-container container', function () {
|
|||||||
gasEstimatesLoading: false,
|
gasEstimatesLoading: false,
|
||||||
hideBasic: true,
|
hideBasic: true,
|
||||||
infoRowProps: {
|
infoRowProps: {
|
||||||
extraInfoRow: { label: 'mockLabel', value: 'mockValue' },
|
|
||||||
originalTotalFiat: '637.41',
|
originalTotalFiat: '637.41',
|
||||||
originalTotalEth: '12.748189 ETH',
|
originalTotalEth: '12.748189 ETH',
|
||||||
newTotalFiat: '637.41',
|
newTotalFiat: '637.41',
|
||||||
@ -163,7 +158,6 @@ describe('gas-modal-page-container container', function () {
|
|||||||
insufficientBalance: true,
|
insufficientBalance: true,
|
||||||
isSpeedUp: false,
|
isSpeedUp: false,
|
||||||
isRetry: false,
|
isRetry: false,
|
||||||
isSwap: false,
|
|
||||||
txId: 34,
|
txId: 34,
|
||||||
isEthereumNetwork: true,
|
isEthereumNetwork: true,
|
||||||
isMainnet: true,
|
isMainnet: true,
|
||||||
@ -174,7 +168,6 @@ describe('gas-modal-page-container container', function () {
|
|||||||
id: 34,
|
id: 34,
|
||||||
},
|
},
|
||||||
value: '0x640000000000000',
|
value: '0x640000000000000',
|
||||||
minimumGasLimit: 21000,
|
|
||||||
}
|
}
|
||||||
const baseMockOwnProps = { transaction: { id: 34 } }
|
const baseMockOwnProps = { transaction: { id: 34 } }
|
||||||
const tests = [
|
const tests = [
|
||||||
|
@ -93,7 +93,12 @@ export default class GasPriceButtonGroup extends Component {
|
|||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleGasPriceSelection(priceInHexWei)}
|
onClick={() =>
|
||||||
|
handleGasPriceSelection(
|
||||||
|
priceInHexWei,
|
||||||
|
renderableGasInfo.gasEstimateType,
|
||||||
|
)
|
||||||
|
}
|
||||||
key={`gas-price-button-${index}`}
|
key={`gas-price-button-${index}`}
|
||||||
>
|
>
|
||||||
{this.renderButtonContent(
|
{this.renderButtonContent(
|
||||||
|
@ -3,6 +3,7 @@ import React from 'react'
|
|||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
import shallow from '../../../../../../lib/shallow-with-context'
|
import shallow from '../../../../../../lib/shallow-with-context'
|
||||||
import GasPriceButtonGroup from '../gas-price-button-group.component'
|
import GasPriceButtonGroup from '../gas-price-button-group.component'
|
||||||
|
import { GAS_ESTIMATE_TYPES } from '../../../../../helpers/constants/common'
|
||||||
|
|
||||||
import ButtonGroup from '../../../../ui/button-group'
|
import ButtonGroup from '../../../../ui/button-group'
|
||||||
|
|
||||||
@ -17,18 +18,21 @@ describe('GasPriceButtonGroup Component', function () {
|
|||||||
className: 'gas-price-button-group',
|
className: 'gas-price-button-group',
|
||||||
gasButtonInfo: [
|
gasButtonInfo: [
|
||||||
{
|
{
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
||||||
feeInPrimaryCurrency: '$0.52',
|
feeInPrimaryCurrency: '$0.52',
|
||||||
feeInSecondaryCurrency: '0.0048 ETH',
|
feeInSecondaryCurrency: '0.0048 ETH',
|
||||||
timeEstimate: '~ 1 min 0 sec',
|
timeEstimate: '~ 1 min 0 sec',
|
||||||
priceInHexWei: '0xa1b2c3f',
|
priceInHexWei: '0xa1b2c3f',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.AVERAGE,
|
||||||
feeInPrimaryCurrency: '$0.39',
|
feeInPrimaryCurrency: '$0.39',
|
||||||
feeInSecondaryCurrency: '0.004 ETH',
|
feeInSecondaryCurrency: '0.004 ETH',
|
||||||
timeEstimate: '~ 1 min 30 sec',
|
timeEstimate: '~ 1 min 30 sec',
|
||||||
priceInHexWei: '0xa1b2c39',
|
priceInHexWei: '0xa1b2c39',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
gasEstimateType: GAS_ESTIMATE_TYPES.FAST,
|
||||||
feeInPrimaryCurrency: '$0.30',
|
feeInPrimaryCurrency: '$0.30',
|
||||||
feeInSecondaryCurrency: '0.00354 ETH',
|
feeInSecondaryCurrency: '0.00354 ETH',
|
||||||
timeEstimate: '~ 2 min 1 sec',
|
timeEstimate: '~ 2 min 1 sec',
|
||||||
@ -105,10 +109,12 @@ describe('GasPriceButtonGroup Component', function () {
|
|||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
GasPriceButtonGroup.prototype.renderButtonContent.resetHistory()
|
GasPriceButtonGroup.prototype.renderButtonContent.resetHistory()
|
||||||
const renderButtonResult = GasPriceButtonGroup.prototype.renderButton(
|
const renderButtonResult = wrapper
|
||||||
{ ...mockGasPriceButtonGroupProps.gasButtonInfo[0] },
|
.instance()
|
||||||
mockButtonPropsAndFlags,
|
.renderButton(
|
||||||
)
|
{ ...mockGasPriceButtonGroupProps.gasButtonInfo[0] },
|
||||||
|
mockButtonPropsAndFlags,
|
||||||
|
)
|
||||||
wrappedRenderButtonResult = shallow(renderButtonResult)
|
wrappedRenderButtonResult = shallow(renderButtonResult)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -128,7 +134,10 @@ describe('GasPriceButtonGroup Component', function () {
|
|||||||
)
|
)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
mockGasPriceButtonGroupProps.handleGasPriceSelection.getCall(0).args,
|
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,
|
feeInPrimaryCurrency,
|
||||||
feeInSecondaryCurrency,
|
feeInSecondaryCurrency,
|
||||||
timeEstimate,
|
timeEstimate,
|
||||||
|
gasEstimateType,
|
||||||
} = mockGasPriceButtonGroupProps.gasButtonInfo[0]
|
} = mockGasPriceButtonGroupProps.gasButtonInfo[0]
|
||||||
const { showCheck, className } = mockGasPriceButtonGroupProps
|
const { showCheck, className } = mockGasPriceButtonGroupProps
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
GasPriceButtonGroup.prototype.renderButtonContent.getCall(0).args,
|
GasPriceButtonGroup.prototype.renderButtonContent.getCall(0).args,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
gasEstimateType,
|
||||||
feeInPrimaryCurrency,
|
feeInPrimaryCurrency,
|
||||||
feeInSecondaryCurrency,
|
feeInSecondaryCurrency,
|
||||||
timeEstimate,
|
timeEstimate,
|
||||||
|
@ -10,6 +10,7 @@ import { ENVIRONMENT_TYPE_POPUP } from '../../../../../app/scripts/lib/enums'
|
|||||||
|
|
||||||
// Modal Components
|
// Modal Components
|
||||||
import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container'
|
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 DepositEtherModal from './deposit-ether-modal'
|
||||||
import AccountDetailsModal from './account-details-modal'
|
import AccountDetailsModal from './account-details-modal'
|
||||||
import ExportPrivateKeyModal from './export-private-key-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: {
|
EDIT_APPROVAL_PERMISSION: {
|
||||||
contents: <EditApprovalPermission />,
|
contents: <EditApprovalPermission />,
|
||||||
mobileModalStyle: {
|
mobileModalStyle: {
|
||||||
|
@ -2,6 +2,10 @@ import { createSlice } from '@reduxjs/toolkit'
|
|||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import log from 'loglevel'
|
import log from 'loglevel'
|
||||||
|
|
||||||
|
import {
|
||||||
|
loadLocalStorageData,
|
||||||
|
saveLocalStorageData,
|
||||||
|
} from '../../../lib/local-storage-helpers'
|
||||||
import {
|
import {
|
||||||
addToken,
|
addToken,
|
||||||
addUnapprovedTransaction,
|
addUnapprovedTransaction,
|
||||||
@ -27,7 +31,10 @@ import {
|
|||||||
SWAPS_ERROR_ROUTE,
|
SWAPS_ERROR_ROUTE,
|
||||||
SWAPS_MAINTENANCE_ROUTE,
|
SWAPS_MAINTENANCE_ROUTE,
|
||||||
} from '../../helpers/constants/routes'
|
} 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 { calcGasTotal } from '../../pages/send/send.utils'
|
||||||
import {
|
import {
|
||||||
decimalToHex,
|
decimalToHex,
|
||||||
@ -37,9 +44,9 @@ import {
|
|||||||
hexToDecimal,
|
hexToDecimal,
|
||||||
hexWEIToDecGWEI,
|
hexWEIToDecGWEI,
|
||||||
} from '../../helpers/utils/conversions.util'
|
} from '../../helpers/utils/conversions.util'
|
||||||
|
import { conversionLessThan } from '../../helpers/utils/conversion-util'
|
||||||
import { calcTokenAmount } from '../../helpers/utils/token-util'
|
import { calcTokenAmount } from '../../helpers/utils/token-util'
|
||||||
import {
|
import {
|
||||||
getFastPriceEstimateInHexWEI,
|
|
||||||
getSelectedAccount,
|
getSelectedAccount,
|
||||||
getTokenExchangeRates,
|
getTokenExchangeRates,
|
||||||
conversionRateSelector as getConversionRate,
|
conversionRateSelector as getConversionRate,
|
||||||
@ -51,14 +58,16 @@ import {
|
|||||||
SWAP_FAILED_ERROR,
|
SWAP_FAILED_ERROR,
|
||||||
SWAPS_FETCH_ORDER_CONFLICT,
|
SWAPS_FETCH_ORDER_CONFLICT,
|
||||||
} from '../../helpers/constants/swaps'
|
} from '../../helpers/constants/swaps'
|
||||||
import {
|
|
||||||
fetchBasicGasAndTimeEstimates,
|
|
||||||
fetchGasEstimates,
|
|
||||||
resetCustomGasState,
|
|
||||||
} from '../gas/gas.duck'
|
|
||||||
import { formatCurrency } from '../../helpers/utils/confirm-tx.util'
|
import { formatCurrency } from '../../helpers/utils/confirm-tx.util'
|
||||||
import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'
|
import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'
|
||||||
|
|
||||||
|
const GAS_PRICES_LOADING_STATES = {
|
||||||
|
INITIAL: 'INITIAL',
|
||||||
|
LOADING: 'LOADING',
|
||||||
|
FAILED: 'FAILED',
|
||||||
|
COMPLETED: 'COMPLETED',
|
||||||
|
}
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
aggregatorMetadata: null,
|
aggregatorMetadata: null,
|
||||||
approveTxId: null,
|
approveTxId: null,
|
||||||
@ -68,6 +77,14 @@ const initialState = {
|
|||||||
quotesFetchStartTime: null,
|
quotesFetchStartTime: null,
|
||||||
topAssets: {},
|
topAssets: {},
|
||||||
toToken: null,
|
toToken: null,
|
||||||
|
customGas: {
|
||||||
|
price: null,
|
||||||
|
limit: null,
|
||||||
|
loading: GAS_PRICES_LOADING_STATES.INITIAL,
|
||||||
|
priceEstimates: {},
|
||||||
|
priceEstimatesLastRetrieved: 0,
|
||||||
|
fallBackPrice: null,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const slice = createSlice({
|
const slice = createSlice({
|
||||||
@ -106,6 +123,27 @@ const slice = createSlice({
|
|||||||
setToToken: (state, action) => {
|
setToToken: (state, action) => {
|
||||||
state.toToken = action.payload
|
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) =>
|
export const getQuotesFetchStartTime = (state) =>
|
||||||
state.swaps.quotesFetchStartTime
|
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
|
// Background selectors
|
||||||
|
|
||||||
const getSwapsState = (state) => state.metamask.swapsState
|
const getSwapsState = (state) => state.metamask.swapsState
|
||||||
@ -185,17 +266,8 @@ export const getUsedQuote = (state) =>
|
|||||||
export const getDestinationTokenInfo = (state) =>
|
export const getDestinationTokenInfo = (state) =>
|
||||||
getFetchParams(state)?.metaData?.destinationTokenInfo
|
getFetchParams(state)?.metaData?.destinationTokenInfo
|
||||||
|
|
||||||
export const getSwapsTradeTxParams = (state) => {
|
export const getUsedSwapsGasPrice = (state) =>
|
||||||
const { selectedAggId, topAggId, quotes } = getSwapsState(state)
|
getCustomSwapsGasPrice(state) || getSwapsFallbackGasPrice(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 getApproveTxParams = (state) => {
|
export const getApproveTxParams = (state) => {
|
||||||
const { approvalNeeded } = getSelectedQuote(state) || getTopQuote(state) || {}
|
const { approvalNeeded } = getSelectedQuote(state) || getTopQuote(state) || {}
|
||||||
@ -215,6 +287,9 @@ const {
|
|||||||
clearSwapsState,
|
clearSwapsState,
|
||||||
navigatedBackToBuildQuote,
|
navigatedBackToBuildQuote,
|
||||||
retriedGetQuotes,
|
retriedGetQuotes,
|
||||||
|
swapGasPriceEstimatesFetchCompleted,
|
||||||
|
swapGasPriceEstimatesFetchStarted,
|
||||||
|
swapGasPriceEstimatesFetchFailed,
|
||||||
setAggregatorMetadata,
|
setAggregatorMetadata,
|
||||||
setBalanceError,
|
setBalanceError,
|
||||||
setFetchingQuotes,
|
setFetchingQuotes,
|
||||||
@ -222,6 +297,9 @@ const {
|
|||||||
setQuotesFetchStartTime,
|
setQuotesFetchStartTime,
|
||||||
setTopAssets,
|
setTopAssets,
|
||||||
setToToken,
|
setToToken,
|
||||||
|
swapCustomGasModalPriceEdited,
|
||||||
|
swapCustomGasModalLimitEdited,
|
||||||
|
retrievedFallbackSwapsGasPrice,
|
||||||
} = actions
|
} = actions
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -233,6 +311,8 @@ export {
|
|||||||
setQuotesFetchStartTime as setSwapQuotesFetchStartTime,
|
setQuotesFetchStartTime as setSwapQuotesFetchStartTime,
|
||||||
setTopAssets,
|
setTopAssets,
|
||||||
setToToken as setSwapToToken,
|
setToToken as setSwapToToken,
|
||||||
|
swapCustomGasModalPriceEdited,
|
||||||
|
swapCustomGasModalLimitEdited,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const navigateBackToBuildQuote = (history) => {
|
export const navigateBackToBuildQuote = (history) => {
|
||||||
@ -255,7 +335,6 @@ export const prepareForRetryGetQuotes = () => {
|
|||||||
|
|
||||||
export const prepareToLeaveSwaps = () => {
|
export const prepareToLeaveSwaps = () => {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
dispatch(resetCustomGasState())
|
|
||||||
dispatch(clearSwapsState())
|
dispatch(clearSwapsState())
|
||||||
await dispatch(resetBackgroundSwapsState())
|
await dispatch(resetBackgroundSwapsState())
|
||||||
}
|
}
|
||||||
@ -263,9 +342,11 @@ export const prepareToLeaveSwaps = () => {
|
|||||||
|
|
||||||
export const fetchAndSetSwapsGasPriceInfo = () => {
|
export const fetchAndSetSwapsGasPriceInfo = () => {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
const basicEstimates = await dispatch(fetchBasicGasAndTimeEstimates())
|
const basicEstimates = await dispatch(fetchMetaSwapsGasPriceEstimates())
|
||||||
dispatch(setSwapsTxGasPrice(decGWEIToHexWEI(basicEstimates.fastest)))
|
|
||||||
await dispatch(fetchGasEstimates(basicEstimates.blockTime))
|
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
|
// TODO: Check for any errors we should expect to occur in production, and report others to Sentry
|
||||||
log.error(`Error fetching quotes: `, e)
|
log.error(`Error fetching quotes: `, e)
|
||||||
|
|
||||||
dispatch(setSwapsErrorKey(ERROR_FETCHING_QUOTES))
|
dispatch(setSwapsErrorKey(ERROR_FETCHING_QUOTES))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,6 +589,8 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
await dispatch(stopPollingForQuotes())
|
await dispatch(stopPollingForQuotes())
|
||||||
history.push(AWAITING_SWAP_ROUTE)
|
history.push(AWAITING_SWAP_ROUTE)
|
||||||
|
|
||||||
|
const { fast: fastGasEstimate } = getSwapGasPriceEstimateData(state)
|
||||||
|
|
||||||
const usedQuote = getUsedQuote(state)
|
const usedQuote = getUsedQuote(state)
|
||||||
const usedTradeTxParams = usedQuote.trade
|
const usedTradeTxParams = usedQuote.trade
|
||||||
|
|
||||||
@ -524,13 +608,9 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
`0x${decimalToHex(usedQuote?.maxGas || 0)}`,
|
`0x${decimalToHex(usedQuote?.maxGas || 0)}`,
|
||||||
estimatedGasLimitWithMultiplier,
|
estimatedGasLimitWithMultiplier,
|
||||||
)
|
)
|
||||||
usedTradeTxParams.gas = maxGasLimit
|
|
||||||
|
|
||||||
const customConvertGasPrice = getCustomSwapsGasPrice(state)
|
const usedGasPrice = getUsedSwapsGasPrice(state)
|
||||||
const tradeTxParams = getSwapsTradeTxParams(state)
|
usedTradeTxParams.gas = maxGasLimit
|
||||||
const fastGasEstimate = getFastPriceEstimateInHexWEI(state)
|
|
||||||
const usedGasPrice =
|
|
||||||
customConvertGasPrice || tradeTxParams?.gasPrice || fastGasEstimate
|
|
||||||
usedTradeTxParams.gasPrice = usedGasPrice
|
usedTradeTxParams.gasPrice = usedGasPrice
|
||||||
|
|
||||||
const conversionRate = getConversionRate(state)
|
const conversionRate = getConversionRate(state)
|
||||||
@ -568,8 +648,8 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
: usedQuote.aggregator,
|
: usedQuote.aggregator,
|
||||||
gas_fees: formatCurrency(gasEstimateTotalInEth, 'usd')?.slice(1),
|
gas_fees: formatCurrency(gasEstimateTotalInEth, 'usd')?.slice(1),
|
||||||
estimated_gas: estimatedGasLimit.toString(10),
|
estimated_gas: estimatedGasLimit.toString(10),
|
||||||
suggested_gas_price: hexWEIToDecGWEI(usedGasPrice),
|
suggested_gas_price: fastGasEstimate,
|
||||||
used_gas_price: hexWEIToDecGWEI(fastGasEstimate),
|
used_gas_price: hexWEIToDecGWEI(usedGasPrice),
|
||||||
average_savings: usedQuote.savings?.performance,
|
average_savings: usedQuote.savings?.performance,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,3 +725,68 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
await forceUpdateMetamaskState(dispatch)
|
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,
|
getUsedQuote,
|
||||||
getFetchParams,
|
getFetchParams,
|
||||||
getApproveTxParams,
|
getApproveTxParams,
|
||||||
getSwapsTradeTxParams,
|
getUsedSwapsGasPrice,
|
||||||
fetchQuotesAndSetQuoteState,
|
fetchQuotesAndSetQuoteState,
|
||||||
navigateBackToBuildQuote,
|
navigateBackToBuildQuote,
|
||||||
prepareForRetryGetQuotes,
|
prepareForRetryGetQuotes,
|
||||||
@ -67,7 +67,7 @@ export default function AwaitingSwap({
|
|||||||
const { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {}
|
const { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {}
|
||||||
const usedQuote = useSelector(getUsedQuote)
|
const usedQuote = useSelector(getUsedQuote)
|
||||||
const approveTxParams = useSelector(getApproveTxParams)
|
const approveTxParams = useSelector(getApproveTxParams)
|
||||||
const tradeTxParams = useSelector(getSwapsTradeTxParams)
|
const swapsGasPrice = useSelector(getUsedSwapsGasPrice)
|
||||||
const currentCurrency = useSelector(getCurrentCurrency)
|
const currentCurrency = useSelector(getCurrentCurrency)
|
||||||
const conversionRate = useSelector(conversionRateSelector)
|
const conversionRate = useSelector(conversionRateSelector)
|
||||||
|
|
||||||
@ -77,14 +77,15 @@ export default function AwaitingSwap({
|
|||||||
)
|
)
|
||||||
|
|
||||||
let feeinFiat
|
let feeinFiat
|
||||||
if (usedQuote && tradeTxParams) {
|
|
||||||
|
if (usedQuote && swapsGasPrice) {
|
||||||
const renderableNetworkFees = getRenderableNetworkFeesForQuote(
|
const renderableNetworkFees = getRenderableNetworkFeesForQuote(
|
||||||
usedQuote.gasEstimateWithRefund || usedQuote.averageGas,
|
usedQuote.gasEstimateWithRefund || usedQuote.averageGas,
|
||||||
approveTxParams?.gas || '0x0',
|
approveTxParams?.gas || '0x0',
|
||||||
tradeTxParams.gasPrice,
|
swapsGasPrice,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
tradeTxParams.value,
|
usedQuote?.trade?.value,
|
||||||
sourceTokenInfo?.symbol,
|
sourceTokenInfo?.symbol,
|
||||||
usedQuote.sourceAmount,
|
usedQuote.sourceAmount,
|
||||||
)
|
)
|
||||||
|
@ -21,9 +21,8 @@ import {
|
|||||||
getApproveTxId,
|
getApproveTxId,
|
||||||
getFetchingQuotes,
|
getFetchingQuotes,
|
||||||
setBalanceError,
|
setBalanceError,
|
||||||
getCustomSwapsGasPrice,
|
|
||||||
setTopAssets,
|
setTopAssets,
|
||||||
getSwapsTradeTxParams,
|
getUsedSwapsGasPrice,
|
||||||
getFetchParams,
|
getFetchParams,
|
||||||
setAggregatorMetadata,
|
setAggregatorMetadata,
|
||||||
getAggregatorMetadata,
|
getAggregatorMetadata,
|
||||||
@ -33,7 +32,6 @@ import {
|
|||||||
prepareToLeaveSwaps,
|
prepareToLeaveSwaps,
|
||||||
fetchAndSetSwapsGasPriceInfo,
|
fetchAndSetSwapsGasPriceInfo,
|
||||||
} from '../../ducks/swaps/swaps'
|
} from '../../ducks/swaps/swaps'
|
||||||
import { resetCustomGasState } from '../../ducks/gas/gas.duck'
|
|
||||||
import {
|
import {
|
||||||
AWAITING_SWAP_ROUTE,
|
AWAITING_SWAP_ROUTE,
|
||||||
BUILD_QUOTE_ROUTE,
|
BUILD_QUOTE_ROUTE,
|
||||||
@ -59,7 +57,6 @@ import {
|
|||||||
setSwapsErrorKey,
|
setSwapsErrorKey,
|
||||||
} from '../../store/actions'
|
} from '../../store/actions'
|
||||||
import {
|
import {
|
||||||
getFastPriceEstimateInHexWEI,
|
|
||||||
currentNetworkTxListSelector,
|
currentNetworkTxListSelector,
|
||||||
getRpcPrefsForCurrentProvider,
|
getRpcPrefsForCurrentProvider,
|
||||||
} from '../../selectors'
|
} from '../../selectors'
|
||||||
@ -96,11 +93,9 @@ export default function Swap() {
|
|||||||
const [maxSlippage, setMaxSlippage] = useState(fetchParams?.slippage || 2)
|
const [maxSlippage, setMaxSlippage] = useState(fetchParams?.slippage || 2)
|
||||||
|
|
||||||
const routeState = useSelector(getBackgroundSwapRouteState)
|
const routeState = useSelector(getBackgroundSwapRouteState)
|
||||||
const tradeTxParams = useSelector(getSwapsTradeTxParams)
|
const usedGasPrice = useSelector(getUsedSwapsGasPrice)
|
||||||
const selectedAccount = useSelector(getSelectedAccount)
|
const selectedAccount = useSelector(getSelectedAccount)
|
||||||
const quotes = useSelector(getQuotes)
|
const quotes = useSelector(getQuotes)
|
||||||
const fastGasEstimate = useSelector(getFastPriceEstimateInHexWEI)
|
|
||||||
const customConvertGasPrice = useSelector(getCustomSwapsGasPrice)
|
|
||||||
const txList = useSelector(currentNetworkTxListSelector)
|
const txList = useSelector(currentNetworkTxListSelector)
|
||||||
const tradeTxId = useSelector(getTradeTxId)
|
const tradeTxId = useSelector(getTradeTxId)
|
||||||
const approveTxId = useSelector(getApproveTxId)
|
const approveTxId = useSelector(getApproveTxId)
|
||||||
@ -131,8 +126,6 @@ export default function Swap() {
|
|||||||
useSelector(getFromToken) || fetchParamsFromToken || {}
|
useSelector(getFromToken) || fetchParamsFromToken || {}
|
||||||
const { destinationTokenAddedForSwap } = fetchParams || {}
|
const { destinationTokenAddedForSwap } = fetchParams || {}
|
||||||
|
|
||||||
const usedGasPrice =
|
|
||||||
customConvertGasPrice || tradeTxParams?.gasPrice || fastGasEstimate
|
|
||||||
const approveTxData =
|
const approveTxData =
|
||||||
approveTxId && txList.find(({ id }) => approveTxId === id)
|
approveTxId && txList.find(({ id }) => approveTxId === id)
|
||||||
const tradeTxData = tradeTxId && txList.find(({ id }) => tradeTxId === id)
|
const tradeTxData = tradeTxId && txList.find(({ id }) => tradeTxId === id)
|
||||||
@ -197,7 +190,6 @@ export default function Swap() {
|
|||||||
dispatch(setAggregatorMetadata(newAggregatorMetadata))
|
dispatch(setAggregatorMetadata(newAggregatorMetadata))
|
||||||
})
|
})
|
||||||
|
|
||||||
dispatch(resetCustomGasState())
|
|
||||||
dispatch(fetchAndSetSwapsGasPriceInfo())
|
dispatch(fetchAndSetSwapsGasPriceInfo())
|
||||||
|
|
||||||
return () => {
|
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`
|
return `https://api.metaswap.codefi.network/featureFlag`
|
||||||
case 'aggregatorMetadata':
|
case 'aggregatorMetadata':
|
||||||
return `https://api.metaswap.codefi.network/aggregatorMetadata`
|
return `https://api.metaswap.codefi.network/aggregatorMetadata`
|
||||||
|
case 'gasPrices':
|
||||||
|
return `https://api.metaswap.codefi.network/gasPrices`
|
||||||
default:
|
default:
|
||||||
throw new Error('getBaseApi requires an api call type')
|
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) {
|
function validateData(validators, object, urlUsed) {
|
||||||
return validators.every(({ property, type, validator }) => {
|
return validators.every(({ property, type, validator }) => {
|
||||||
const types = type.split('|')
|
const types = type.split('|')
|
||||||
@ -320,6 +343,36 @@ export async function fetchTokenBalance(address, userAddress) {
|
|||||||
return usersToken
|
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(
|
export function getRenderableNetworkFeesForQuote(
|
||||||
tradeGas,
|
tradeGas,
|
||||||
approveGas,
|
approveGas,
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
getBalanceError,
|
getBalanceError,
|
||||||
getCustomSwapsGas,
|
getCustomSwapsGas,
|
||||||
getDestinationTokenInfo,
|
getDestinationTokenInfo,
|
||||||
getSwapsTradeTxParams,
|
getUsedSwapsGasPrice,
|
||||||
getTopQuote,
|
getTopQuote,
|
||||||
navigateBackToBuildQuote,
|
navigateBackToBuildQuote,
|
||||||
signAndSendTransactions,
|
signAndSendTransactions,
|
||||||
@ -101,8 +101,7 @@ export default function ViewQuote() {
|
|||||||
const quotesLastFetched = useSelector(getQuotesLastFetched)
|
const quotesLastFetched = useSelector(getQuotesLastFetched)
|
||||||
|
|
||||||
// Select necessary data
|
// Select necessary data
|
||||||
const tradeTxParams = useSelector(getSwapsTradeTxParams)
|
const gasPrice = useSelector(getUsedSwapsGasPrice)
|
||||||
const { gasPrice, value: tradeValue } = tradeTxParams || {}
|
|
||||||
const customMaxGas = useSelector(getCustomSwapsGas)
|
const customMaxGas = useSelector(getCustomSwapsGas)
|
||||||
const tokenConversionRates = useSelector(getTokenExchangeRates)
|
const tokenConversionRates = useSelector(getTokenExchangeRates)
|
||||||
const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates)
|
const memoizedTokenConversionRates = useEqualityCheck(tokenConversionRates)
|
||||||
@ -116,6 +115,7 @@ export default function ViewQuote() {
|
|||||||
const selectedQuote = useSelector(getSelectedQuote)
|
const selectedQuote = useSelector(getSelectedQuote)
|
||||||
const topQuote = useSelector(getTopQuote)
|
const topQuote = useSelector(getTopQuote)
|
||||||
const usedQuote = selectedQuote || topQuote
|
const usedQuote = selectedQuote || topQuote
|
||||||
|
const { value: tradeValue = '0x0' } = usedQuote?.trade?.value || {}
|
||||||
|
|
||||||
const fetchParamsSourceToken = fetchParams?.sourceToken
|
const fetchParamsSourceToken = fetchParams?.sourceToken
|
||||||
|
|
||||||
@ -454,9 +454,8 @@ export default function ViewQuote() {
|
|||||||
const onFeeCardMaxRowClick = () =>
|
const onFeeCardMaxRowClick = () =>
|
||||||
dispatch(
|
dispatch(
|
||||||
showModal({
|
showModal({
|
||||||
name: 'CUSTOMIZE_GAS',
|
name: 'CUSTOMIZE_METASWAP_GAS',
|
||||||
txData: { txParams: { ...tradeTxParams, gas: maxGasLimit } },
|
value: usedQuote.value,
|
||||||
isSwap: true,
|
|
||||||
customGasLimitMessage: approveGas
|
customGasLimitMessage: approveGas
|
||||||
? t('extraApprovalGas', [hexToDecimal(approveGas)])
|
? t('extraApprovalGas', [hexToDecimal(approveGas)])
|
||||||
: '',
|
: '',
|
||||||
@ -467,8 +466,8 @@ export default function ViewQuote() {
|
|||||||
value: t('amountInEth', [extraNetworkFeeTotalInEth]),
|
value: t('amountInEth', [extraNetworkFeeTotalInEth]),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
useFastestButtons: true,
|
initialGasPrice: gasPrice,
|
||||||
minimumGasLimit: Number(hexToDecimal(nonCustomMaxGasLimit)),
|
initialGasLimit: maxGasLimit,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -605,7 +604,7 @@ export default function ViewQuote() {
|
|||||||
}}
|
}}
|
||||||
submitText={t('swap')}
|
submitText={t('swap')}
|
||||||
onCancel={async () => await dispatch(navigateBackToBuildQuote(history))}
|
onCancel={async () => await dispatch(navigateBackToBuildQuote(history))}
|
||||||
disabled={balanceError}
|
disabled={balanceError || gasPrice === null || gasPrice === undefined}
|
||||||
showTermsOfService
|
showTermsOfService
|
||||||
showTopBorder
|
showTopBorder
|
||||||
/>
|
/>
|
||||||
|
@ -80,20 +80,8 @@ export function getSafeLowEstimate(state) {
|
|||||||
return safeLow
|
return safeLow
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAverageEstimate(state) {
|
export function isCustomPriceSafe(state) {
|
||||||
const {
|
|
||||||
gas: {
|
|
||||||
basicEstimates: { average },
|
|
||||||
},
|
|
||||||
} = state
|
|
||||||
|
|
||||||
return average
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isCustomPriceSafe(state, averageIsSafe) {
|
|
||||||
const safeLow = getSafeLowEstimate(state)
|
const safeLow = getSafeLowEstimate(state)
|
||||||
const average = getAverageEstimate(state)
|
|
||||||
const safeMinimumPrice = averageIsSafe ? average : safeLow
|
|
||||||
|
|
||||||
const customGasPrice = getCustomGasPrice(state)
|
const customGasPrice = getCustomGasPrice(state)
|
||||||
|
|
||||||
@ -101,7 +89,7 @@ export function isCustomPriceSafe(state, averageIsSafe) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (safeMinimumPrice === null) {
|
if (safeLow === null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +100,7 @@ export function isCustomPriceSafe(state, averageIsSafe) {
|
|||||||
fromDenomination: 'WEI',
|
fromDenomination: 'WEI',
|
||||||
toDenomination: 'GWEI',
|
toDenomination: 'GWEI',
|
||||||
},
|
},
|
||||||
{ value: safeMinimumPrice, fromNumericBase: 'dec' },
|
{ value: safeLow, fromNumericBase: 'dec' },
|
||||||
)
|
)
|
||||||
|
|
||||||
return customPriceSafe
|
return customPriceSafe
|
||||||
@ -219,34 +207,23 @@ export function getGasPriceInHexWei(price) {
|
|||||||
return addHexPrefix(priceEstimateToWei(value))
|
return addHexPrefix(priceEstimateToWei(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRenderableBasicEstimateData(
|
export function getRenderableGasButtonData(
|
||||||
state,
|
estimates,
|
||||||
gasLimit,
|
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 {
|
const {
|
||||||
gas: {
|
safeLow,
|
||||||
basicEstimates: {
|
average,
|
||||||
safeLow,
|
fast,
|
||||||
average,
|
safeLowWait,
|
||||||
fast,
|
avgWait,
|
||||||
safeLowWait,
|
fastWait,
|
||||||
avgWait,
|
fastest,
|
||||||
fastWait,
|
fastestWait,
|
||||||
fastest,
|
} = estimates
|
||||||
fastestWait,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} = state
|
|
||||||
|
|
||||||
const slowEstimateData = {
|
const slowEstimateData = {
|
||||||
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
gasEstimateType: GAS_ESTIMATE_TYPES.SLOW,
|
||||||
@ -305,9 +282,38 @@ export function getRenderableBasicEstimateData(
|
|||||||
priceInHexWei: getGasPriceInHexWei(fastest),
|
priceInHexWei: getGasPriceInHexWei(fastest),
|
||||||
}
|
}
|
||||||
|
|
||||||
return useFastestButtons
|
return {
|
||||||
? [fastEstimateData, fastestEstimateData]
|
slowEstimateData,
|
||||||
: [slowEstimateData, averageEstimateData, fastEstimateData]
|
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) {
|
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 () {
|
it('should return renderable data about basic estimates', function () {
|
||||||
tests.forEach((test) => {
|
tests.forEach((test) => {
|
||||||
|
@ -2288,7 +2288,7 @@ export function setSwapsTxGasLimit(gasLimit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setSwapsTxGasParams(gasLimit, gasPrice) {
|
export function customSwapsGasParamsUpdated(gasLimit, gasPrice) {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
await promisifiedBackground.setSwapsTxGasPrice(gasPrice)
|
await promisifiedBackground.setSwapsTxGasPrice(gasPrice)
|
||||||
await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true)
|
await promisifiedBackground.setSwapsTxGasLimit(gasLimit, true)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user