From 62febac87659ddf78a34dd0dac1ee8a38d8c8e77 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 27 Feb 2018 15:14:18 -0800 Subject: refactor retrytx with higher gas price: - create a new tx instead of overwriting the tx hash - add a new state 'dropped' to the txStateManager - mark duplicate txs as dropped when one gets confirmed in a block --- app/scripts/controllers/transactions.js | 43 +++++++++++++++++++++------------ app/scripts/lib/tx-state-manager.js | 38 +++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ef5578d5a..aad3f9952 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -6,7 +6,6 @@ const EthQuery = require('ethjs-query') const TransactionStateManger = require('../lib/tx-state-manager') const TxGasUtil = require('../lib/tx-gas-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') -const createId = require('../lib/random-id') const NonceTracker = require('../lib/nonce-tracker') /* @@ -92,8 +91,22 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker.on('tx:warning', (txMeta) => { this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:warning') }) + this.pendingTxTracker.on('tx:confirmed', (txId) => { + this.txStateManager.setTxStatusConfirmed(txId) + // get the confirmed transactions nonce and from address + const txMeta = this.txStateManager.getTx(txId) + const { nonce, from } = txMeta.txParams + const sameNonceTxs = this.txStateManager.getFilteredTxList({nonce, from}) + if (!sameNonceTxs.length) return + // mark all same nonce transactions as dropped and give i a replacedBy hash + sameNonceTxs.forEach((otherTxMeta) => { + if (otherTxMeta === txId) return + otherTxMeta.replacedBy = txMeta.hash + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:confirmed reference to confirmed txHash with same nonce') + this.txStateManager.setTxStatusDropped(otherTxMeta.id) + }) + }) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) - this.pendingTxTracker.on('tx:confirmed', this.txStateManager.setTxStatusConfirmed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { if (!txMeta.firstRetryBlockNumber) { txMeta.firstRetryBlockNumber = latestBlockNumber @@ -186,14 +199,7 @@ module.exports = class TransactionController extends EventEmitter { // validate await this.txGasUtil.validateTxParams(txParams) // construct txMeta - const txMeta = { - id: createId(), - time: (new Date()).getTime(), - status: 'unapproved', - metamaskNetworkId: this.getNetwork(), - txParams: txParams, - loadingDefaults: true, - } + const txMeta = this.txStateManager.generateTxMeta({txParams}) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) // add default tx params @@ -215,7 +221,6 @@ module.exports = class TransactionController extends EventEmitter { const txParams = txMeta.txParams // ensure value txMeta.gasPriceSpecified = Boolean(txParams.gasPrice) - txMeta.nonceSpecified = Boolean(txParams.nonce) let gasPrice = txParams.gasPrice if (!gasPrice) { gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice() @@ -226,11 +231,17 @@ module.exports = class TransactionController extends EventEmitter { return await this.txGasUtil.analyzeGasUsage(txMeta) } - async retryTransaction (txId) { - this.txStateManager.setTxStatusUnapproved(txId) - const txMeta = this.txStateManager.getTx(txId) - txMeta.lastGasPrice = txMeta.txParams.gasPrice - this.txStateManager.updateTx(txMeta, 'retryTransaction: manual retry') + async retryTransaction (originalTxId) { + const originalTxMeta = this.txStateManager.getTx(originalTxId) + const lastGasPrice = originalTxMeta.txParams.gasPrice + const txMeta = this.txStateManager.generateTxMeta({ + txParams: originalTxMeta.txParams, + lastGasPrice, + loadingDefaults: false, + nonceSpecified: true, + }) + this.addTx(txMeta) + this.emit('newUnapprovedTx', txMeta) } async updateTransaction (txMeta) { diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 051efd247..25442ce47 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -1,9 +1,21 @@ const extend = require('xtend') const EventEmitter = require('events') const ObservableStore = require('obs-store') +const createId = require('./random-id') const ethUtil = require('ethereumjs-util') const txStateHistoryHelper = require('./tx-state-history-helper') +// STATUS METHODS + // statuses: + // - `'unapproved'` the user has not responded + // - `'rejected'` the user has responded no! + // - `'approved'` the user has approved the tx + // - `'signed'` the tx is signed + // - `'submitted'` the tx is sent to a server + // - `'confirmed'` the tx has been included in a block. + // - `'failed'` the tx failed for some reason, included on tx data. + // - `'dropped'` the tx nonce was already used + module.exports = class TransactionStateManger extends EventEmitter { constructor ({ initState, txHistoryLimit, getNetwork }) { super() @@ -16,6 +28,16 @@ module.exports = class TransactionStateManger extends EventEmitter { this.getNetwork = getNetwork } + generateTxMeta (opts) { + return extend({ + id: createId(), + time: (new Date()).getTime(), + status: 'unapproved', + metamaskNetworkId: this.getNetwork(), + loadingDefaults: true, + }, opts) + } + // Returns the number of txs for the current network. getTxCount () { return this.getTxList().length @@ -164,16 +186,6 @@ module.exports = class TransactionStateManger extends EventEmitter { }) } - // STATUS METHODS - // statuses: - // - `'unapproved'` the user has not responded - // - `'rejected'` the user has responded no! - // - `'approved'` the user has approved the tx - // - `'signed'` the tx is signed - // - `'submitted'` the tx is sent to a server - // - `'confirmed'` the tx has been included in a block. - // - `'failed'` the tx failed for some reason, included on tx data. - // get::set status // should return the status of the tx. @@ -211,6 +223,12 @@ module.exports = class TransactionStateManger extends EventEmitter { this._setTxStatus(txId, 'confirmed') } + // should update the status dropped + setTxStatusDropped (txId) { + this._setTxStatus(txId, 'dropped') + } + + setTxStatusFailed (txId, err) { const txMeta = this.getTx(txId) txMeta.err = { -- cgit v1.2.3 From 4a3288fec9ae7bd717b539d9bfcb8d5ba5b1ef8c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 7 Mar 2018 22:01:14 -0800 Subject: transactions - make _markNonceDuplicatesDropped --- app/scripts/controllers/transactions.js | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index aad3f9952..e903c73e8 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -91,21 +91,7 @@ module.exports = class TransactionController extends EventEmitter { this.pendingTxTracker.on('tx:warning', (txMeta) => { this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:warning') }) - this.pendingTxTracker.on('tx:confirmed', (txId) => { - this.txStateManager.setTxStatusConfirmed(txId) - // get the confirmed transactions nonce and from address - const txMeta = this.txStateManager.getTx(txId) - const { nonce, from } = txMeta.txParams - const sameNonceTxs = this.txStateManager.getFilteredTxList({nonce, from}) - if (!sameNonceTxs.length) return - // mark all same nonce transactions as dropped and give i a replacedBy hash - sameNonceTxs.forEach((otherTxMeta) => { - if (otherTxMeta === txId) return - otherTxMeta.replacedBy = txMeta.hash - this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:confirmed reference to confirmed txHash with same nonce') - this.txStateManager.setTxStatusDropped(otherTxMeta.id) - }) - }) + this.pendingTxTracker.on('tx:confirmed', (txId) => this._markNonceDuplicatesDropped(txId)) this.pendingTxTracker.on('tx:failed', this.txStateManager.setTxStatusFailed.bind(this.txStateManager)) this.pendingTxTracker.on('tx:block-update', (txMeta, latestBlockNumber) => { if (!txMeta.firstRetryBlockNumber) { @@ -238,7 +224,6 @@ module.exports = class TransactionController extends EventEmitter { txParams: originalTxMeta.txParams, lastGasPrice, loadingDefaults: false, - nonceSpecified: true, }) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) @@ -264,11 +249,9 @@ module.exports = class TransactionController extends EventEmitter { // wait for a nonce nonceLock = await this.nonceTracker.getNonceLock(fromAddress) // add nonce to txParams - const nonce = txMeta.nonceSpecified ? txMeta.txParams.nonce : nonceLock.nextNonce - if (nonce > nonceLock.nextNonce) { - const message = `Specified nonce may not be larger than account's next valid nonce.` - throw new Error(message) - } + // if txMeta has lastGasPrice then it is a retry at same nonce with higher + // gas price transaction and their for the nonce should not be calculated + const nonce = txMeta.lastGasPrice ? txMeta.txParams.nonce : nonceLock.nextNonce txMeta.txParams.nonce = ethUtil.addHexPrefix(nonce.toString(16)) // add nonce debugging information to txMeta txMeta.nonceDetails = nonceLock.nonceDetails @@ -325,6 +308,22 @@ module.exports = class TransactionController extends EventEmitter { // PRIVATE METHODS // + _markNonceDuplicatesDropped (txId) { + this.txStateManager.setTxStatusConfirmed(txId) + // get the confirmed transactions nonce and from address + const txMeta = this.txStateManager.getTx(txId) + const { nonce, from } = txMeta.txParams + const sameNonceTxs = this.txStateManager.getFilteredTxList({nonce, from}) + if (!sameNonceTxs.length) return + // mark all same nonce transactions as dropped and give i a replacedBy hash + sameNonceTxs.forEach((otherTxMeta) => { + if (otherTxMeta === txId) return + otherTxMeta.replacedBy = txMeta.hash + this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:confirmed reference to confirmed txHash with same nonce') + this.txStateManager.setTxStatusDropped(otherTxMeta.id) + }) + } + _updateMemstore () { const unapprovedTxs = this.txStateManager.getUnapprovedTxList() const selectedAddressTxList = this.txStateManager.getFilteredTxList({ -- cgit v1.2.3 From 5572345b781ce68178dd4e72d4e56b2dec26a454 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 8 Mar 2018 10:36:31 -0800 Subject: fix marking of confirmed transaction as dropped --- app/scripts/controllers/transactions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index e903c73e8..3dbd424ca 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -317,7 +317,7 @@ module.exports = class TransactionController extends EventEmitter { if (!sameNonceTxs.length) return // mark all same nonce transactions as dropped and give i a replacedBy hash sameNonceTxs.forEach((otherTxMeta) => { - if (otherTxMeta === txId) return + if (otherTxMeta.id === txId) return otherTxMeta.replacedBy = txMeta.hash this.txStateManager.updateTx(txMeta, 'transactions/pending-tx-tracker#event: tx:confirmed reference to confirmed txHash with same nonce') this.txStateManager.setTxStatusDropped(otherTxMeta.id) -- cgit v1.2.3 From 6cee76b3e797dd302c1bf97d7799567a366b2004 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 8 Mar 2018 16:12:25 -0330 Subject: Add html and css for responsive retry button. --- ui/app/components/tx-list-item.js | 9 +++++ ui/app/css/itcss/components/transaction-list.scss | 47 +++++++++++++++++++++++ ui/app/css/itcss/settings/variables.scss | 1 + 3 files changed, 57 insertions(+) diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 1a13070c8..574d10e14 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -240,6 +240,15 @@ TxListItem.prototype.render = function () { ]), ]), + + h('div.tx-list-item-retry-container', [ + + h('span.tx-list-item-retry-copy', 'Taking too long?'), + + h('span.tx-list-item-retry-link', 'Increase the gas on your transaction'), + + ]), + ]), // holding on icon from design ]) } diff --git a/ui/app/css/itcss/components/transaction-list.scss b/ui/app/css/itcss/components/transaction-list.scss index c3df493df..4545897e3 100644 --- a/ui/app/css/itcss/components/transaction-list.scss +++ b/ui/app/css/itcss/components/transaction-list.scss @@ -126,6 +126,53 @@ } } +.tx-list-item-retry-container { + background: #d1edff; + width: 100%; + border-radius: 4px; + font-size: 0.8em; + display: flex; + justify-content: center; + margin-left: 44px; + width: calc(100% - 44px); + + @media screen and (min-width: 576px) and (max-width: 679px) { + flex-flow: column; + align-items: center; + } + + @media screen and (min-width: 380px) and (max-width: 575px) { + flex-flow: row; + } + + @media screen and (max-width: 379px) { + flex-flow: column; + align-items: center; + } +} + +.tx-list-item-retry-copy { + font-family: Roboto; +} + +.tx-list-item-retry-link { + text-decoration: underline; + margin-left: 6px; + cursor: pointer; + + @media screen and (min-width: 576px) and (max-width: 679px) { + margin-left: 0px; + } + + @media screen and (min-width: 380px) and (max-width: 575px) { + margin-left: 6px; + } + + @media screen and (max-width: 379px) { + margin-left: 0px; + } +} + .tx-list-date { color: $dusty-gray; font-size: 12px; diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss index 4c0972527..1b5f1a491 100644 --- a/ui/app/css/itcss/settings/variables.scss +++ b/ui/app/css/itcss/settings/variables.scss @@ -46,6 +46,7 @@ $manatee: #93949d; $spindle: #c7ddec; $mid-gray: #5b5d67; $cape-cod: #38393a; +$onahau: #d1edff; /* Z-Indicies -- cgit v1.2.3 From 5433d2fe3a3f48948449258b03ae431fe81b8cf2 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 9 Mar 2018 00:19:26 -0330 Subject: Retry transaction logic added to tx-list-item, confirm-send-ether, customize-gas-modal, and dependents. --- ui/app/actions.js | 4 +- ui/app/components/customize-gas-modal/index.js | 18 ++++++++- ui/app/components/pending-tx/confirm-send-ether.js | 20 ++++++++- ui/app/components/tx-list-item.js | 47 ++++++++++++++++++---- ui/app/components/tx-list.js | 13 +++--- ui/app/conversion-util.js | 13 ++++++ ui/app/reducers/metamask.js | 4 ++ ui/app/selectors.js | 5 +++ ui/app/send-v2.js | 5 +++ 9 files changed, 113 insertions(+), 16 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index 4f902a6a2..3e050c38c 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1228,8 +1228,10 @@ function retryTransaction (txId) { if (err) { return dispatch(actions.displayWarning(err.message)) } + const { selectedAddressTxList } = newState + const { id: newTxId } = selectedAddressTxList[selectedAddressTxList.length - 1] dispatch(actions.updateMetamaskState(newState)) - dispatch(actions.viewPendingTx(txId)) + dispatch(actions.viewPendingTx(newTxId)) }) } } diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 826d2cd4b..34a93d6c6 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -21,12 +21,14 @@ const { conversionUtil, multiplyCurrencies, conversionGreaterThan, + conversionMax, subtractCurrencies, } = require('../../conversion-util') const { getGasPrice, getGasLimit, + getForceGasMin, conversionRateSelector, getSendAmount, getSelectedToken, @@ -44,6 +46,7 @@ function mapStateToProps (state) { return { gasPrice: getGasPrice(state), gasLimit: getGasLimit(state), + forceGasMin: getForceGasMin(state), conversionRate, amount: getSendAmount(state), maxModeOn: getSendMaxModeState(state), @@ -217,7 +220,7 @@ CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) { } CustomizeGasModal.prototype.render = function () { - const { hideModal } = this.props + const { hideModal, forceGasMin } = this.props const { gasPrice, gasLimit, gasTotal, error, priceSigZeros, priceSigDec } = this.state let convertedGasPrice = conversionUtil(gasPrice, { @@ -229,6 +232,17 @@ CustomizeGasModal.prototype.render = function () { convertedGasPrice += convertedGasPrice.match(/[.]/) ? priceSigZeros : `${priceSigDec}${priceSigZeros}` + if (forceGasMin) { + const convertedMinPrice = conversionUtil(forceGasMin, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + }) + convertedGasPrice = conversionMax( + { value: convertedMinPrice, fromNumericBase: 'dec' }, + { value: convertedGasPrice, fromNumericBase: 'dec' } + ) + } + const convertedGasLimit = conversionUtil(gasLimit, { fromNumericBase: 'hex', toNumericBase: 'dec', @@ -251,7 +265,7 @@ CustomizeGasModal.prototype.render = function () { h(GasModalCard, { value: convertedGasPrice, - min: MIN_GAS_PRICE_GWEI, + min: forceGasMin || MIN_GAS_PRICE_GWEI, // max: 1000, step: multiplyCurrencies(MIN_GAS_PRICE_GWEI, 10), onChange: value => this.convertAndSetGasPrice(value), diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 3f8d9c28f..a6e00d922 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -36,13 +36,29 @@ function mapDispatchToProps (dispatch) { return { clearSend: () => dispatch(actions.clearSend()), editTransaction: txMeta => { - const { id, txParams } = txMeta + const { id, txParams, lastGasPrice } = txMeta const { gas: gasLimit, gasPrice, to, value: amount, } = txParams + + let forceGasMin + let nonce + if (lastGasPrice) { + const stripped = ethUtil.stripHexPrefix(lastGasPrice) + forceGasMin = ethUtil.addHexPrefix(addCurrencies(stripped, MIN_GAS_PRICE_HEX, { + aBase: 16, + bBase: 16, + toNumericBase: 'hex', + fromDenomination: 'WEI', + toDenomination: 'GWEI', + })) + + nonce = txParams.nonce + } + dispatch(actions.updateSend({ gasLimit, gasPrice, @@ -51,6 +67,8 @@ function mapDispatchToProps (dispatch) { amount, errors: { to: null, amount: null }, editingTransactionId: id, + forceGasMin, + nonce, })) dispatch(actions.showSendPage()) }, diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 574d10e14..123f723be 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -9,18 +9,26 @@ abiDecoder.addABI(abi) const Identicon = require('./identicon') const contractMap = require('eth-contract-metadata') +const actions = require('../actions') const { conversionUtil, multiplyCurrencies } = require('../conversion-util') const { calcTokenAmount } = require('../token-util') const { getCurrentCurrency } = require('../selectors') -module.exports = connect(mapStateToProps)(TxListItem) +module.exports = connect(mapStateToProps, mapDispatchToProps)(TxListItem) function mapStateToProps (state) { return { tokens: state.metamask.tokens, currentCurrency: getCurrentCurrency(state), tokenExchangeRates: state.metamask.tokenExchangeRates, + selectedAddressTxList: state.metamask.selectedAddressTxList, + } +} + +function mapDispatchToProps (dispatch) { + return { + retryTransaction: transactionId => dispatch(actions.retryTransaction(transactionId)), } } @@ -167,12 +175,32 @@ TxListItem.prototype.getSendTokenTotal = async function () { } } +TxListItem.prototype.showRetryButton = function () { + const { + transactionStatus, + transactionTime, + selectedAddressTxList, + transactionId, + txParams, + } = this.props + const currentNonce = txParams.nonce + const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) + const isLastWithNonce = currentNonceTxs[currentNonceTxs.length - 1].id === transactionId + + return transactionStatus === 'submitted' && isLastWithNonce && Date.now() - transactionTime > 5000 +} + +TxListItem.prototype.resubmit = function () { + const { transactionId } = this.props + this.props.retryTransaction(transactionId) +} + TxListItem.prototype.render = function () { const { transactionStatus, transactionAmount, onClick, - transActionId, + transactionId, dateString, address, className, @@ -181,8 +209,8 @@ TxListItem.prototype.render = function () { const showFiatTotal = transactionAmount !== '0x0' && fiatTotal return h(`div${className || ''}`, { - key: transActionId, - onClick: () => onClick && onClick(transActionId), + key: transactionId, + onClick: () => onClick && onClick(transactionId), }, [ h(`div.flex-column.tx-list-item-wrapper`, {}, [ @@ -241,12 +269,17 @@ TxListItem.prototype.render = function () { ]), ]), - h('div.tx-list-item-retry-container', [ + this.showRetryButton() && h('div.tx-list-item-retry-container', [ h('span.tx-list-item-retry-copy', 'Taking too long?'), - h('span.tx-list-item-retry-link', 'Increase the gas on your transaction'), - + h('span.tx-list-item-retry-link', { + onClick: (event) => { + event.stopPropagation() + this.resubmit() + }, + }, 'Increase the gas on your transaction'), + ]), ]), // holding on icon from design diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 1729e6a6f..30f816d58 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -74,9 +74,10 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa address: transaction.txParams.to, transactionStatus: transaction.status, transactionAmount: transaction.txParams.value, - transActionId: transaction.id, + transactionId: transaction.id, transactionHash: transaction.hash, transactionNetworkId: transaction.metamaskNetworkId, + transactionTime: transaction.time, } const { @@ -84,29 +85,31 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionStatus, transactionAmount, dateString, - transActionId, + transactionId, transactionHash, transactionNetworkId, + transactionTime, } = props const { showConfTxPage } = this.props const opts = { - key: transActionId || transactionHash, + key: transactionId || transactionHash, txParams: transaction.txParams, transactionStatus, - transActionId, + transactionId, dateString, address, transactionAmount, transactionHash, conversionRate, tokenInfoGetter: this.tokenInfoGetter, + transactionTime, } const isUnapproved = transactionStatus === 'unapproved' if (isUnapproved) { - opts.onClick = () => showConfTxPage({id: transActionId}) + opts.onClick = () => showConfTxPage({id: transactionId}) opts.transactionStatus = 'Not Started' } else if (transactionHash) { opts.onClick = () => this.view(transactionHash, transactionNetworkId) diff --git a/ui/app/conversion-util.js b/ui/app/conversion-util.js index ee42ebea1..d484ed16d 100644 --- a/ui/app/conversion-util.js +++ b/ui/app/conversion-util.js @@ -187,6 +187,18 @@ const conversionGreaterThan = ( return firstValue.gt(secondValue) } +const conversionMax = ( + { ...firstProps }, + { ...secondProps }, +) => { + const firstIsGreater = conversionGreaterThan( + { ...firstProps }, + { ...secondProps } + ) + + return firstIsGreater ? firstProps.value : secondProps.value +} + const conversionGTE = ( { ...firstProps }, { ...secondProps }, @@ -216,6 +228,7 @@ module.exports = { conversionGreaterThan, conversionGTE, conversionLTE, + conversionMax, toNegative, subtractCurrencies, } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index cddcd0c1f..999939b89 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -38,6 +38,8 @@ function reduceMetamask (state, action) { errors: {}, maxModeOn: false, editingTransactionId: null, + forceGasMin: null, + nonce: null, }, coinOptions: {}, useBlockie: false, @@ -298,6 +300,8 @@ function reduceMetamask (state, action) { memo: '', errors: {}, editingTransactionId: null, + forceGasMin: null, + nonce: null, }, }) diff --git a/ui/app/selectors.js b/ui/app/selectors.js index 5d2635775..d37c26f7e 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -18,6 +18,7 @@ const selectors = { getCurrentAccountWithSendEtherInfo, getGasPrice, getGasLimit, + getForceGasMin, getAddressBook, getSendFrom, getCurrentCurrency, @@ -130,6 +131,10 @@ function getGasLimit (state) { return state.metamask.send.gasLimit } +function getForceGasMin (state) { + return state.metamask.send.forceGasMin +} + function getSendFrom (state) { return state.metamask.send.from } diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 1d67150e3..edb6bc41d 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -543,6 +543,7 @@ SendTransactionScreen.prototype.getEditedTx = function () { selectedToken, editingTransactionId, unapprovedTxs, + nonce, } = this.props const editingTx = { @@ -554,6 +555,10 @@ SendTransactionScreen.prototype.getEditedTx = function () { }, } + if (nonce) { + editingTx.txParams.nonce = ethUtil.addHexPrefix(nonce) + } + if (selectedToken) { const data = TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), -- cgit v1.2.3 From 2d6b378bf8f8f0b23ef54b48118b61fb6c7deee1 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 9 Mar 2018 02:03:36 -0330 Subject: Adds inline opening of gas customization to confirm-send-ether screen. --- ui/app/components/pending-tx/confirm-send-ether.js | 48 ++++++++++++++++++---- ui/app/components/send/gas-fee-display-v2.js | 4 +- ui/app/css/itcss/components/send.scss | 21 ++++++++++ 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index a6e00d922..422b1c6c1 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -9,6 +9,7 @@ const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil, addCurrencies } = require('../../conversion-util') +const GasFeeDisplay = require('../send/gas-fee-display-v2') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -73,6 +74,18 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + showCustomizeGasModal: (txMeta, sendGasLimit, sendGasPrice, sendGasTotal) => { + const { id, txParams } = txMeta + const { gas: txGasLimit, gasPrice: txGasPrice } = txParams + + dispatch(actions.updateSend({ + gasLimit: sendGasLimit || txGasLimit, + gasPrice: sendGasPrice || txGasPrice, + editingTransactionId: id, + gasTotal: sendGasTotal, + })) + dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) + }, } } @@ -157,6 +170,7 @@ ConfirmSendEther.prototype.getGasFee = function () { return { FIAT, ETH, + gasFeeInHex: txFeeBn.toString(16), } } @@ -164,7 +178,7 @@ ConfirmSendEther.prototype.getData = function () { const { identities } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH } = this.getGasFee() + const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH, gasFeeInHex } = this.getGasFee() const { FIAT: amountInFIAT, ETH: amountInETH } = this.getAmount() const totalInFIAT = addCurrencies(gasFeeInFIAT, amountInFIAT, { @@ -192,11 +206,20 @@ ConfirmSendEther.prototype.getData = function () { amountInETH, totalInFIAT, totalInETH, + gasFeeInHex, } } ConfirmSendEther.prototype.render = function () { - const { editTransaction, currentCurrency, clearSend } = this.props + const { + editTransaction, + currentCurrency, + clearSend, + conversionRate, + currentCurrency: convertedCurrency, + showCustomizeGasModal, + send: { gasTotal, gasLimit: sendGasLimit, gasPrice: sendGasPrice }, + } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -212,11 +235,17 @@ ConfirmSendEther.prototype.render = function () { memo, gasFeeInFIAT, gasFeeInETH, + gasFeeInHex, amountInFIAT, totalInFIAT, totalInETH, } = this.getData() + const title = txMeta.lastGasPrice ? 'Overwrite Transaction' : 'Confirm' + const subtitle = txMeta.lastGasPrice + ? 'Increase your gas fee to attempt to overwrite and speed up your transaction' + : 'Please review your transaction.' + // This is from the latest master // It handles some of the errors that we are not currently handling // Leaving as comments fo reference @@ -235,11 +264,11 @@ ConfirmSendEther.prototype.render = function () { // Main Send token Card h('div.page-container', [ h('div.page-container__header', [ - h('button.confirm-screen-back-button', { + !txMeta.lastGasPrice && h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), }, 'Edit'), - h('div.page-container__title', 'Confirm'), - h('div.page-container__subtitle', `Please review your transaction.`), + h('div.page-container__title', title), + h('div.page-container__subtitle', subtitle), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ @@ -302,9 +331,12 @@ ConfirmSendEther.prototype.render = function () { h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `${gasFeeInFIAT} ${currentCurrency.toUpperCase()}`), - - h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`), + h(GasFeeDisplay, { + gasTotal: gasTotal || gasFeeInHex, + conversionRate, + convertedCurrency, + onClick: () => showCustomizeGasModal(txMeta, sendGasLimit, sendGasPrice, gasTotal), + }), ]), ]), diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js index 0c4c3f7a9..da1bdd05e 100644 --- a/ui/app/components/send/gas-fee-display-v2.js +++ b/ui/app/components/send/gas-fee-display-v2.js @@ -32,11 +32,11 @@ GasFeeDisplay.prototype.render = function () { }) : h('div.currency-display', 'Loading...'), - h('button.send-v2__sliders-icon-container', { + h('button.sliders-icon-container', { onClick, disabled: !gasTotal, }, [ - h('i.fa.fa-sliders.send-v2__sliders-icon'), + h('i.fa.fa-sliders.sliders-icon'), ]), ]) diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index bb17e53cd..1a058b305 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -660,6 +660,7 @@ &__gas-fee-display { width: 100%; + position: relative; } &__sliders-icon-container { @@ -885,3 +886,23 @@ } } } + +.sliders-icon-container { + display: flex; + align-items: center; + justify-content: center; + height: 24px; + width: 24px; + border: 1px solid $curious-blue; + border-radius: 4px; + background-color: $white; + position: absolute; + right: 15px; + top: 14px; + cursor: pointer; + font-size: 1em; +} + +.sliders-icon { + color: $curious-blue; +} \ No newline at end of file -- cgit v1.2.3 From c1ff927fa0e129a828d3345b21723300d5e73ef1 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 9 Mar 2018 10:00:37 -0330 Subject: Lint fixes. --- ui/app/actions.js | 2 +- ui/app/components/pending-tx/confirm-send-ether.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index 200946753..d6f509590 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1271,7 +1271,7 @@ function retryTransaction (txId) { return dispatch(actions.displayWarning(err.message)) } const { selectedAddressTxList } = newState - const { id: newTxId } = selectedAddressTxList[selectedAddressTxList.length - 1] + const { id: newTxId } = selectedAddressTxList[selectedAddressTxList.length - 1] dispatch(actions.updateMetamaskState(newState)) dispatch(actions.viewPendingTx(newTxId)) }) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 422b1c6c1..ec61d66b4 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -233,8 +233,6 @@ ConfirmSendEther.prototype.render = function () { name: toName, }, memo, - gasFeeInFIAT, - gasFeeInETH, gasFeeInHex, amountInFIAT, totalInFIAT, -- cgit v1.2.3 From f805a2eb735ea2ae93e91df0d35c6856987fa734 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 02:31:35 -0230 Subject: Fix gas calculation and nonce / forceGasMin state setting errors; retry button shows on correct tx. --- ui/app/components/customize-gas-modal/index.js | 6 +-- ui/app/components/pending-tx/confirm-send-ether.js | 52 +++++++++++++--------- ui/app/components/tx-list-item.js | 6 ++- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 34a93d6c6..2bac57253 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -117,9 +117,9 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { updateSendAmount(maxAmount) } - updateGasPrice(gasPrice) - updateGasLimit(gasLimit) - updateGasTotal(gasTotal) + updateGasPrice(ethUtil.addHexPrefix(gasPrice)) + updateGasLimit(ethUtil.addHexPrefix(gasLimit)) + updateGasTotal(ethUtil.addHexPrefix(gasTotal)) hideModal() } diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index ec61d66b4..b1e3a0374 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -8,7 +8,11 @@ const Identicon = require('../identicon') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') -const { conversionUtil, addCurrencies } = require('../../conversion-util') +const { + conversionUtil, + addCurrencies, + multiplyCurrencies +} = require('../../conversion-util') const GasFeeDisplay = require('../send/gas-fee-display-v2') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -37,7 +41,7 @@ function mapDispatchToProps (dispatch) { return { clearSend: () => dispatch(actions.clearSend()), editTransaction: txMeta => { - const { id, txParams, lastGasPrice } = txMeta + const { id, txParams } = txMeta const { gas: gasLimit, gasPrice, @@ -45,21 +49,6 @@ function mapDispatchToProps (dispatch) { value: amount, } = txParams - let forceGasMin - let nonce - if (lastGasPrice) { - const stripped = ethUtil.stripHexPrefix(lastGasPrice) - forceGasMin = ethUtil.addHexPrefix(addCurrencies(stripped, MIN_GAS_PRICE_HEX, { - aBase: 16, - bBase: 16, - toNumericBase: 'hex', - fromDenomination: 'WEI', - toDenomination: 'GWEI', - })) - - nonce = txParams.nonce - } - dispatch(actions.updateSend({ gasLimit, gasPrice, @@ -68,21 +57,36 @@ function mapDispatchToProps (dispatch) { amount, errors: { to: null, amount: null }, editingTransactionId: id, - forceGasMin, - nonce, })) dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), showCustomizeGasModal: (txMeta, sendGasLimit, sendGasPrice, sendGasTotal) => { - const { id, txParams } = txMeta + const { id, txParams, lastGasPrice } = txMeta const { gas: txGasLimit, gasPrice: txGasPrice } = txParams + let forceGasMin + let nonce + if (lastGasPrice) { + const stripped = ethUtil.stripHexPrefix(lastGasPrice) + forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(stripped, 1.1, { + multiplicandBase: 16, + multiplierBase: 10, + toNumericBase: 'hex', + fromDenomination: 'WEI', + toDenomination: 'GWEI', + })) + + nonce = txParams.nonce + } + dispatch(actions.updateSend({ gasLimit: sendGasLimit || txGasLimit, gasPrice: sendGasPrice || txGasPrice, editingTransactionId: id, gasTotal: sendGasTotal, + forceGasMin, + nonce, })) dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) }, @@ -493,6 +497,14 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) + if (txData.lastGasPrice) { + const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send + const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams + + txData.txParams.gasPrice = sendGasPrice || txGasPrice + txData.txParams.gas = sendGasLimit || txGasLimit + } + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 123f723be..f7d53709f 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -185,9 +185,11 @@ TxListItem.prototype.showRetryButton = function () { } = this.props const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) - const isLastWithNonce = currentNonceTxs[currentNonceTxs.length - 1].id === transactionId + const currentStatusNonceTx = currentNonceTxs.filter(tx => + tx.status !== 'rejected' && tx.status !== 'failed') + const isLastPassingWithNonce = currentStatusNonceTx[currentStatusNonceTx.length - 1].id === transactionId - return transactionStatus === 'submitted' && isLastWithNonce && Date.now() - transactionTime > 5000 + return transactionStatus === 'submitted' && isLastPassingWithNonce && Date.now() - transactionTime > 30000 } TxListItem.prototype.resubmit = function () { -- cgit v1.2.3 From e6d1ce56e7b792957f7b5c3249ecf013752b87ed Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 03:11:45 -0230 Subject: Improve phrasing of copy. --- ui/app/components/pending-tx/confirm-send-ether.js | 2 +- ui/app/components/tx-list-item.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index b1e3a0374..8788a77f8 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -243,7 +243,7 @@ ConfirmSendEther.prototype.render = function () { totalInETH, } = this.getData() - const title = txMeta.lastGasPrice ? 'Overwrite Transaction' : 'Confirm' + const title = txMeta.lastGasPrice ? 'Reprice Transaction' : 'Confirm' const subtitle = txMeta.lastGasPrice ? 'Increase your gas fee to attempt to overwrite and speed up your transaction' : 'Please review your transaction.' diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index f7d53709f..62426252f 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -280,7 +280,7 @@ TxListItem.prototype.render = function () { event.stopPropagation() this.resubmit() }, - }, 'Increase the gas on your transaction'), + }, 'Increase the gas price on your transaction'), ]), -- cgit v1.2.3 From 179066fe6ba3eca002454981c5ef56df7bb142ab Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 03:26:37 -0230 Subject: Set txMeta.time to reflect time of tx approval. --- ui/app/components/pending-tx/confirm-send-ether.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 8788a77f8..899c2617c 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -457,7 +457,7 @@ ConfirmSendEther.prototype.render = function () { ConfirmSendEther.prototype.onSubmit = function (event) { event.preventDefault() - const txMeta = this.gatherTxMeta() + const txMeta = this.gatherTxMeta({ time: (new Date()).getTime() }) const valid = this.checkValidity() this.setState({ valid, submitting: true }) @@ -492,7 +492,7 @@ ConfirmSendEther.prototype.getFormEl = function () { } // After a customizable state value has been updated, -ConfirmSendEther.prototype.gatherTxMeta = function () { +ConfirmSendEther.prototype.gatherTxMeta = function (opts) { const props = this.props const state = this.state const txData = clone(state.txData) || clone(props.txData) @@ -506,7 +506,7 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { } // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) - return txData + return Object.assign(txData, opts) } ConfirmSendEther.prototype.verifyGasParams = function () { -- cgit v1.2.3 From 9fd349d7407d7c33deb317942f7e2835585767c9 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Mar 2018 09:51:37 -0700 Subject: transactions:state - add a submittedTime stamp so the ui has a better grasp of the time of submission --- app/scripts/lib/tx-state-manager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index e75f733aa..ad07c813f 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -214,7 +214,11 @@ module.exports = class TransactionStateManager extends EventEmitter { } // should update the status of the tx to 'submitted'. + // and add a time stamp for when it was called setTxStatusSubmitted (txId) { + const txMeta = this.getTx(txId) + txMeta.submittedTime = (new Date()).getTime() + this.updateTx(txMeta, 'txStateManager - add submitted time stamp') this._setTxStatus(txId, 'submitted') } -- cgit v1.2.3 From c6dff98ee1551c4ae69c14c52073d64ace15f773 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Mar 2018 14:30:59 -0700 Subject: tests - add tests for transactions#retryTransaction and transactions#_markNonceDuplicatesDropped --- test/unit/tx-controller-test.js | 45 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/test/unit/tx-controller-test.js b/test/unit/tx-controller-test.js index cc99afee4..712097fce 100644 --- a/test/unit/tx-controller-test.js +++ b/test/unit/tx-controller-test.js @@ -392,6 +392,49 @@ describe('Transaction Controller', function () { }) }) + describe('#retryTransaction', function () { + it('should create a new txMeta with the same txParams as the original one', function (done) { + let txParams = { + nonce: '0x00', + from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4', + to: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4', + data: '0x0', + } + txController.txStateManager._saveTxList([ + { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams }, + ]) + txController.retryTransaction(1) + .then((txMeta) => { + assert.equal(txMeta.txParams.nonce, txParams.nonce, 'nonce should be the same') + assert.equal(txMeta.txParams.from, txParams.from, 'from should be the same') + assert.equal(txMeta.txParams.to, txParams.to, 'to should be the same') + assert.equal(txMeta.txParams.data, txParams.data, 'data should be the same') + assert.ok(('lastGasPrice' in txMeta), 'should have the key `lastGasPrice`') + assert.equal(txController.txStateManager.getTxList().length, 2) + done() + }).catch(done) + }) + }) + + describe('#_markNonceDuplicatesDropped', function () { + it('should mark all nonce duplicates as dropped without marking the confirmed transaction as dropped', function () { + txController.txStateManager._saveTxList([ + { id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + { id: 4, status: 'submitted', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + { id: 5, status: 'submitted', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + { id: 6, status: 'submitted', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + { id: 7, status: 'submitted', metamaskNetworkId: currentNetworkId, history: [{}], txParams: { nonce: '0x01' } }, + ]) + txController._markNonceDuplicatesDropped(1) + const confirmedTx = txController.txStateManager.getTx(1) + const droppedTxs = txController.txStateManager.getFilteredTxList({ nonce: '0x01', status: 'dropped' }) + assert.equal(confirmedTx.status, 'confirmed', 'the confirmedTx should remain confirmed') + assert.equal(droppedTxs.length, 6, 'their should be 6 dropped txs') + + }) + }) describe('#getPendingTransactions', function () { beforeEach(function () { @@ -401,7 +444,7 @@ describe('Transaction Controller', function () { { id: 3, status: 'approved', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 4, status: 'signed', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 5, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {} }, - { id: 6, status: 'confimed', metamaskNetworkId: currentNetworkId, txParams: {} }, + { id: 6, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} }, { id: 7, status: 'failed', metamaskNetworkId: currentNetworkId, txParams: {} }, ]) }) -- cgit v1.2.3 From 9d7640996aa9b63fb6c9271d7e0698e7acdc559e Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 13 Mar 2018 14:42:26 -0700 Subject: transactions - return the txMeta in retryTransaction --- app/scripts/controllers/transactions.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index a3f731b6e..ab07dde62 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -3,7 +3,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') const EthQuery = require('ethjs-query') -const TransactionStateManager = require('../lib/tx-state-manager') +const TransactionStateManger = require('../lib/tx-state-manager') const TxGasUtil = require('../lib/tx-gas-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const NonceTracker = require('../lib/nonce-tracker') @@ -37,7 +37,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = new EthQuery(this.provider) this.txGasUtil = new TxGasUtil(this.provider) - this.txStateManager = new TransactionStateManager({ + this.txStateManager = new TransactionStateManger({ initState: opts.initState, txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), @@ -227,6 +227,7 @@ module.exports = class TransactionController extends EventEmitter { }) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) + return txMeta } async updateTransaction (txMeta) { -- cgit v1.2.3 From d6e4d2e80d05f64bb543e524c6288b8b7c33e4c1 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 21:09:04 -0230 Subject: Use new submittedTime field to correctly show retry button in old and new ui. --- old-ui/app/components/transaction-list-item.js | 12 +++++++++--- old-ui/app/components/transaction-list.js | 2 +- ui/app/components/pending-tx/confirm-send-ether.js | 2 +- ui/app/components/tx-list-item.js | 10 +++++----- ui/app/components/tx-list.js | 6 +++--- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index e7251df8d..b9da171ba 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -29,9 +29,15 @@ function TransactionListItem () { } TransactionListItem.prototype.showRetryButton = function () { - const { transaction = {} } = this.props - const { status, time } = transaction - return status === 'submitted' && Date.now() - time > 30000 + const { transaction = {}, transactions } = this.props + const { status, submittedTime, txParams } = transaction + const currentNonce = txParams.nonce + const currentNonceTxs = transactions.filter(tx => tx.txParams.nonce === currentNonce) + const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') + const isLastSubmittedTxWithCurrentNonce = + currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1].id === transaction.id + + return isLastSubmittedTxWithCurrentNonce && Date.now() - submittedTime > 30000 } TransactionListItem.prototype.render = function () { diff --git a/old-ui/app/components/transaction-list.js b/old-ui/app/components/transaction-list.js index 345e3ca16..c77852921 100644 --- a/old-ui/app/components/transaction-list.js +++ b/old-ui/app/components/transaction-list.js @@ -62,7 +62,7 @@ TransactionList.prototype.render = function () { } return h(TransactionListItem, { transaction, i, network, key, - conversionRate, + conversionRate, transactions, showTx: (txId) => { this.props.viewPendingTx(txId) }, diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 899c2617c..8fe58482b 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -11,7 +11,7 @@ const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil, addCurrencies, - multiplyCurrencies + multiplyCurrencies, } = require('../../conversion-util') const GasFeeDisplay = require('../send/gas-fee-display-v2') diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 62426252f..941fcb69c 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -178,18 +178,18 @@ TxListItem.prototype.getSendTokenTotal = async function () { TxListItem.prototype.showRetryButton = function () { const { transactionStatus, - transactionTime, + transactionSubmittedTime, selectedAddressTxList, transactionId, txParams, } = this.props const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) - const currentStatusNonceTx = currentNonceTxs.filter(tx => - tx.status !== 'rejected' && tx.status !== 'failed') - const isLastPassingWithNonce = currentStatusNonceTx[currentStatusNonceTx.length - 1].id === transactionId + const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => transactionStatus === 'submitted') + const isLastSubmittedTxWithCurrentNonce = + currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1].id === transactionId - return transactionStatus === 'submitted' && isLastPassingWithNonce && Date.now() - transactionTime > 30000 + return isLastSubmittedTxWithCurrentNonce && Date.now() - transactionSubmittedTime > 30000 } TxListItem.prototype.resubmit = function () { diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 30f816d58..add70a266 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -77,7 +77,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionId: transaction.id, transactionHash: transaction.hash, transactionNetworkId: transaction.metamaskNetworkId, - transactionTime: transaction.time, + transactionSubmittedTime: transaction.transactionSubmittedTime, } const { @@ -88,7 +88,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionId, transactionHash, transactionNetworkId, - transactionTime, + transactionSubmittedTime, } = props const { showConfTxPage } = this.props @@ -103,7 +103,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionHash, conversionRate, tokenInfoGetter: this.tokenInfoGetter, - transactionTime, + transactionSubmittedTime, } const isUnapproved = transactionStatus === 'unapproved' -- cgit v1.2.3 From e293b6349c522171db26c57e718c5213aa6d5cb3 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 21:11:50 -0230 Subject: Styling for dropped. --- ui/app/components/tx-list-item.js | 1 + ui/app/css/itcss/components/transaction-list.scss | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 941fcb69c..d2fc57b13 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -253,6 +253,7 @@ TxListItem.prototype.render = function () { className: classnames('tx-list-status', { 'tx-list-status--rejected': transactionStatus === 'rejected', 'tx-list-status--failed': transactionStatus === 'failed', + 'tx-list-status--dropped': transactionStatus === 'dropped', }), }, transactionStatus, diff --git a/ui/app/css/itcss/components/transaction-list.scss b/ui/app/css/itcss/components/transaction-list.scss index 4545897e3..df7d80e2e 100644 --- a/ui/app/css/itcss/components/transaction-list.scss +++ b/ui/app/css/itcss/components/transaction-list.scss @@ -236,6 +236,10 @@ .tx-list-status--failed { color: $monzo; } + + .tx-list-status--dropped { + opacity: 0.5; + } } .tx-list-item { -- cgit v1.2.3 From 8c7988978f05fa57bba892efb42ae0036ce25771 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 21:32:22 -0230 Subject: Undefined check in showRetryButton --- old-ui/app/components/transaction-list-item.js | 7 ++++--- ui/app/components/tx-list-item.js | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index b9da171ba..3881d8c1c 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -34,10 +34,11 @@ TransactionListItem.prototype.showRetryButton = function () { const currentNonce = txParams.nonce const currentNonceTxs = transactions.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') - const isLastSubmittedTxWithCurrentNonce = - currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1].id === transaction.id + const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1] + const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce + && lastSubmittedTxWithCurrentNonce.id === transaction.id - return isLastSubmittedTxWithCurrentNonce && Date.now() - submittedTime > 30000 + return currentTxIsLatestWithNonce && Date.now() - submittedTime > 30000 } TransactionListItem.prototype.render = function () { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index d2fc57b13..453f7e95c 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -186,10 +186,11 @@ TxListItem.prototype.showRetryButton = function () { const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => transactionStatus === 'submitted') - const isLastSubmittedTxWithCurrentNonce = - currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1].id === transactionId + const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1] + const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce + && lastSubmittedTxWithCurrentNonce.id === transactionId - return isLastSubmittedTxWithCurrentNonce && Date.now() - transactionSubmittedTime > 30000 + return currentTxIsLatestWithNonce && Date.now() - submittedTime > 30000 } TxListItem.prototype.resubmit = function () { -- cgit v1.2.3 From 46ded45b8186c0b338f6cff811cd89c48ef1a5ab Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 21:38:08 -0230 Subject: Use correct var name in new-ui showRetryButton --- ui/app/components/tx-list-item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 453f7e95c..ebf5db19f 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -190,7 +190,7 @@ TxListItem.prototype.showRetryButton = function () { const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transactionId - return currentTxIsLatestWithNonce && Date.now() - submittedTime > 30000 + return currentTxIsLatestWithNonce && Date.now() - transactionSubmittedTime > 30000 } TxListItem.prototype.resubmit = function () { -- cgit v1.2.3 From c52253bb0eb8ab1c7c7e9c0e7002d5ada42d53d6 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 21:57:23 -0230 Subject: Use correct name for submittedTime field in tx-list.js --- ui/app/components/tx-list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index add70a266..782de0266 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -77,7 +77,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionId: transaction.id, transactionHash: transaction.hash, transactionNetworkId: transaction.metamaskNetworkId, - transactionSubmittedTime: transaction.transactionSubmittedTime, + transactionSubmittedTime: transaction.submittedTime, } const { -- cgit v1.2.3 From 80a2e59194d3c5e5dc5fa098a5c022ae5dc30848 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 22:08:27 -0230 Subject: Correctly set latest submitted retry with nonces that matches others in old-ui transaction-list-item. --- old-ui/app/components/transaction-list-item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index 3881d8c1c..61db8b350 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -34,7 +34,7 @@ TransactionListItem.prototype.showRetryButton = function () { const currentNonce = txParams.nonce const currentNonceTxs = transactions.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') - const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1] + const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[0] const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transaction.id -- cgit v1.2.3 From bf3c5add08baf905a4fd723fdc2b5c59342cc597 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 22:17:08 -0230 Subject: Adds styles for dropped txs in old-ui. --- old-ui/app/components/transaction-list-item.js | 5 +++++ old-ui/app/css/index.css | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/old-ui/app/components/transaction-list-item.js b/old-ui/app/components/transaction-list-item.js index 61db8b350..7ab3414e5 100644 --- a/old-ui/app/components/transaction-list-item.js +++ b/old-ui/app/components/transaction-list-item.js @@ -208,6 +208,11 @@ function formatDate (date) { function renderErrorOrWarning (transaction) { const { status, err, warning } = transaction + // show dropped + if (status === 'dropped') { + return h('span.dropped', ' (Dropped)') + } + // show rejected if (status === 'rejected') { return h('span.error', ' (Rejected)') diff --git a/old-ui/app/css/index.css b/old-ui/app/css/index.css index 67c327f62..7af713336 100644 --- a/old-ui/app/css/index.css +++ b/old-ui/app/css/index.css @@ -247,6 +247,10 @@ app sections color: #FFAE00; } +.dropped { + color: #6195ED; +} + .lock { width: 50px; height: 50px; -- cgit v1.2.3 From 0d33aed20e3f3eea68e7d0cb41fbfb0d80415000 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 23:29:47 -0230 Subject: Fix tx-list-item submitted check. --- ui/app/components/tx-list-item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index ebf5db19f..b7f7c5ab4 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -185,7 +185,7 @@ TxListItem.prototype.showRetryButton = function () { } = this.props const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) - const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => transactionStatus === 'submitted') + const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') const lastSubmittedTxWithCurrentNonce = currentNonceSubmittedTxs[currentNonceSubmittedTxs.length - 1] const currentTxIsLatestWithNonce = lastSubmittedTxWithCurrentNonce && lastSubmittedTxWithCurrentNonce.id === transactionId -- cgit v1.2.3 From e94a14ef8aee8a80a4d21ed8cb1d5b680296eb0b Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 23:44:05 -0230 Subject: Make token confirmations compatible. --- ui/app/components/pending-tx/confirm-send-token.js | 85 +++++++++++++++++++--- ui/app/components/tx-list-item.js | 17 ++++- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index e4b0c186a..4ce6a7bc3 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -8,6 +8,7 @@ abiDecoder.addABI(tokenAbi) const actions = require('../../actions') const clone = require('clone') const Identicon = require('../identicon') +const GasFeeDisplay = require('../send/gas-fee-display-v2.js') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const { @@ -88,6 +89,42 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showSendTokenPage()) }, + showCustomizeGasModal: (txMeta, sendGasLimit, sendGasPrice, sendGasTotal) => { + const { id, txParams, lastGasPrice } = txMeta + const { gas: txGasLimit, gasPrice: txGasPrice } = txParams + const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) + const { params = [] } = tokenData + const { value: to } = params[0] || {} + const { value: tokenAmountInDec } = params[1] || {} + const tokenAmountInHex = conversionUtil(tokenAmountInDec, { + fromNumericBase: 'dec', + toNumericBase: 'hex', + }) + + let forceGasMin + let nonce + if (lastGasPrice) { + const stripped = ethUtil.stripHexPrefix(lastGasPrice) + forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(stripped, 1.1, { + multiplicandBase: 16, + multiplierBase: 10, + toNumericBase: 'hex', + fromDenomination: 'WEI', + toDenomination: 'GWEI', + })) + } + + dispatch(actions.updateSend({ + gasLimit: sendGasLimit || txGasLimit, + gasPrice: sendGasPrice || txGasPrice, + editingTransactionId: id, + gasTotal: sendGasTotal, + to, + amount: tokenAmountInHex, + forceGasMin, + })) + dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) + }, } } @@ -187,6 +224,7 @@ ConfirmSendToken.prototype.getGasFee = function () { token: tokenExchangeRate ? tokenGas : null, + gasFeeInHex: gasTotal.toString(16), } } @@ -239,19 +277,31 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { } ConfirmSendToken.prototype.renderGasFee = function () { - const { token: { symbol }, currentCurrency } = this.props - const { fiat: fiatGas, token: tokenGas, eth: ethGas } = this.getGasFee() + const { + token: { symbol }, + currentCurrency: convertedCurrency, + conversionRate, + send: { gasTotal, gasLimit: sendGasLimit, gasPrice: sendGasPrice }, + showCustomizeGasModal, + } = this.props + const txMeta = this.gatherTxMeta() + const { + fiat: fiatGas, + token: tokenGas, + eth: ethGas, + gasFeeInHex + } = this.getGasFee() return ( h('section.flex-row.flex-center.confirm-screen-row', [ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `${fiatGas} ${currentCurrency}`), - - h( - 'div.confirm-screen-row-detail', - tokenGas ? `${tokenGas} ${symbol}` : `${ethGas} ETH` - ), + h(GasFeeDisplay, { + gasTotal: gasTotal || gasFeeInHex, + conversionRate, + convertedCurrency, + onClick: () => showCustomizeGasModal(txMeta, sendGasLimit, sendGasPrice, gasTotal), + }), ]), ]) ) @@ -307,16 +357,21 @@ ConfirmSendToken.prototype.render = function () { this.inputs = [] + const title = txMeta.lastGasPrice ? 'Reprice Transaction' : 'Confirm' + const subtitle = txMeta.lastGasPrice + ? 'Increase your gas fee to attempt to overwrite and speed up your transaction' + : 'Please review your transaction.' + return ( h('div.confirm-screen-container.confirm-send-token', [ // Main Send token Card h('div.page-container', [ h('div.page-container__header', [ - h('button.confirm-screen-back-button', { + !txMeta.lastGasPrice && h('button.confirm-screen-back-button', { onClick: () => editTransaction(txMeta), }, 'Edit'), - h('div.page-container__title', 'Confirm'), - h('div.page-container__subtitle', `Please review your transaction.`), + h('div.page-container__title', title), + h('div.page-container__subtitle', subtitle), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ @@ -438,6 +493,14 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) + if (txData.lastGasPrice) { + const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send + const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams + + txData.txParams.gasPrice = sendGasPrice || txGasPrice + txData.txParams.gas = sendGasLimit || txGasLimit + } + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index b7f7c5ab4..0b826e909 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -28,6 +28,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { + setSelectedToken: tokenAddress => dispatch(actions.setSelectedToken(tokenAddress)), retryTransaction: transactionId => dispatch(actions.retryTransaction(transactionId)), } } @@ -39,6 +40,7 @@ function TxListItem () { this.state = { total: null, fiatTotal: null, + isTokenTx: null, } } @@ -47,12 +49,13 @@ TxListItem.prototype.componentDidMount = async function () { const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { name: txDataName } = decodedData || {} + const isTokenTx = txDataName === 'transfer' - const { total, fiatTotal } = txDataName === 'transfer' + const { total, fiatTotal } = isTokenTx ? await this.getSendTokenTotal() : this.getSendEtherTotal() - this.setState({ total, fiatTotal }) + this.setState({ total, fiatTotal, isTokenTx }) } TxListItem.prototype.getAddressText = function () { @@ -193,6 +196,10 @@ TxListItem.prototype.showRetryButton = function () { return currentTxIsLatestWithNonce && Date.now() - transactionSubmittedTime > 30000 } +TxListItem.prototype.setSelectedToken = function (tokenAddress) { + this.props.setSelectedToken(tokenAddress) +} + TxListItem.prototype.resubmit = function () { const { transactionId } = this.props this.props.retryTransaction(transactionId) @@ -207,8 +214,9 @@ TxListItem.prototype.render = function () { dateString, address, className, + txParams, } = this.props - const { total, fiatTotal } = this.state + const { total, fiatTotal, isTokenTx } = this.state const showFiatTotal = transactionAmount !== '0x0' && fiatTotal return h(`div${className || ''}`, { @@ -280,6 +288,9 @@ TxListItem.prototype.render = function () { h('span.tx-list-item-retry-link', { onClick: (event) => { event.stopPropagation() + if (isTokenTx) { + this.setSelectedToken(txParams.to) + } this.resubmit() }, }, 'Increase the gas price on your transaction'), -- cgit v1.2.3 From c37684d7bde00adcb4b2e43db16be91978e2ef12 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 23:49:10 -0230 Subject: Remove unnecessary addition of nonce to state. --- ui/app/components/pending-tx/confirm-send-ether.js | 3 --- ui/app/reducers/metamask.js | 2 -- ui/app/send-v2.js | 5 ----- 3 files changed, 10 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 8fe58482b..f3f7e86c5 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -76,8 +76,6 @@ function mapDispatchToProps (dispatch) { fromDenomination: 'WEI', toDenomination: 'GWEI', })) - - nonce = txParams.nonce } dispatch(actions.updateSend({ @@ -86,7 +84,6 @@ function mapDispatchToProps (dispatch) { editingTransactionId: id, gasTotal: sendGasTotal, forceGasMin, - nonce, })) dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) }, diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index b27e7140a..2c93172cc 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -39,7 +39,6 @@ function reduceMetamask (state, action) { maxModeOn: false, editingTransactionId: null, forceGasMin: null, - nonce: null, }, coinOptions: {}, useBlockie: false, @@ -299,7 +298,6 @@ function reduceMetamask (state, action) { errors: {}, editingTransactionId: null, forceGasMin: null, - nonce: null, }, }) diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 697dfc517..fc1df1f51 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -548,7 +548,6 @@ SendTransactionScreen.prototype.getEditedTx = function () { selectedToken, editingTransactionId, unapprovedTxs, - nonce, } = this.props const editingTx = { @@ -560,10 +559,6 @@ SendTransactionScreen.prototype.getEditedTx = function () { }, } - if (nonce) { - editingTx.txParams.nonce = ethUtil.addHexPrefix(nonce) - } - if (selectedToken) { const data = TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), -- cgit v1.2.3 From cc267d6c818c83b0384b569733d05efef384ac3e Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 13 Mar 2018 23:56:45 -0230 Subject: Fix more lint errors. --- ui/app/components/pending-tx/confirm-send-ether.js | 1 - ui/app/components/pending-tx/confirm-send-token.js | 9 +-------- ui/app/components/tx-list-item.js | 3 +-- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index f3f7e86c5..4666e047d 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -66,7 +66,6 @@ function mapDispatchToProps (dispatch) { const { gas: txGasLimit, gasPrice: txGasPrice } = txParams let forceGasMin - let nonce if (lastGasPrice) { const stripped = ethUtil.stripHexPrefix(lastGasPrice) forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(stripped, 1.1, { diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 4ce6a7bc3..476c1d259 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -102,7 +102,6 @@ function mapDispatchToProps (dispatch, ownProps) { }) let forceGasMin - let nonce if (lastGasPrice) { const stripped = ethUtil.stripHexPrefix(lastGasPrice) forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(stripped, 1.1, { @@ -278,19 +277,13 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { ConfirmSendToken.prototype.renderGasFee = function () { const { - token: { symbol }, currentCurrency: convertedCurrency, conversionRate, send: { gasTotal, gasLimit: sendGasLimit, gasPrice: sendGasPrice }, showCustomizeGasModal, } = this.props const txMeta = this.gatherTxMeta() - const { - fiat: fiatGas, - token: tokenGas, - eth: ethGas, - gasFeeInHex - } = this.getGasFee() + const { gasFeeInHex } = this.getGasFee() return ( h('section.flex-row.flex-center.confirm-screen-row', [ diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 0b826e909..4c2b77af9 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -55,7 +55,7 @@ TxListItem.prototype.componentDidMount = async function () { ? await this.getSendTokenTotal() : this.getSendEtherTotal() - this.setState({ total, fiatTotal, isTokenTx }) + this.setState({ total, fiatTotal, isTokenTx }) } TxListItem.prototype.getAddressText = function () { @@ -180,7 +180,6 @@ TxListItem.prototype.getSendTokenTotal = async function () { TxListItem.prototype.showRetryButton = function () { const { - transactionStatus, transactionSubmittedTime, selectedAddressTxList, transactionId, -- cgit v1.2.3 From 106ce091a9ef9fbd37b90c49bc76f12bd796ebb5 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 14 Mar 2018 11:45:04 -0230 Subject: Fix TransactionStateManager spelling. --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index ab07dde62..3e3909361 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -3,7 +3,7 @@ const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') const EthQuery = require('ethjs-query') -const TransactionStateManger = require('../lib/tx-state-manager') +const TransactionStateManager = require('../lib/tx-state-manager') const TxGasUtil = require('../lib/tx-gas-utils') const PendingTransactionTracker = require('../lib/pending-tx-tracker') const NonceTracker = require('../lib/nonce-tracker') @@ -37,7 +37,7 @@ module.exports = class TransactionController extends EventEmitter { this.query = new EthQuery(this.provider) this.txGasUtil = new TxGasUtil(this.provider) - this.txStateManager = new TransactionStateManger({ + this.txStateManager = new TransactionStateManager({ initState: opts.initState, txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), -- cgit v1.2.3 From f8e13fd793c5761c4c077b912934f8cbc434b13c Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 14 Mar 2018 12:28:26 -0230 Subject: Fix tests. --- development/states/confirm-new-ui.json | 2 +- development/states/send-edit.json | 2 +- test/integration/lib/send-new-ui.js | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/development/states/confirm-new-ui.json b/development/states/confirm-new-ui.json index 6ea8e64cd..6981781a9 100644 --- a/development/states/confirm-new-ui.json +++ b/development/states/confirm-new-ui.json @@ -116,7 +116,7 @@ "send": { "gasLimit": "0xea60", "gasPrice": "0xba43b7400", - "gasTotal": "0xb451dc41b578", + "gasTotal": "0xaa87bee538000", "tokenBalance": null, "from": { "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", diff --git a/development/states/send-edit.json b/development/states/send-edit.json index 6ea8e64cd..6981781a9 100644 --- a/development/states/send-edit.json +++ b/development/states/send-edit.json @@ -116,7 +116,7 @@ "send": { "gasLimit": "0xea60", "gasPrice": "0xba43b7400", - "gasTotal": "0xb451dc41b578", + "gasTotal": "0xaa87bee538000", "tokenBalance": null, "from": { "address": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb", diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index faab10fdf..bfd17f3d8 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -93,7 +93,7 @@ async function runSendFlowTest(assert, done) { 'send gas field should show estimated gas total converted to USD' ) - const sendGasOpenCustomizeModalButton = await queryAsync($, '.send-v2__sliders-icon-container') + const sendGasOpenCustomizeModalButton = await queryAsync($, '.sliders-icon-container') sendGasOpenCustomizeModalButton[0].click() const customizeGasModal = await queryAsync($, '.send-v2__customize-gas') @@ -135,9 +135,9 @@ async function runSendFlowTest(assert, done) { assert.equal(confirmToName[0].textContent, 'Send Account 3', 'confirm screen should show correct to name') const confirmScreenRows = await queryAsync($, '.confirm-screen-rows') - const confirmScreenGas = confirmScreenRows.find('.confirm-screen-row-info')[2] - assert.equal(confirmScreenGas.textContent, '3.6 USD', 'confirm screen should show correct gas') - const confirmScreenTotal = confirmScreenRows.find('.confirm-screen-row-info')[3] + const confirmScreenGas = confirmScreenRows.find('.currency-display__converted-value')[0] + assert.equal(confirmScreenGas.textContent, '3.60 USD', 'confirm screen should show correct gas') + const confirmScreenTotal = confirmScreenRows.find('.confirm-screen-row-info')[2] assert.equal(confirmScreenTotal.textContent, '2405.36 USD', 'confirm screen should show correct total') const confirmScreenBackButton = await queryAsync($, '.confirm-screen-back-button') -- cgit v1.2.3 From bc987a1129194c0c79cde9d73557a98a22aa4e40 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 14 Mar 2018 08:20:54 -0700 Subject: fix destructuring of variables --- app/scripts/lib/local-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 781aea17e..1cf00dd30 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -3,7 +3,7 @@ // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/local const extension = require('extensionizer') -const { promisify } = require('util').promisify +const { promisify } = require('util') module.exports = class ExtensionStore { constructor() { -- cgit v1.2.3 From fb838da7340d460650750cb8ea5fa3fb6fe319de Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 14 Mar 2018 17:07:09 -0230 Subject: Revert 'Set txMeta.time to reflect time of tx approval.' --- ui/app/components/pending-tx/confirm-send-ether.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 6624a378d..9b9a4e4ea 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -454,7 +454,7 @@ ConfirmSendEther.prototype.render = function () { ConfirmSendEther.prototype.onSubmit = function (event) { event.preventDefault() - const txMeta = this.gatherTxMeta({ time: (new Date()).getTime() }) + const txMeta = this.gatherTxMeta() const valid = this.checkValidity() this.setState({ valid, submitting: true }) @@ -489,7 +489,7 @@ ConfirmSendEther.prototype.getFormEl = function () { } // After a customizable state value has been updated, -ConfirmSendEther.prototype.gatherTxMeta = function (opts) { +ConfirmSendEther.prototype.gatherTxMeta = function () { const props = this.props const state = this.state const txData = clone(state.txData) || clone(props.txData) @@ -503,7 +503,7 @@ ConfirmSendEther.prototype.gatherTxMeta = function (opts) { } // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) - return Object.assign(txData, opts) + return txData } ConfirmSendEther.prototype.verifyGasParams = function () { -- cgit v1.2.3 From a4c6a5e92e09b70db2e9ab92a8123176de127910 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 14 Mar 2018 17:10:59 -0230 Subject: Ensure changes from customize gas modal opened from confirm screen are captured for non-tx transactions. --- ui/app/components/pending-tx/confirm-send-ether.js | 10 ++++------ ui/app/components/pending-tx/confirm-send-token.js | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 9b9a4e4ea..928149ccd 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -494,13 +494,11 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - if (txData.lastGasPrice) { - const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send - const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams + const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send + const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams - txData.txParams.gasPrice = sendGasPrice || txGasPrice - txData.txParams.gas = sendGasLimit || txGasLimit - } + txData.txParams.gasPrice = sendGasPrice || txGasPrice + txData.txParams.gas = sendGasLimit || txGasLimit // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index ac773b1d2..fe323ffd3 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -487,13 +487,11 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - if (txData.lastGasPrice) { - const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send - const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams + const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send + const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams - txData.txParams.gasPrice = sendGasPrice || txGasPrice - txData.txParams.gas = sendGasLimit || txGasLimit - } + txData.txParams.gasPrice = sendGasPrice || txGasPrice + txData.txParams.gas = sendGasLimit || txGasLimit // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData -- cgit v1.2.3 From 66422cd083e86582b44d19664e6c6fc95bdb8ce5 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 14 Mar 2018 18:50:18 -0230 Subject: Force gas min has correct precision and is set when editing gas if max. --- ui/app/components/customize-gas-modal/index.js | 7 ++++++- ui/app/components/pending-tx/confirm-send-ether.js | 4 +--- ui/app/components/pending-tx/confirm-send-token.js | 4 +--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 291447bb4..d8384c19d 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -233,6 +233,7 @@ CustomizeGasModal.prototype.render = function () { convertedGasPrice += convertedGasPrice.match(/[.]/) ? priceSigZeros : `${priceSigDec}${priceSigZeros}` + let newGasPrice = gasPrice if (forceGasMin) { const convertedMinPrice = conversionUtil(forceGasMin, { fromNumericBase: 'hex', @@ -242,6 +243,10 @@ CustomizeGasModal.prototype.render = function () { { value: convertedMinPrice, fromNumericBase: 'dec' }, { value: convertedGasPrice, fromNumericBase: 'dec' } ) + newGasPrice = conversionMax( + { value: gasPrice, fromNumericBase: 'hex' }, + { value: forceGasMin, fromNumericBase: 'hex' } + ) } const convertedGasLimit = conversionUtil(gasLimit, { @@ -302,7 +307,7 @@ CustomizeGasModal.prototype.render = function () { }, [t('cancel')]), h(`div.send-v2__customize-gas__save${error ? '__error' : ''}.allcaps`, { - onClick: () => !error && this.save(gasPrice, gasLimit, gasTotal), + onClick: () => !error && this.save(newGasPrice, gasLimit, gasTotal), }, [t('save')]), ]), diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 928149ccd..dca39f0a5 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -68,13 +68,11 @@ function mapDispatchToProps (dispatch) { let forceGasMin if (lastGasPrice) { - const stripped = ethUtil.stripHexPrefix(lastGasPrice) - forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(stripped, 1.1, { + forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice, 1.1, { multiplicandBase: 16, multiplierBase: 10, toNumericBase: 'hex', fromDenomination: 'WEI', - toDenomination: 'GWEI', })) } diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index fe323ffd3..6035dd801 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -104,13 +104,11 @@ function mapDispatchToProps (dispatch, ownProps) { let forceGasMin if (lastGasPrice) { - const stripped = ethUtil.stripHexPrefix(lastGasPrice) - forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(stripped, 1.1, { + forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice, 1.1, { multiplicandBase: 16, multiplierBase: 10, toNumericBase: 'hex', fromDenomination: 'WEI', - toDenomination: 'GWEI', })) } -- cgit v1.2.3 From b0122be3c960b68620c5769ca969db60e4a45351 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 14 Mar 2018 19:03:14 -0230 Subject: Set retry gasPrice to forceGasMin on confirm screen in cases where gas is not edited. --- ui/app/components/pending-tx/confirm-send-ether.js | 19 +++++++++++++++++-- ui/app/components/pending-tx/confirm-send-token.js | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index dca39f0a5..a4763eab7 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -493,9 +493,24 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { const txData = clone(state.txData) || clone(props.txData) const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send - const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams + const { + lastGasPrice, + txParams: { + gasPrice: txGasPrice, + gas: txGasLimit, + }, + } = txData + + let forceGasMin + if (lastGasPrice) { + forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice, 1.1, { + multiplicandBase: 16, + multiplierBase: 10, + toNumericBase: 'hex', + })) + } - txData.txParams.gasPrice = sendGasPrice || txGasPrice + txData.txParams.gasPrice = sendGasPrice || forceGasMin || txGasPrice txData.txParams.gas = sendGasLimit || txGasLimit // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 6035dd801..f1142b142 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -486,9 +486,24 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const txData = clone(state.txData) || clone(props.txData) const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send - const { gasPrice: txGasPrice, gas: txGasLimit } = txData.txParams + const { + lastGasPrice, + txParams: { + gasPrice: txGasPrice, + gas: txGasLimit, + }, + } = txData + + let forceGasMin + if (lastGasPrice) { + forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice, 1.1, { + multiplicandBase: 16, + multiplierBase: 10, + toNumericBase: 'hex', + })) + } - txData.txParams.gasPrice = sendGasPrice || txGasPrice + txData.txParams.gasPrice = sendGasPrice || forceGasMin || txGasPrice txData.txParams.gas = sendGasLimit || txGasLimit // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) -- cgit v1.2.3 From 74e9a5c49103709f02d3b123ce7e957bcea172c7 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 15 Mar 2018 10:41:25 -0700 Subject: add to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7d4a09fe..75ba7670f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Current Master +- MetaMask will no longer allow nonces to be specified by the dapp - Add ability for internationalization. - Will now throw an error if the `to` field in txParams is not valid. - Will strip null values from the `to` field. -- cgit v1.2.3