diff --git a/CHANGELOG.md b/CHANGELOG.md index b45e18641..1cf23ccbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## Current Master +## 4.7.2 Sun Jun 03 2018 + +- Fix bug preventing users from logging in. Internally accounts and identities were out of sync. +- Fix support links to point to new support system (Zendesk) +- Fix bug in migration #26 ( moving account nicknames to preferences ) +- Clears account nicknames on restore from seedPhrase + ## 4.7.1 Fri Jun 01 2018 - Fix bug where errors were not returned to Dapps. diff --git a/README.md b/README.md index 970bd758f..70faa8856 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ If you're a web dapp developer, we've got two types of guides for you: ## Building locally - Install [Node.js](https://nodejs.org/en/) version 6.3.1 or later. - - Install local dependencies with `npm install`. + - Install dependencies: + - For node versions up to and including 9, install local dependencies with `npm install`. + - For node versions 10 and later, install [Yarn](https://yarnpkg.com/lang/en/docs/install/) and use `yarn install`. - Install gulp globally with `npm install -g gulp-cli`. - Build the project to the `./dist/` folder with `gulp build`. - Optionally, to rebuild on file changes, run `gulp dev`. diff --git a/app/manifest.json b/app/manifest.json index dbce13f7c..c1f26d2ea 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "4.7.1", + "version": "4.7.2", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index a4ff1207e..760868ddf 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -63,6 +63,13 @@ class PreferencesController { this.store.updateState({ currentLocale: key }) } + /** + * Updates identities to only include specified addresses. Removes identities + * not included in addresses array + * + * @param {string[]} addresses An array of hex addresses + * + */ setAddresses (addresses) { const oldIdentities = this.store.getState().identities const identities = addresses.reduce((ids, address, index) => { @@ -73,6 +80,24 @@ class PreferencesController { this.store.updateState({ identities }) } + /** + * Adds addresses to the identities object without removing identities + * + * @param {string[]} addresses An array of hex addresses + * + */ + addAddresses (addresses) { + const identities = this.store.getState().identities + addresses.forEach((address) => { + // skip if already exists + if (identities[address]) return + // add missing identity + const identityCount = Object.keys(identities).length + identities[address] = { name: `Account ${identityCount + 1}`, address } + }) + this.store.updateState({ identities }) + } + /** * Setter for the `selectedAddress` property * @@ -111,7 +136,7 @@ class PreferencesController { /** * Adds a new token to the token array, or updates the token if passed an address that already exists. * Modifies the existing tokens array from the store. All objects in the tokens array array AddedToken objects. - * @see AddedToken {@link AddedToken} + * @see AddedToken {@link AddedToken} * * @param {string} rawAddress Hex address of the token contract. May or may not be a checksum address. * @param {string} symbol The symbol of the token @@ -197,7 +222,7 @@ class PreferencesController { } /** - * Setter for the `currentAccountTab` property + * Setter for the `currentAccountTab` property * * @param {string} currentAccountTab Specifies the new tab to be marked as current * @returns {Promise} Promise resolves with undefined @@ -215,7 +240,7 @@ class PreferencesController { * The returned list will have a max length of 2. If the _url currently exists it the list, it will be moved to the * end of the list. The current list is modified and returned as a promise. * - * @param {string} _url The rpc url to add to the frequentRpcList. + * @param {string} _url The rpc url to add to the frequentRpcList. * @returns {Promise} The updated frequentRpcList. * */ diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupRaven.js index d164827ab..77aefb00a 100644 --- a/app/scripts/lib/setupRaven.js +++ b/app/scripts/lib/setupRaven.js @@ -66,7 +66,7 @@ function simplifyErrorMessages(report) { function rewriteErrorMessages(report, rewriteFn) { // rewrite top level message - report.message = rewriteFn(report.message) + if (report.message) report.message = rewriteFn(report.message) // rewrite each exception message if (report.exception && report.exception.values) { report.exception.values.forEach(item => { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a570f2567..96f976568 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -139,6 +139,8 @@ module.exports = class MetamaskController extends EventEmitter { const address = addresses[0] this.preferencesController.setSelectedAddress(address) } + // ensure preferences + identities controller know about all addresses + this.preferencesController.addAddresses(addresses) this.accountTracker.syncWithAddresses(addresses) }) @@ -456,7 +458,11 @@ module.exports = class MetamaskController extends EventEmitter { async createNewVaultAndRestore (password, seed) { const release = await this.createVaultMutex.acquire() try { + // clear known identities + this.preferencesController.setAddresses([]) + // create new vault const vault = await this.keyringController.createNewVaultAndRestore(password, seed) + // set new identities const accounts = await this.keyringController.getAccounts() this.preferencesController.setAddresses(accounts) this.selectFirstIdentity() diff --git a/app/scripts/migrations/026.js b/app/scripts/migrations/026.js index 1b8a91a45..4e907e09c 100644 --- a/app/scripts/migrations/026.js +++ b/app/scripts/migrations/026.js @@ -27,7 +27,7 @@ module.exports = { function transformState (state) { if (!state.KeyringController || !state.PreferencesController) { - return + return state } if (!state.KeyringController.walletNicknames) { diff --git a/docs/publishing.md b/docs/publishing.md index 3022b7eda..45662900d 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -2,18 +2,32 @@ When publishing a new version of MetaMask, we follow this procedure: +## Preparation + +We try to ensure certain criteria are met before deploying: + +- Deploy early in the week, to give time for emergency responses to unforeseen bugs. +- Deploy early in the day, for the same reason. +- Make sure at least one member of the support team is "on duty" to watch for new user issues coming through the support system. +- Roll out incrementally when possible, to a small number of users first, and gradually to more users. + ## Incrementing Version & Changelog Version can be automatically incremented [using our bump script](./bumping-version.md). npm run version:bump $BUMP_TYPE` where `$BUMP_TYPE` is one of `major`, `minor`, or `patch`. -## Publishing +## Building -1. `npm run dist` to generate the latest build. -2. Publish to chrome store. - - Visit [the chrome developer dashboard](https://chrome.google.com/webstore/developer/dashboard?authuser=2). -3. Publish to firefox addon marketplace. -4. Post on Github releases page. -5. `npm run announce`, post that announcement in our public places. +While we develop on the main `develop` branch, our production version is maintained on the `master` branch. + +With each pull request, the @MetaMaskBot will comment with a build of that new pull request, so after bumping the version on `develop`, open a pull request against `master`, and once the pull request is reviewed and merged, you can download those builds for publication. + +## Publishing +1. Publish to chrome store. +2. Visit [the chrome developer dashboard](https://chrome.google.com/webstore/developer/dashboard?authuser=2). +3. Publish to [firefox addon marketplace](http://addons.mozilla.org/en-us/firefox/addon/ether-metamask). +4. Publish to [Opera store](https://addons.opera.com/en/extensions/details/metamask/). +5. Post on [Github releases](https://github.com/MetaMask/metamask-extension/releases) page. +6. Run the `npm run announce` script, and post that announcement in our public places. diff --git a/package-lock.json b/package-lock.json index 945c47ae0..dd046f089 100644 --- a/package-lock.json +++ b/package-lock.json @@ -309,7 +309,7 @@ }, "@sinonjs/formatio": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", "dev": true, "requires": { @@ -1500,7 +1500,8 @@ }, "dependencies": { "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", + "from": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" }, "chai": { "version": "3.5.0", @@ -8013,6 +8014,7 @@ "dependencies": { "async-eventemitter": { "version": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", + "from": "async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", "requires": { "async": "2.6.0" } @@ -8266,6 +8268,7 @@ "dependencies": { "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", + "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { "bn.js": "4.11.8", "ethereumjs-util": "5.1.3" @@ -8499,7 +8502,7 @@ "eth-query": "2.1.2", "ethereumjs-block": "1.7.0", "ethereumjs-tx": "1.3.3", - "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", + "ethereumjs-util": "^5.0.1", "ethereumjs-vm": "2.3.5", "through2": "2.0.3", "treeify": "1.1.0", @@ -8648,7 +8651,7 @@ "async": "2.6.0", "ethereum-common": "0.2.0", "ethereumjs-tx": "1.3.3", - "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", + "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "2.3.0" } }, @@ -8658,7 +8661,7 @@ "integrity": "sha1-7OBR0+/b53GtKlGNYWMsoqt17Ls=", "requires": { "ethereum-common": "0.0.18", - "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9" + "ethereumjs-util": "^5.0.0" }, "dependencies": { "ethereum-common": { @@ -8670,6 +8673,7 @@ }, "ethereumjs-util": { "version": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", + "from": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", "requires": { "bn.js": "4.11.8", "create-hash": "1.1.3", @@ -9107,7 +9111,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -11823,6 +11827,7 @@ }, "gulp": { "version": "github:gulpjs/gulp#71c094a51c7972d26f557899ddecab0210ef3776", + "from": "github:gulpjs/gulp#4.0", "requires": { "glob-watcher": "4.0.0", "gulp-cli": "2.0.1", @@ -18205,7 +18210,7 @@ "integrity": "sha512-LKd2OoIT9Re/OG38zXbd5pyHIk2IfcOUczCwkYXl5iJIbufg9nqpweh66VfPwMkUlrEvc7YVvtQdmSrB9V9TkQ==", "requires": { "async": "1.5.2", - "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", + "ethereumjs-util": "^5.0.0", "level-ws": "0.0.0", "levelup": "1.3.9", "memdown": "1.4.1", @@ -31227,7 +31232,8 @@ }, "dependencies": { "bignumber.js": { - "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" + "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", + "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git" } } }, @@ -31708,6 +31714,7 @@ }, "websocket": { "version": "git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c", + "from": "websocket@git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c", "requires": { "debug": "2.6.9", "nan": "2.8.0", diff --git a/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js b/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js index abd599b26..1611f817b 100644 --- a/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js +++ b/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js @@ -15,7 +15,7 @@ export default class TokenListPlaceholder extends Component { diff --git a/ui/app/components/pages/create-account/import-account/index.js b/ui/app/components/pages/create-account/import-account/index.js index 52d3dcde9..e2e973af9 100644 --- a/ui/app/components/pages/create-account/import-account/index.js +++ b/ui/app/components/pages/create-account/import-account/index.js @@ -46,7 +46,7 @@ AccountImportSubview.prototype.render = function () { }, onClick: () => { global.platform.openWindow({ - url: 'https://metamask.helpscoutdocs.com/article/17-what-are-loose-accounts', + url: 'https://consensys.zendesk.com/hc/en-us/articles/360004180111-What-are-imported-accounts-New-UI', }) }, }, this.context.t('here')),