diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | app/scripts/keyring-controller.js | 3 | ||||
-rw-r--r-- | test/unit/nonce-tracker-test.js | 19 | ||||
-rw-r--r-- | ui/app/add-token.js | 31 | ||||
-rw-r--r-- | ui/app/app.js | 3 | ||||
-rw-r--r-- | ui/app/components/account-dropdowns.js | 21 | ||||
-rw-r--r-- | ui/app/components/dropdown.js | 2 | ||||
-rw-r--r-- | ui/app/css/lib.css | 5 | ||||
-rw-r--r-- | ui/app/unlock.js | 2 |
9 files changed, 77 insertions, 12 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d528d253..a58180da9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## Current Master +- Readded loose keyring label back into the account list. +- Add info on token contract addresses. +- Add validation preventing users from inputting their own addresses as token tracking addresses. ## 3.9.13 2017-9-8 diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 2edc8060e..fd57fac70 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -171,9 +171,9 @@ class KeyringController extends EventEmitter { return this.setupAccounts(checkedAccounts) }) .then(() => this.persistAllKeyrings()) + .then(() => this._updateMemStoreKeyrings()) .then(() => this.fullUpdate()) .then(() => { - this._updateMemStoreKeyrings() return keyring }) } @@ -208,6 +208,7 @@ class KeyringController extends EventEmitter { return selectedKeyring.addAccounts(1) .then(this.setupAccounts.bind(this)) .then(this.persistAllKeyrings.bind(this)) + .then(this._updateMemStoreKeyrings.bind(this)) .then(this.fullUpdate.bind(this)) } diff --git a/test/unit/nonce-tracker-test.js b/test/unit/nonce-tracker-test.js index 3312a3bd0..8970cf84d 100644 --- a/test/unit/nonce-tracker-test.js +++ b/test/unit/nonce-tracker-test.js @@ -162,6 +162,25 @@ describe('Nonce Tracker', function () { await nonceLock.releaseLock() }) }) + + describe('Faq issue 67', function () { + beforeEach(function () { + const txGen = new MockTxGen() + const confirmedTxs = txGen.generate({ status: 'confirmed' }, { count: 64 }) + const pendingTxs = txGen.generate({ + status: 'submitted', + }, { count: 10 }) + // 0x40 is 64 in hex: + nonceTracker = generateNonceTrackerWith(pendingTxs, [], '0x40') + }) + + it('should return nonce after network nonce', async function () { + this.timeout(15000) + const nonceLock = await nonceTracker.getNonceLock('0x7d3517b0d011698406d6e0aed8453f0be2697926') + assert.equal(nonceLock.nextNonce, '74', `nonce should be 74 got ${nonceLock.nextNonce}`) + await nonceLock.releaseLock() + }) + }) }) }) diff --git a/ui/app/add-token.js b/ui/app/add-token.js index 15ef7a852..18adc7eb5 100644 --- a/ui/app/add-token.js +++ b/ui/app/add-token.js @@ -3,6 +3,8 @@ const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('./actions') +const Tooltip = require('./components/tooltip.js') + const ethUtil = require('ethereumjs-util') const abi = require('human-standard-token-abi') @@ -15,6 +17,7 @@ module.exports = connect(mapStateToProps)(AddTokenScreen) function mapStateToProps (state) { return { + identities: state.metamask.identities, } } @@ -64,15 +67,25 @@ AddTokenScreen.prototype.render = function () { }, [ h('div', [ - h('span', { - style: { fontWeight: 'bold', paddingRight: '10px'}, - }, 'Token Address'), + h(Tooltip, { + position: 'top', + title: 'The contract of the actual token contract. Click for more info.', + }, [ + h('a', { + style: { fontWeight: 'bold', paddingRight: '10px'}, + href: 'https://consensyssupport.happyfox.com/staff/kb/article/24-what-is-a-token-contract-address', + target: '_blank', + }, [ + h('span', 'Token Contract Address '), + h('i.fa.fa-question-circle'), + ]), + ]), ]), h('section.flex-row.flex-center', [ h('input#token-address', { name: 'address', - placeholder: 'Token Address', + placeholder: 'Token Contract Address', onChange: this.tokenAddressDidChange.bind(this), style: { width: 'inherit', @@ -171,7 +184,9 @@ AddTokenScreen.prototype.tokenAddressDidChange = function (event) { AddTokenScreen.prototype.validateInputs = function () { let msg = '' const state = this.state + const identitiesList = Object.keys(this.props.identities) const { address, symbol, decimals } = state + const standardAddress = ethUtil.addHexPrefix(address).toLowerCase() const validAddress = ethUtil.isValidAddress(address) if (!validAddress) { @@ -189,7 +204,12 @@ AddTokenScreen.prototype.validateInputs = function () { msg += 'Symbol must be between 0 and 10 characters.' } - const isValid = validAddress && validDecimals + const ownAddress = identitiesList.includes(standardAddress) + if (ownAddress) { + msg = 'Personal address detected. Input the token contract address.' + } + + const isValid = validAddress && validDecimals && !ownAddress if (!isValid) { this.setState({ @@ -216,4 +236,3 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) this.setState({ symbol: symbol[0], decimals: decimals[0].toString() }) } } - diff --git a/ui/app/app.js b/ui/app/app.js index 1f3d5b0f8..ee800ea90 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -42,6 +42,7 @@ function mapStateToProps (state) { identities, accounts, address, + keyrings, } = state.metamask const selected = address || Object.keys(accounts)[0] @@ -69,6 +70,7 @@ function mapStateToProps (state) { // state needed to get account dropdown temporarily rendering from app bar identities, selected, + keyrings, } } @@ -187,6 +189,7 @@ App.prototype.renderAppBar = function () { identities: this.props.identities, selected: this.props.currentView.context, network: this.props.network, + keyrings: this.props.keyrings, }, []), // hamburger diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index 7c24e70bd..b087a40d4 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -22,12 +22,19 @@ class AccountDropdowns extends Component { } renderAccounts () { - const { identities, selected } = this.props + const { identities, selected, keyrings } = this.props return Object.keys(identities).map((key, index) => { const identity = identities[key] const isSelected = identity.address === selected + const simpleAddress = identity.address.substring(2).toLowerCase() + + const keyring = keyrings.find((kr) => { + return kr.accounts.includes(simpleAddress) || + kr.accounts.includes(identity.address) + }) + return h( DropdownMenuItem, { @@ -51,6 +58,7 @@ class AccountDropdowns extends Component { }, }, ), + this.indicateIfLoose(keyring), h('span', { style: { marginLeft: '20px', @@ -67,6 +75,14 @@ class AccountDropdowns extends Component { }) } + indicateIfLoose (keyring) { + try { // Sometimes keyrings aren't loaded yet: + const type = keyring.type + const isLoose = type !== 'HD Key Tree' + return isLoose ? h('.keyring-label', 'LOOSE') : null + } catch (e) { return } + } + renderAccountSelector () { const { actions } = this.props const { accountSelectorActive } = this.state @@ -145,6 +161,8 @@ class AccountDropdowns extends Component { ) } + + renderAccountOptions () { const { actions } = this.props const { optionsMenuActive } = this.state @@ -278,6 +296,7 @@ AccountDropdowns.defaultProps = { AccountDropdowns.propTypes = { identities: PropTypes.objectOf(PropTypes.object), selected: PropTypes.string, + keyrings: PropTypes.array, } const mapDispatchToProps = (dispatch) => { diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdown.js index 34c7149ee..73710acc2 100644 --- a/ui/app/components/dropdown.js +++ b/ui/app/components/dropdown.js @@ -32,7 +32,7 @@ class Dropdown extends Component { 'style', ` li.dropdown-menu-item:hover { color:rgb(225, 225, 225); } - li.dropdown-menu-item { color: rgb(185, 185, 185); } + li.dropdown-menu-item { color: rgb(185, 185, 185); position: relative } ` ), ...children, diff --git a/ui/app/css/lib.css b/ui/app/css/lib.css index 81647d1c1..f3acbee76 100644 --- a/ui/app/css/lib.css +++ b/ui/app/css/lib.css @@ -215,12 +215,13 @@ hr.horizontal-line { z-index: 1; font-size: 11px; background: rgba(255,0,0,0.8); - bottom: -47px; color: white; + bottom: 0px; + left: -8px; border-radius: 10px; height: 20px; min-width: 20px; - position: relative; + position: absolute; display: flex; align-items: center; justify-content: center; diff --git a/ui/app/unlock.js b/ui/app/unlock.js index 9bacd5124..4180791c4 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -80,7 +80,7 @@ UnlockScreen.prototype.render = function () { color: 'rgb(247, 134, 28)', textDecoration: 'underline', }, - }, 'I forgot my password.'), + }, 'Restore from seed phrase'), ]), ]) ) |