diff options
-rw-r--r-- | ui/app/components/bn-as-decimal-input.js | 143 | ||||
-rw-r--r-- | ui/app/components/pending-tx.js | 27 |
2 files changed, 157 insertions, 13 deletions
diff --git a/ui/app/components/bn-as-decimal-input.js b/ui/app/components/bn-as-decimal-input.js new file mode 100644 index 000000000..6c2132ca1 --- /dev/null +++ b/ui/app/components/bn-as-decimal-input.js @@ -0,0 +1,143 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const extend = require('xtend') + +module.exports = BnAsDecimalInput + +inherits(BnAsDecimalInput, Component) +function BnAsDecimalInput () { + this.state = { invalid: null } + Component.call(this) +} + +/* Bn as Decimal Input + * + * A component for allowing easy, decimal editing + * of a passed in hex string value. + * + * On change, calls back its `onChange` function parameter + * and passes it an updated hex string. + */ + +BnAsDecimalInput.prototype.render = function () { + const props = this.props + const state = this.state + + const { value, precision, onChange, min, max } = props + + const suffix = props.suffix + const style = props.style + const newValue = value.toNumber(10) / scale + const scale = Math.pow(10, precision) + + return ( + h('.flex-column', [ + h('.flex-row', { + style: { + alignItems: 'flex-end', + lineHeight: '13px', + fontFamily: 'Montserrat Light', + textRendering: 'geometricPrecision', + }, + }, [ + h('input.hex-input', { + type: 'number', + step: 'any', + required: true, + min: min, + max: max, + style: extend({ + display: 'block', + textAlign: 'right', + backgroundColor: 'transparent', + border: '1px solid #bdbdbd', + + }, style), + value: newValue, + onBlur: (event) => { + this.updateValidity(event) + }, + onChange: (event) => { + this.updateValidity(event) + const value = (event.target.value === '') ? '' : event.target.value + const scaledNumber = Math.floor(scale * value) + const precisionBN = new BN(scaledNumber, 10) + onChange(precisionBN) + }, + onInvalid: (event) => { + const msg = this.constructWarning() + if (msg === state.invalid) { + return + } + this.setState({ invalid: msg }) + event.preventDefault() + return false + }, + }), + h('div', { + style: { + color: ' #AEAEAE', + fontSize: '12px', + marginLeft: '5px', + marginRight: '6px', + width: '20px', + }, + }, suffix), + ]), + + state.invalid ? h('span.error', { + style: { + position: 'absolute', + right: '0px', + textAlign: 'right', + transform: 'translateY(26px)', + padding: '3px', + background: 'rgba(255,255,255,0.85)', + zIndex: '1', + textTransform: 'capitalize', + border: '2px solid #E20202', + }, + }, state.invalid) : null, + ]) + ) +} + +BnAsDecimalInput.prototype.setValid = function (message) { + this.setState({ invalid: null }) +} + +BnAsDecimalInput.prototype.updateValidity = function (event) { + const target = event.target + const value = this.props.value + const newValue = target.value + + if (value === newValue) { + return + } + + const valid = target.checkValidity() + + if (valid) { + this.setState({ invalid: null }) + } +} + +BnAsDecimalInput.prototype.constructWarning = function () { + const { name, min, max } = this.props + let message = name ? name + ' ' : '' + + if (min && max) { + message += `must be greater than or equal to ${min} and less than or equal to ${max}.` + } else if (min) { + message += `must be greater than or equal to ${min}.` + } else if (max) { + message += `must be less than or equal to ${max}.` + } else { + message += 'Invalid input.' + } + + return message +} diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 5ea885195..95d345a3d 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -13,7 +13,7 @@ const EthBalance = require('./eth-balance') const util = require('../util') const addressSummary = util.addressSummary const nameForAddress = require('../../lib/contract-namer') -const HexInput = require('./hex-as-decimal-input') +const BNInput = require('./bn-as-decimal-input') const MIN_GAS_PRICE_GWEI_BN = new BN(2) const GWEI_FACTOR = new BN(1e9) @@ -54,7 +54,6 @@ PendingTx.prototype.render = function () { // Gas Price const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) const gasPriceBn = hexToBn(gasPrice) - const gasPriceGweiBn = gasPriceBn.div(GWEI_FACTOR) const txFeeBn = gasBn.mul(gasPriceBn) const valueBn = hexToBn(txParams.value) @@ -166,9 +165,10 @@ PendingTx.prototype.render = function () { h('.cell.label', 'Gas Limit'), h('.cell.value', { }, [ - h(HexInput, { + h(BNInput, { name: 'Gas Limit', - value: gas, + value: gasBn, + precision: 0, // The hard lower limit for gas. min: MIN_GAS_LIMIT_BN.toString(10), suffix: 'UNITS', @@ -176,10 +176,10 @@ PendingTx.prototype.render = function () { position: 'relative', top: '5px', }, - onChange: (newHex) => { - log.info(`Gas limit changed to ${newHex}`) + onChange: (newBN) => { + log.info(`Gas limit changed to ${newBN.toString(10)}`) const txMeta = this.gatherTxMeta() - txMeta.txParams.gas = newHex + txMeta.txParams.gas = '0x' + newBN.toString('hex') this.setState({ txData: txMeta }) }, ref: (hexInput) => { this.inputs.push(hexInput) }, @@ -192,20 +192,20 @@ PendingTx.prototype.render = function () { h('.cell.label', 'Gas Price'), h('.cell.value', { }, [ - h(HexInput, { + h(BNInput, { name: 'Gas Price', - value: gasPriceGweiBn.toString(16), + value: gasPriceBn, + precision: 9, suffix: 'GWEI', min: MIN_GAS_PRICE_GWEI_BN.toString(10), style: { position: 'relative', top: '5px', }, - onChange: (newHex) => { - log.info(`Gas price changed to: ${newHex}`) - const inWei = hexToBn(newHex).mul(GWEI_FACTOR) + onChange: (newBN) => { + log.info(`Gas price changed to: ${newBN.toString(10)}`) const txMeta = this.gatherTxMeta() - txMeta.txParams.gasPrice = inWei.toString(16) + txMeta.txParams.gasPrice = '0x' + newBN.toString('hex') this.setState({ txData: txMeta }) }, ref: (hexInput) => { this.inputs.push(hexInput) }, @@ -368,6 +368,7 @@ PendingTx.prototype.miniAccountPanelForRecipient = function () { } PendingTx.prototype.resetGasFields = function () { + log.debug(`pending-tx resetGasFields`) this.inputs.forEach((hexInput) => { |