Merge remote-tracking branch 'origin/master' into AddTokenList

feature/default_network_editable
Dan Finlay 8 years ago
commit 39c7ed230d
  1. 2
      CHANGELOG.md
  2. 15
      app/scripts/controllers/transactions.js
  3. 5
      test/unit/tx-controller-test.js
  4. 3
      ui/app/accounts/import/json.js
  5. 22
      ui/app/components/ens-input.js

@ -3,6 +3,7 @@
## Current Master ## Current Master
- Add list of popular tokens held to the account detail view. - Add list of popular tokens held to the account detail view.
- Add a warning to JSON file import.
## 3.7.8 2017-6-12 ## 3.7.8 2017-6-12
@ -10,6 +11,7 @@
- The default network on installation is now MainNet - The default network on installation is now MainNet
- Fix currency API URL from cryptonator. - Fix currency API URL from cryptonator.
- Update gasLimit params with every new block seen. - Update gasLimit params with every new block seen.
- Fix ENS resolver symbol UI.
## 3.7.7 2017-6-8 ## 3.7.7 2017-6-8

@ -9,7 +9,6 @@ const createId = require('../lib/random-id')
const denodeify = require('denodeify') const denodeify = require('denodeify')
const RETRY_LIMIT = 200 const RETRY_LIMIT = 200
const RESUBMIT_INTERVAL = 10000 // Ten seconds
module.exports = class TransactionController extends EventEmitter { module.exports = class TransactionController extends EventEmitter {
constructor (opts) { constructor (opts) {
@ -26,6 +25,7 @@ module.exports = class TransactionController extends EventEmitter {
this.query = opts.ethQuery this.query = opts.ethQuery
this.txProviderUtils = new TxProviderUtil(this.query) this.txProviderUtils = new TxProviderUtil(this.query)
this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) this.blockTracker.on('block', this.checkForTxInBlock.bind(this))
this.blockTracker.on('block', this.resubmitPendingTxs.bind(this))
this.signEthTx = opts.signTransaction this.signEthTx = opts.signTransaction
this.nonceLock = Semaphore(1) this.nonceLock = Semaphore(1)
@ -34,8 +34,6 @@ module.exports = class TransactionController extends EventEmitter {
this.store.subscribe(() => this._updateMemstore()) this.store.subscribe(() => this._updateMemstore())
this.networkStore.subscribe(() => this._updateMemstore()) this.networkStore.subscribe(() => this._updateMemstore())
this.preferencesStore.subscribe(() => this._updateMemstore()) this.preferencesStore.subscribe(() => this._updateMemstore())
this.continuallyResubmitPendingTxs()
} }
getState () { getState () {
@ -212,7 +210,7 @@ module.exports = class TransactionController extends EventEmitter {
getChainId () { getChainId () {
const networkState = this.networkStore.getState() const networkState = this.networkStore.getState()
const getChainId = parseInt(networkState.network) const getChainId = parseInt(networkState)
if (Number.isNaN(getChainId)) { if (Number.isNaN(getChainId)) {
return 0 return 0
} else { } else {
@ -409,18 +407,15 @@ module.exports = class TransactionController extends EventEmitter {
this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) this.memStore.updateState({ unapprovedTxs, selectedAddressTxList })
} }
continuallyResubmitPendingTxs () { resubmitPendingTxs () {
const pending = this.getTxsByMetaData('status', 'submitted') const pending = this.getTxsByMetaData('status', 'submitted')
// only try resubmitting if their are transactions to resubmit
if (!pending.length) return
const resubmit = denodeify(this.resubmitTx.bind(this)) const resubmit = denodeify(this.resubmitTx.bind(this))
Promise.all(pending.map(txMeta => resubmit(txMeta))) Promise.all(pending.map(txMeta => resubmit(txMeta)))
.catch((reason) => { .catch((reason) => {
log.info('Problem resubmitting tx', reason) log.info('Problem resubmitting tx', reason)
}) })
.then(() => {
global.setTimeout(() => {
this.continuallyResubmitPendingTxs()
}, RESUBMIT_INTERVAL)
})
} }
resubmitTx (txMeta, cb) { resubmitTx (txMeta, cb) {

@ -311,12 +311,13 @@ describe('Transaction Controller', function () {
}) })
describe('#sign replay-protected tx', function () { describe('#sign replay-protected tx', function () {
it('prepares a tx with the chainId set', function () { it('prepares a tx with the chainId set', function (done) {
txController.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop) txController.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} }, noop)
txController.signTransaction('1', (err, rawTx) => { txController.signTransaction('1', (err, rawTx) => {
if (err) return assert.fail('it should not fail') if (err) return done('it should not fail')
const ethTx = new EthTx(ethUtil.toBuffer(rawTx)) const ethTx = new EthTx(ethUtil.toBuffer(rawTx))
assert.equal(ethTx.getChainId(), currentNetworkId) assert.equal(ethTx.getChainId(), currentNetworkId)
done()
}) })
}) })
}) })

@ -5,6 +5,8 @@ const connect = require('react-redux').connect
const actions = require('../../actions') const actions = require('../../actions')
const FileInput = require('react-simple-file-input').default const FileInput = require('react-simple-file-input').default
const HELP_LINK = 'https://github.com/MetaMask/faq/blob/master/README.md#q-i-cant-use-the-import-feature-for-uploading-a-json-file-the-window-keeps-closing-when-i-try-to-select-a-file'
module.exports = connect(mapStateToProps)(JsonImportSubview) module.exports = connect(mapStateToProps)(JsonImportSubview)
function mapStateToProps (state) { function mapStateToProps (state) {
@ -32,6 +34,7 @@ JsonImportSubview.prototype.render = function () {
}, [ }, [
h('p', 'Used by a variety of different clients'), h('p', 'Used by a variety of different clients'),
h('a.warning', { href: HELP_LINK, target: '_blank' }, 'File import not working? Click here!'),
h(FileInput, { h(FileInput, {
readAs: 'text', readAs: 'text',

@ -7,6 +7,7 @@ const copyToClipboard = require('copy-to-clipboard')
const ENS = require('ethjs-ens') const ENS = require('ethjs-ens')
const networkMap = require('ethjs-ens/lib/network-map.json') const networkMap = require('ethjs-ens/lib/network-map.json')
const ensRE = /.+\.eth$/ const ensRE = /.+\.eth$/
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
module.exports = EnsInput module.exports = EnsInput
@ -21,7 +22,6 @@ EnsInput.prototype.render = function () {
const opts = extend(props, { const opts = extend(props, {
list: 'addresses', list: 'addresses',
onChange: () => { onChange: () => {
this.setState({ ensResolution: '0x0000000000000000000000000000000000000000' })
const network = this.props.network const network = this.props.network
const networkHasEnsSupport = getNetworkEnsSupport(network) const networkHasEnsSupport = getNetworkEnsSupport(network)
if (!networkHasEnsSupport) return if (!networkHasEnsSupport) return
@ -73,6 +73,7 @@ EnsInput.prototype.render = function () {
EnsInput.prototype.componentDidMount = function () { EnsInput.prototype.componentDidMount = function () {
const network = this.props.network const network = this.props.network
const networkHasEnsSupport = getNetworkEnsSupport(network) const networkHasEnsSupport = getNetworkEnsSupport(network)
this.setState({ ensResolution: ZERO_ADDRESS })
if (networkHasEnsSupport) { if (networkHasEnsSupport) {
const provider = global.ethereumProvider const provider = global.ethereumProvider
@ -85,18 +86,10 @@ EnsInput.prototype.lookupEnsName = function () {
const recipient = document.querySelector('input[name="address"]').value const recipient = document.querySelector('input[name="address"]').value
const { ensResolution } = this.state const { ensResolution } = this.state
if (!this.ens) {
return this.setState({
loadingEns: false,
ensFailure: true,
hoverText: 'ENS is not supported on your current network.',
})
}
log.info(`ENS attempting to resolve name: ${recipient}`) log.info(`ENS attempting to resolve name: ${recipient}`)
this.ens.lookup(recipient.trim()) this.ens.lookup(recipient.trim())
.then((address) => { .then((address) => {
if (address === '0x0000000000000000000000000000000000000000') throw new Error('No address has been set for this name.') if (address === ZERO_ADDRESS) throw new Error('No address has been set for this name.')
if (address !== ensResolution) { if (address !== ensResolution) {
this.setState({ this.setState({
loadingEns: false, loadingEns: false,
@ -111,7 +104,7 @@ EnsInput.prototype.lookupEnsName = function () {
log.error(reason) log.error(reason)
return this.setState({ return this.setState({
loadingEns: false, loadingEns: false,
ensResolution: '0x0000000000000000000000000000000000000000', ensResolution: ZERO_ADDRESS,
ensFailure: true, ensFailure: true,
hoverText: reason.message, hoverText: reason.message,
}) })
@ -124,7 +117,7 @@ EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
// If an address is sent without a nickname, meaning not from ENS or from // If an address is sent without a nickname, meaning not from ENS or from
// the user's own accounts, a default of a one-space string is used. // the user's own accounts, a default of a one-space string is used.
const nickname = state.nickname || ' ' const nickname = state.nickname || ' '
if (ensResolution && this.props.onChange && if (prevState && ensResolution && this.props.onChange &&
ensResolution !== prevState.ensResolution) { ensResolution !== prevState.ensResolution) {
this.props.onChange(ensResolution, nickname) this.props.onChange(ensResolution, nickname)
} }
@ -143,7 +136,7 @@ EnsInput.prototype.ensIcon = function (recipient) {
} }
EnsInput.prototype.ensIconContents = function (recipient) { EnsInput.prototype.ensIconContents = function (recipient) {
const { loadingEns, ensFailure, ensResolution } = this.state || {} const { loadingEns, ensFailure, ensResolution } = this.state || { ensResolution: ZERO_ADDRESS}
if (loadingEns) { if (loadingEns) {
return h('img', { return h('img', {
@ -160,7 +153,7 @@ EnsInput.prototype.ensIconContents = function (recipient) {
return h('i.fa.fa-warning.fa-lg.warning') return h('i.fa.fa-warning.fa-lg.warning')
} }
if (ensResolution) { if (ensResolution && (ensResolution !== ZERO_ADDRESS)) {
return h('i.fa.fa-check-circle.fa-lg.cursor-pointer', { return h('i.fa.fa-check-circle.fa-lg.cursor-pointer', {
style: { color: 'green' }, style: { color: 'green' },
onClick: (event) => { onClick: (event) => {
@ -175,4 +168,3 @@ EnsInput.prototype.ensIconContents = function (recipient) {
function getNetworkEnsSupport (network) { function getNetworkEnsSupport (network) {
return Boolean(networkMap[network]) return Boolean(networkMap[network])
} }

Loading…
Cancel
Save