aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app')
-rw-r--r--ui/app/components/bn-as-decimal-input.js143
-rw-r--r--ui/app/components/pending-tx.js39
2 files changed, 164 insertions, 18 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..d0eebe09e
--- /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 bn string value.
+ *
+ * On change, calls back its `onChange` function parameter
+ * and passes it an updated bn 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 scale = Math.pow(10, precision)
+ const newValue = value.toNumber(10) / scale
+
+ 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 0d1f06ba6..37a3a3bf3 100644
--- a/ui/app/components/pending-tx.js
+++ b/ui/app/components/pending-tx.js
@@ -12,7 +12,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)
@@ -50,7 +50,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)
@@ -152,9 +151,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',
@@ -174,9 +174,10 @@ 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: {
@@ -342,22 +343,22 @@ PendingTx.prototype.miniAccountPanelForRecipient = function () {
}
}
-PendingTx.prototype.gasPriceChanged = function (newHex) {
- log.info(`Gas price changed to: ${newHex}`)
- const inWei = hexToBn(newHex).mul(GWEI_FACTOR)
+PendingTx.prototype.gasPriceChanged = function (newBN) {
+ log.info(`Gas price changed to: ${newBN.toString(10)}`)
const txMeta = this.gatherTxMeta()
- txMeta.txParams.gasPrice = inWei.toString(16)
- this.setState({ txData: txMeta })
+ txMeta.txParams.gasPrice = '0x' + newBN.toString('hex')
+ this.setState({ txData: cloneObj(txMeta) })
}
-PendingTx.prototype.gasLimitChanged = function (newHex) {
- log.info(`Gas limit changed to ${newHex}`)
+PendingTx.prototype.gasLimitChanged = function (newBN) {
+ log.info(`Gas limit changed to ${newBN.toString(10)}`)
const txMeta = this.gatherTxMeta()
- txMeta.txParams.gas = newHex
- this.setState({ txData: txMeta })
+ txMeta.txParams.gas = '0x' + newBN.toString('hex')
+ this.setState({ txData: cloneObj(txMeta) })
}
PendingTx.prototype.resetGasFields = function () {
+
log.debug(`pending-tx resetGasFields`)
this.inputs.forEach((hexInput) => {
@@ -404,7 +405,7 @@ PendingTx.prototype.gatherTxMeta = function () {
log.debug(`pending-tx gatherTxMeta`)
const props = this.props
const state = this.state
- const txData = state.txData || props.txData
+ const txData = cloneObj(state.txData) || cloneObj(props.txData)
log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`)
return txData
@@ -425,7 +426,6 @@ PendingTx.prototype._notZeroOrEmptyString = function (obj) {
function forwardCarrat () {
return (
-
h('img', {
src: 'images/forward-carrat.svg',
style: {
@@ -433,6 +433,9 @@ function forwardCarrat () {
height: '37px',
},
})
-
)
}
+
+function cloneObj (obj) {
+ return JSON.parse(JSON.stringify(obj))
+}