aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/send/send-content
diff options
context:
space:
mode:
authorDan J Miller <danjm.com@gmail.com>2019-02-06 08:24:28 +0800
committerDan Finlay <542863+danfinlay@users.noreply.github.com>2019-02-06 08:24:28 +0800
commit38b91f63a21d1563cf88307e280f52836df005db (patch)
tree4632fe335ab9ff05df98f6739891a00a5229d90c /ui/app/components/send/send-content
parentc28fa312503b7c868bfcfceb42b3a79c0f25d492 (diff)
downloadtangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar
tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.gz
tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.bz2
tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.lz
tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.xz
tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.tar.zst
tangerine-wallet-browser-38b91f63a21d1563cf88307e280f52836df005db.zip
Add togglable advanced gas controls on send and confirm screens (#6112)
* Extract advanced gas input controls to their own component * Add advanced inline gas toggle to settings * Add optional advanced inline gas to send send screen * Adds optional advanced gas inputs to the confirm screen * Add info modals for advanced gas inputs. * Fix translation of advance gas toggle description. * Lint and unit test fixes for inline-advanced-gas-inputs * Increase margin above advanced options button on send screen * Move methods from constructor to property syntax in advanced-gas-inputs.component
Diffstat (limited to 'ui/app/components/send/send-content')
-rw-r--r--ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js85
-rw-r--r--ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js51
-rw-r--r--ui/app/components/send/send-content/send-gas-row/tests/send-gas-row-container.test.js47
3 files changed, 153 insertions, 30 deletions
diff --git a/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
index 8d305dd4f..50337e0bf 100644
--- a/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
+++ b/ui/app/components/send/send-content/send-gas-row/send-gas-row.component.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import SendRowWrapper from '../send-row-wrapper/'
import GasFeeDisplay from './gas-fee-display/gas-fee-display.component'
import GasPriceButtonGroup from '../../../gas-customization/gas-price-button-group'
+import AdvancedGasInputs from '../../../gas-customization/advanced-gas-inputs'
export default class SendGasRow extends Component {
@@ -13,54 +14,94 @@ export default class SendGasRow extends Component {
gasLoadingError: PropTypes.bool,
gasTotal: PropTypes.string,
showCustomizeGasModal: PropTypes.func,
+ setGasPrice: PropTypes.func,
+ setGasLimit: PropTypes.func,
gasPriceButtonGroupProps: PropTypes.object,
gasButtonGroupShown: PropTypes.bool,
+ advancedInlineGasShown: PropTypes.bool,
resetGasButtons: PropTypes.func,
+ gasPrice: PropTypes.number,
+ gasLimit: PropTypes.number,
+ insufficientBalance: PropTypes.bool,
}
static contextTypes = {
t: PropTypes.func,
}
- render () {
+ renderAdvancedOptionsButton () {
+ const { showCustomizeGasModal } = this.props
+ return <div className="advanced-gas-options-btn" onClick={() => showCustomizeGasModal()}>
+ { this.context.t('advancedOptions') }
+ </div>
+ }
+
+ renderContent () {
const {
conversionRate,
convertedCurrency,
gasLoadingError,
gasTotal,
- gasFeeError,
showCustomizeGasModal,
gasPriceButtonGroupProps,
gasButtonGroupShown,
+ advancedInlineGasShown,
resetGasButtons,
+ setGasPrice,
+ setGasLimit,
+ gasPrice,
+ gasLimit,
+ insufficientBalance,
} = this.props
+ const gasPriceButtonGroup = <div>
+ <GasPriceButtonGroup
+ className="gas-price-button-group--small"
+ showCheck={false}
+ {...gasPriceButtonGroupProps}
+ />
+ { this.renderAdvancedOptionsButton() }
+ </div>
+ const gasFeeDisplay = <GasFeeDisplay
+ conversionRate={conversionRate}
+ convertedCurrency={convertedCurrency}
+ gasLoadingError={gasLoadingError}
+ gasTotal={gasTotal}
+ onReset={resetGasButtons}
+ onClick={() => showCustomizeGasModal()}
+ />
+ const advancedGasInputs = <div>
+ <AdvancedGasInputs
+ updateCustomGasPrice={newGasPrice => setGasPrice(newGasPrice, gasLimit)}
+ updateCustomGasLimit={newGasLimit => setGasLimit(newGasLimit, gasPrice)}
+ customGasPrice={gasPrice}
+ customGasLimit={gasLimit}
+ insufficientBalance={insufficientBalance}
+ customPriceIsSafe={true}
+ isSpeedUp={false}
+ />
+ { this.renderAdvancedOptionsButton() }
+ </div>
+
+ if (advancedInlineGasShown) {
+ return advancedGasInputs
+ } else if (gasButtonGroupShown) {
+ return gasPriceButtonGroup
+ } else {
+ return gasFeeDisplay
+ }
+ }
+
+ render () {
+ const { gasFeeError } = this.props
+
return (
<SendRowWrapper
label={`${this.context.t('transactionFee')}:`}
showError={gasFeeError}
errorType={'gasFee'}
>
- {gasButtonGroupShown
- ? <div>
- <GasPriceButtonGroup
- className="gas-price-button-group--small"
- showCheck={false}
- {...gasPriceButtonGroupProps}
- />
- <div className="advanced-gas-options-btn" onClick={() => showCustomizeGasModal()}>
- { this.context.t('advancedOptions') }
- </div>
- </div>
- : <GasFeeDisplay
- conversionRate={conversionRate}
- convertedCurrency={convertedCurrency}
- gasLoadingError={gasLoadingError}
- gasTotal={gasTotal}
- onReset={resetGasButtons}
- onClick={() => showCustomizeGasModal()}
- />}
-
+ { this.renderContent() }
</SendRowWrapper>
)
}
diff --git a/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js b/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
index 977f8ab3c..b32928b75 100644
--- a/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
+++ b/ui/app/components/send/send-content/send-gas-row/send-gas-row.container.js
@@ -4,32 +4,59 @@ import {
getCurrentCurrency,
getGasTotal,
getGasPrice,
+ getGasLimit,
+ getSendAmount,
} from '../../send.selectors.js'
import {
+ isBalanceSufficient,
+ calcGasTotal,
+} from '../../send.utils.js'
+import {
getBasicGasEstimateLoadingStatus,
getRenderableEstimateDataForSmallButtonsFromGWEI,
getDefaultActiveButtonIndex,
} from '../../../../selectors/custom-gas'
import {
+ decGWEIToHexWEI,
+ decimalToHex,
+ convertGasPriceForInputs,
+ convertGasLimitForInputs,
+} from '../../../../helpers/conversions.util'
+import {
showGasButtonGroup,
} from '../../../../ducks/send.duck'
import {
resetCustomData,
} from '../../../../ducks/gas.duck'
import { getGasLoadingError, gasFeeIsInError, getGasButtonGroupShown } from './send-gas-row.selectors.js'
-import { showModal, setGasPrice } from '../../../../actions'
+import { showModal, setGasPrice, setGasLimit, setGasTotal } from '../../../../actions'
+import { getAdvancedInlineGasShown, getCurrentEthBalance } from '../../../../selectors'
import SendGasRow from './send-gas-row.component'
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow)
function mapStateToProps (state) {
const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state)
- const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, getGasPrice(state))
+ const gasPrice = getGasPrice(state)
+ const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, gasPrice)
+ const renderableGasPrice = convertGasPriceForInputs(gasPrice)
+ const renderableGasLimit = convertGasLimitForInputs(getGasLimit(state))
+
+ const gasTotal = getGasTotal(state)
+ const conversionRate = getConversionRate(state)
+ const balance = getCurrentEthBalance(state)
+
+ const insufficientBalance = !isBalanceSufficient({
+ amount: getSendAmount(state),
+ gasTotal,
+ balance,
+ conversionRate,
+ })
return {
- conversionRate: getConversionRate(state),
+ conversionRate,
convertedCurrency: getCurrentCurrency(state),
- gasTotal: getGasTotal(state),
+ gasTotal,
gasFeeError: gasFeeIsInError(state),
gasLoadingError: getGasLoadingError(state),
gasPriceButtonGroupProps: {
@@ -39,13 +66,26 @@ function mapStateToProps (state) {
gasButtonInfo,
},
gasButtonGroupShown: getGasButtonGroupShown(state),
+ advancedInlineGasShown: getAdvancedInlineGasShown(state),
+ gasPrice: renderableGasPrice,
+ gasLimit: renderableGasLimit,
+ insufficientBalance,
}
}
function mapDispatchToProps (dispatch) {
return {
showCustomizeGasModal: () => dispatch(showModal({ name: 'CUSTOMIZE_GAS', hideBasic: true })),
- setGasPrice: newPrice => dispatch(setGasPrice(newPrice)),
+ setGasPrice: (newPrice, gasLimit) => {
+ newPrice = decGWEIToHexWEI(newPrice)
+ dispatch(setGasPrice(newPrice))
+ dispatch(setGasTotal(calcGasTotal(gasLimit, newPrice)))
+ },
+ setGasLimit: (newLimit, gasPrice) => {
+ newLimit = decimalToHex(newLimit)
+ dispatch(setGasLimit(newLimit))
+ dispatch(setGasTotal(calcGasTotal(newLimit, gasPrice)))
+ },
showGasButtonGroup: () => dispatch(showGasButtonGroup()),
resetCustomData: () => dispatch(resetCustomData()),
}
@@ -74,5 +114,6 @@ function mergeProps (stateProps, dispatchProps, ownProps) {
dispatchSetGasPrice(gasButtonInfo[1].priceInHexWei)
dispatchShowGasButtonGroup()
},
+ setGasPrice: dispatchSetGasPrice,
}
}
diff --git a/ui/app/components/send/send-content/send-gas-row/tests/send-gas-row-container.test.js b/ui/app/components/send/send-content/send-gas-row/tests/send-gas-row-container.test.js
index f0c82e4f7..439f2ef6a 100644
--- a/ui/app/components/send/send-content/send-gas-row/tests/send-gas-row-container.test.js
+++ b/ui/app/components/send/send-content/send-gas-row/tests/send-gas-row-container.test.js
@@ -9,6 +9,8 @@ let mergeProps
const actionSpies = {
showModal: sinon.spy(),
setGasPrice: sinon.spy(),
+ setGasTotal: sinon.spy(),
+ setGasLimit: sinon.spy(),
}
const sendDuckSpies = {
@@ -28,11 +30,26 @@ proxyquire('../send-gas-row.container.js', {
return () => ({})
},
},
+ '../../../../selectors': {
+ getCurrentEthBalance: (s) => `mockCurrentEthBalance:${s}`,
+ getAdvancedInlineGasShown: (s) => `mockAdvancedInlineGasShown:${s}`,
+ },
'../../send.selectors.js': {
getConversionRate: (s) => `mockConversionRate:${s}`,
getCurrentCurrency: (s) => `mockConvertedCurrency:${s}`,
getGasTotal: (s) => `mockGasTotal:${s}`,
getGasPrice: (s) => `mockGasPrice:${s}`,
+ getGasLimit: (s) => `mockGasLimit:${s}`,
+ getSendAmount: (s) => `mockSendAmount:${s}`,
+ },
+ '../../send.utils.js': {
+ isBalanceSufficient: ({
+ amount,
+ gasTotal,
+ balance,
+ conversionRate,
+ }) => `${amount}:${gasTotal}:${balance}:${conversionRate}`,
+ calcGasTotal: (gasLimit, gasPrice) => gasLimit + gasPrice,
},
'./send-gas-row.selectors.js': {
getGasLoadingError: (s) => `mockGasLoadingError:${s}`,
@@ -47,6 +64,12 @@ proxyquire('../send-gas-row.container.js', {
},
'../../../../ducks/send.duck': sendDuckSpies,
'../../../../ducks/gas.duck': gasDuckSpies,
+ '../../../../helpers/conversions.util': {
+ convertGasPriceForInputs: str => str + '*',
+ convertGasLimitForInputs: str => str + '**',
+ decGWEIToHexWEI: str => '0x' + str + '000',
+ decimalToHex: str => '0x' + str,
+ },
})
describe('send-gas-row container', () => {
@@ -67,6 +90,10 @@ describe('send-gas-row container', () => {
gasButtonInfo: `mockGasButtonInfo:mockState`,
},
gasButtonGroupShown: `mockGetGasButtonGroupShown:mockState`,
+ advancedInlineGasShown: 'mockAdvancedInlineGasShown:mockState',
+ gasLimit: 'mockGasLimit:mockState**',
+ gasPrice: 'mockGasPrice:mockState*',
+ insufficientBalance: false,
})
})
@@ -79,6 +106,7 @@ describe('send-gas-row container', () => {
beforeEach(() => {
dispatchSpy = sinon.spy()
mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy)
+ actionSpies.setGasTotal.resetHistory()
})
describe('showCustomizeGasModal()', () => {
@@ -94,10 +122,23 @@ describe('send-gas-row container', () => {
describe('setGasPrice()', () => {
it('should dispatch an action', () => {
- mapDispatchToPropsObject.setGasPrice('mockNewPrice')
- assert(dispatchSpy.calledOnce)
+ mapDispatchToPropsObject.setGasPrice('mockNewPrice', 'mockLimit')
+ assert(dispatchSpy.calledTwice)
assert(actionSpies.setGasPrice.calledOnce)
- assert.equal(actionSpies.setGasPrice.getCall(0).args[0], 'mockNewPrice')
+ assert.equal(actionSpies.setGasPrice.getCall(0).args[0], '0xmockNewPrice000')
+ assert(actionSpies.setGasTotal.calledOnce)
+ assert.equal(actionSpies.setGasTotal.getCall(0).args[0], 'mockLimit0xmockNewPrice000')
+ })
+ })
+
+ describe('setGasLimit()', () => {
+ it('should dispatch an action', () => {
+ mapDispatchToPropsObject.setGasLimit('mockNewLimit', 'mockPrice')
+ assert(dispatchSpy.calledTwice)
+ assert(actionSpies.setGasLimit.calledOnce)
+ assert.equal(actionSpies.setGasLimit.getCall(0).args[0], '0xmockNewLimit')
+ assert(actionSpies.setGasTotal.calledOnce)
+ assert.equal(actionSpies.setGasTotal.getCall(0).args[0], '0xmockNewLimitmockPrice')
})
})