From 687984a9383d948cbe2e8964973ee8c2f0370e6d Mon Sep 17 00:00:00 2001 From: Akshit Kr Nagpal Date: Tue, 2 Jul 2019 17:43:02 +0530 Subject: Added Confirmation Modal for Delete Network (#6776) --- app/_locales/en/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index cc087867a..625aaef66 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1208,6 +1208,12 @@ "resetAccountDescription": { "message": "Resetting your account will clear your transaction history." }, + "deleteNetwork": { + "message": "Delete Network?" + }, + "deleteNetworkDescription": { + "message": "Are you sure you want to delete this network?" + }, "restoreFromSeed": { "message": "Restore account?" }, -- cgit v1.2.3 From 865321d26909c9927910557f4380ffb2d15d9caa Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 2 Jul 2019 22:16:20 -0300 Subject: Update asmcrypto.js to latest version (#6767) This silences a warning message that was printed to the console whenever this module was loaded during tests. The API changes between these two versions were reviewed carefully for differences. The only difference made was to `PBKDF2_HMAC_SHA256.bytes`, which was replaced by `Pbkdf2HmacSha256`. The length argument no longer has a default value, so it has been set to match what the default value was in the previous version we used, which is 32 (the SHA256 hash size). --- app/scripts/edge-encryptor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js index dcb06873b..cfb241ec9 100644 --- a/app/scripts/edge-encryptor.js +++ b/app/scripts/edge-encryptor.js @@ -74,8 +74,10 @@ class EdgeEncryptor { var passBuffer = Unibabel.utf8ToBuffer(password) var saltBuffer = Unibabel.base64ToBuffer(salt) + const iterations = 10000 + const length = 32 // SHA256 hash size return new Promise((resolve) => { - var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000) + var key = asmcrypto.Pbkdf2HmacSha256(passBuffer, saltBuffer, iterations, length) resolve(key) }) } -- cgit v1.2.3 From df17853502f2a9cad6bf0067663de9496f67a7b7 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 4 Jul 2019 12:21:21 -0230 Subject: Remove UiMigrationAnnouncement and associated state (#6794) --- app/scripts/controllers/preferences.js | 9 --------- app/scripts/metamask-controller.js | 1 - 2 files changed, 10 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index acf952bb1..86c9517f5 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -55,7 +55,6 @@ class PreferencesController { useNativeCurrencyAsPrimaryCurrency: true, }, completedOnboarding: false, - completedUiMigration: true, metaMetricsId: null, metaMetricsSendCount: 0, }, opts.initState) @@ -613,14 +612,6 @@ class PreferencesController { return Promise.resolve(true) } - /** - * Sets the {@code completedUiMigration} state to {@code true}, indicating that the user has completed the UI switch. - */ - completeUiMigration () { - this.store.updateState({ completedUiMigration: true }) - return Promise.resolve(true) - } - // // PRIVATE METHODS // diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0b6f5fcb5..393154c60 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -454,7 +454,6 @@ module.exports = class MetamaskController extends EventEmitter { setAccountLabel: nodeify(preferencesController.setAccountLabel, preferencesController), setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController), setPreference: nodeify(preferencesController.setPreference, preferencesController), - completeUiMigration: nodeify(preferencesController.completeUiMigration, preferencesController), completeOnboarding: nodeify(preferencesController.completeOnboarding, preferencesController), addKnownMethodData: nodeify(preferencesController.addKnownMethodData, preferencesController), -- cgit v1.2.3 From 397e0d128d034d10ab3f44641128f3aef99355a9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 1 Jul 2019 13:03:57 -0700 Subject: Version 6.7.2 RC1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d09407373..8639577bb 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "6.7.1", + "version": "6.7.2", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", -- cgit v1.2.3 From 05e21208146c65325330746a7860ce086f10e345 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 3 Jul 2019 18:03:44 -0230 Subject: Version 6.7.2 gas limit fix (#6786) * Introduce delay for eth_estimateGas calls with in test * Add test that fails when gas estimates of contract method calls without gas are too high. * Get transaction gas data from unApprovedTxs instead of confirmTransaction * Fix selection of gas data in gas-modal-page-container.container * Lint changes related to Version-6.7.2-gasLimitFix * Fix e2e tests on Version-6.7.2-gasLimitFix * Fix unit and integration tests for changes from Version-6.7.2-gasLimitFix * more e2e fixes * Add assertions for transaction values on confirm screen * Fix display of transaction amount on confirm screen. --- .../controllers/network/createLocalhostClient.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/network/createLocalhostClient.js b/app/scripts/controllers/network/createLocalhostClient.js index 09b1d3c1c..3a435e5d0 100644 --- a/app/scripts/controllers/network/createLocalhostClient.js +++ b/app/scripts/controllers/network/createLocalhostClient.js @@ -2,9 +2,12 @@ const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware') const createFetchMiddleware = require('eth-json-rpc-middleware/fetch') const createBlockRefRewriteMiddleware = require('eth-json-rpc-middleware/block-ref-rewrite') const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector') +const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware') const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware') const BlockTracker = require('eth-block-tracker') +const inTest = process.env.IN_TEST === 'true' + module.exports = createLocalhostClient function createLocalhostClient () { @@ -13,9 +16,24 @@ function createLocalhostClient () { const blockTracker = new BlockTracker({ provider: blockProvider, pollingInterval: 1000 }) const networkMiddleware = mergeMiddleware([ + createEstimateGasMiddleware(), createBlockRefRewriteMiddleware({ blockTracker }), createBlockTrackerInspectorMiddleware({ blockTracker }), fetchMiddleware, ]) return { networkMiddleware, blockTracker } } + +function delay (time) { + return new Promise(resolve => setTimeout(resolve, time)) +} + + +function createEstimateGasMiddleware () { + return createAsyncMiddleware(async (req, _, next) => { + if (req.method === 'eth_estimateGas' && inTest) { + await delay(2000) + } + return next() + }) +} -- cgit v1.2.3 From 95f198550e419c598750a1717014dac6ca5091e9 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 5 Jul 2019 14:01:34 -0300 Subject: Declare variables before use (#6806) While working on #6805, I noticed that many variables were being used before they were declared. Technically this worked fine in practice because we were using the `transform-es2015-block-scoping` Babel plugin, which transforms `let` and `const` to `var`, which is hoisted. However, after removing that Babel transformation, many things broke. All instances of variables or classes being used before declared have been fixed. The `no-use-before-define` eslint rule has been added to catch these cases going forward. The rule is disabled for function declarations for the moment, because those are always hoisted. We could disable that too if we want to, but it's purely stylistic and would require a lot more changes. --- app/scripts/inpage.js | 89 +++++++++++++++++++------------------ app/scripts/lib/createStreamSink.js | 13 +++--- 2 files changed, 52 insertions(+), 50 deletions(-) (limited to 'app') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index fb16dd43d..2a0a9ad18 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -1,4 +1,36 @@ /*global Web3*/ + + +// need to make sure we aren't affected by overlapping namespaces +// and that we dont affect the app with our namespace +// mostly a fix for web3's BigNumber if AMD's "define" is defined... +let __define + +/** + * Caches reference to global define object and deletes it to + * avoid conflicts with other global define objects, such as + * AMD's define function + */ +const cleanContextForImports = () => { + __define = global.define + try { + global.define = undefined + } catch (_) { + console.warn('MetaMask - global.define could not be deleted.') + } +} + +/** + * Restores global define object from cached reference + */ +const restoreContextAfterImports = () => { + try { + global.define = __define + } catch (_) { + console.warn('MetaMask - global.define could not be overwritten.') + } +} + cleanContextForImports() require('web3/dist/web3.min.js') const log = require('loglevel') @@ -46,6 +78,20 @@ inpageProvider.enable = function ({ force } = {}) { // this will be default true so it does not break any old apps. inpageProvider.autoRefreshOnNetworkChange = true + +// publicConfig isn't populated until we get a message from background. +// Using this getter will ensure the state is available +const getPublicConfigWhenReady = async () => { + const store = inpageProvider.publicConfigStore + let state = store.getState() + // if state is missing, wait for first update + if (!state.networkVersion) { + state = await new Promise(resolve => store.once('update', resolve)) + console.log('new state', state) + } + return state +} + // add metamask-specific convenience methods inpageProvider._metamask = new Proxy({ /** @@ -87,19 +133,6 @@ inpageProvider._metamask = new Proxy({ }, }) -// publicConfig isn't populated until we get a message from background. -// Using this getter will ensure the state is available -async function getPublicConfigWhenReady () { - const store = inpageProvider.publicConfigStore - let state = store.getState() - // if state is missing, wait for first update - if (!state.networkVersion) { - state = await new Promise(resolve => store.once('update', resolve)) - console.log('new state', state) - } - return state -} - // Work around for web3@1.0 deleting the bound `sendAsync` but not the unbound // `sendAsync` method on the prototype, causing `this` reference issues with drizzle const proxiedInpageProvider = new Proxy(inpageProvider, { @@ -161,33 +194,3 @@ inpageProvider.publicConfigStore.subscribe(function (state) { window.postMessage('onboardingcomplete', '*') } }) - -// need to make sure we aren't affected by overlapping namespaces -// and that we dont affect the app with our namespace -// mostly a fix for web3's BigNumber if AMD's "define" is defined... -let __define - -/** - * Caches reference to global define object and deletes it to - * avoid conflicts with other global define objects, such as - * AMD's define function - */ -function cleanContextForImports () { - __define = global.define - try { - global.define = undefined - } catch (_) { - console.warn('MetaMask - global.define could not be deleted.') - } -} - -/** - * Restores global define object from cached reference - */ -function restoreContextAfterImports () { - try { - global.define = __define - } catch (_) { - console.warn('MetaMask - global.define could not be overwritten.') - } -} diff --git a/app/scripts/lib/createStreamSink.js b/app/scripts/lib/createStreamSink.js index b93dbc089..eb9d0bd1a 100644 --- a/app/scripts/lib/createStreamSink.js +++ b/app/scripts/lib/createStreamSink.js @@ -1,13 +1,6 @@ const WritableStream = require('readable-stream').Writable const promiseToCallback = require('promise-to-callback') -module.exports = createStreamSink - - -function createStreamSink (asyncWriteFn, _opts) { - return new AsyncWritableStream(asyncWriteFn, _opts) -} - class AsyncWritableStream extends WritableStream { constructor (asyncWriteFn, _opts) { @@ -22,3 +15,9 @@ class AsyncWritableStream extends WritableStream { } } + +function createStreamSink (asyncWriteFn, _opts) { + return new AsyncWritableStream(asyncWriteFn, _opts) +} + +module.exports = createStreamSink -- cgit v1.2.3 From 32a3f5ad7b8d30c1d4843152e575770b189146ea Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Mon, 8 Jul 2019 15:28:35 -0230 Subject: Address various UI styling issues (#6744) * Add loading spinner to pending tx status label. * Add border around account icon in top right * Change style of settings toggle buttons; wrap with local components * Eliminate large space after settings labels when no description * Remove network form from advanced tab of settings * Keep new account container height to contents when in full screen --- app/_locales/en/messages.json | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 625aaef66..e0a3ad1a9 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -237,9 +237,15 @@ "bytes": { "message": "Bytes" }, + "off": { + "message": "Off" + }, "ok": { "message": "Ok" }, + "on": { + "message": "On" + }, "optionalBlockExplorerUrl": { "message": "Block Explorer URL (optional)" }, -- cgit v1.2.3 From fabba27b78ad7299d8638a1a3f0b2ded3d21080d Mon Sep 17 00:00:00 2001 From: Brian Soule Date: Wed, 10 Jul 2019 07:26:20 -0500 Subject: Capitalized speed up label to match rest of UI (#6828) --- app/_locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e0a3ad1a9..741a92107 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1469,7 +1469,7 @@ "message": "there can only be a space between words" }, "speedUp": { - "message": "speed up" + "message": "Speed Up" }, "speedUpTitle": { "message": "Speed Up Transaction" -- cgit v1.2.3 From 45534d9908b9a495e2afcbe8a04343b0bb4ee6a5 Mon Sep 17 00:00:00 2001 From: filmendless Date: Wed, 10 Jul 2019 21:37:20 +0700 Subject: [ImgBot] Optimize images (#1) (#6829) *Total -- 5,450.78kb -> 4,473.66kb (17.93%) /images/404.png -- 38.48kb -> 11.19kb (70.91%) /images/deadface.png -- 8.14kb -> 4.50kb (44.67%) /images/cancel.png -- 10.67kb -> 6.04kb (43.38%) /app/images/key-32.png -- 1.08kb -> 0.68kb (37.66%) /app/images/coinswitch_logo.png -- 3.06kb -> 1.94kb (36.43%) /images/info-logo.png -- 31.80kb -> 20.43kb (35.77%) /docs/transaction-flow.png -- 137.82kb -> 91.38kb (33.7%) /ui/design/metamask-logo-eyes.png -- 142.65kb -> 94.94kb (33.45%) /images/coinbase logo.png -- 9.55kb -> 6.43kb (32.64%) /ui/design/chromeStorePics/screen_dao_accounts.png -- 505.47kb -> 347.03kb (31.34%) /docs/architecture.png -- 136.94kb -> 94.15kb (31.25%) /ui/design/chromeStorePics/screen_dao_locked.png -- 280.38kb -> 199.54kb (28.83%) /app/images/logo.png -- 6.43kb -> 4.58kb (28.81%) /ui/design/chromeStorePics/screen_wei_account.png -- 638.31kb -> 469.17kb (26.5%) /images/pw-128x128.png -- 92.76kb -> 69.18kb (25.42%) /app/images/pw128x128.png -- 92.76kb -> 69.18kb (25.42%) /app/images/shapeshift logo.png -- 17.13kb -> 13.54kb (20.92%) /ui/design/02b-metamask-AccDetails-Send.jpg -- 107.56kb -> 92.00kb (14.46%) /images/icon-128.png -- 5.63kb -> 4.82kb (14.45%) /ui/design/chromeStorePics/icon-128.png -- 5.63kb -> 4.82kb (14.45%) /ui/design/02a-metamask-AccDetails.jpg -- 114.81kb -> 99.73kb (13.14%) /ui/design/02a-metamask-AccDetails-OverTransaction.jpg -- 119.21kb -> 103.65kb (13.06%) /ui/design/02a-metamask-AccDetails-OverToken.jpg -- 118.99kb -> 103.62kb (12.92%) /ui/design/wireframes/metamask_wfs_jan_13.png -- 409.24kb -> 357.28kb (12.7%) /ui/design/chromeStorePics/screen_dao_notification.png -- 289.55kb -> 254.49kb (12.11%) /ui/design/05-metamask-Menu.jpg -- 127.21kb -> 111.93kb (12.01%) /app/images/ethereum-metamask-chrome.png -- 58.62kb -> 51.86kb (11.52%) /ui/design/chromeStorePics/final_screen_dao_accounts.png -- 243.86kb -> 217.46kb (10.82%) /ui/design/chromeStorePics/promo1400560.png -- 255.51kb -> 228.52kb (10.56%) /images/icon-512.png -- 41.09kb -> 36.95kb (10.08%) /ui/design/chromeStorePics/promo920680.png -- 201.87kb -> 181.88kb (9.9%) /ui/design/chromeStorePics/final_screen_wei_account.png -- 247.44kb -> 223.83kb (9.54%) /ui/design/chromeStorePics/final_screen_dao_locked.png -- 215.13kb -> 196.06kb (8.87%) /ui/design/chromeStorePics/final_screen_dao_notification.png -- 209.38kb -> 192.76kb (7.94%) /ui/design/00-metamask-SignIn.jpg -- 56.49kb -> 53.22kb (5.79%) /ui/design/03-metamask-Qr.jpg -- 64.50kb -> 60.89kb (5.6%) /ui/design/01-metamask-SelectAcc.jpg -- 74.28kb -> 70.34kb (5.3%) /ui/design/02-metamask-AccDetails.jpg -- 74.00kb -> 70.15kb (5.21%) /ui/design/chromeStorePics/promo440280.png -- 56.12kb -> 53.92kb (3.93%) /app/images/icon-64.png -- 3.49kb -> 3.40kb (2.66%) /ui/design/chromeStorePics/icon-64.png -- 3.49kb -> 3.40kb (2.66%) /images/pw-48x48.png -- 3.20kb -> 3.16kb (1.34%) /ui/design/chromeStorePics/final_screen_wei_notification.png -- 189.32kb -> 187.93kb (0.73%) /images/icon-32.png -- 1.69kb -> 1.68kb (0.46%) --- app/images/coinswitch_logo.png | Bin 3132 -> 1991 bytes app/images/ethereum-metamask-chrome.png | Bin 60022 -> 53107 bytes app/images/icon-64.png | Bin 3573 -> 3478 bytes app/images/key-32.png | Bin 1110 -> 692 bytes app/images/logo.png | Bin 6589 -> 4691 bytes app/images/pw128x128.png | Bin 94988 -> 70843 bytes app/images/shapeshift logo.png | Bin 17537 -> 13869 bytes 7 files changed, 0 insertions(+), 0 deletions(-) (limited to 'app') diff --git a/app/images/coinswitch_logo.png b/app/images/coinswitch_logo.png index 445ecf02e..aa8f525be 100644 Binary files a/app/images/coinswitch_logo.png and b/app/images/coinswitch_logo.png differ diff --git a/app/images/ethereum-metamask-chrome.png b/app/images/ethereum-metamask-chrome.png index 0b886babb..ffd0ff146 100644 Binary files a/app/images/ethereum-metamask-chrome.png and b/app/images/ethereum-metamask-chrome.png differ diff --git a/app/images/icon-64.png b/app/images/icon-64.png index b3019ad65..9a1995874 100644 Binary files a/app/images/icon-64.png and b/app/images/icon-64.png differ diff --git a/app/images/key-32.png b/app/images/key-32.png index ca11cacd9..ac9ddcae3 100644 Binary files a/app/images/key-32.png and b/app/images/key-32.png differ diff --git a/app/images/logo.png b/app/images/logo.png index db6ba7d6c..3013d583b 100644 Binary files a/app/images/logo.png and b/app/images/logo.png differ diff --git a/app/images/pw128x128.png b/app/images/pw128x128.png index a0eb1b730..c1ef2b5b2 100644 Binary files a/app/images/pw128x128.png and b/app/images/pw128x128.png differ diff --git a/app/images/shapeshift logo.png b/app/images/shapeshift logo.png index ac8faba5b..a8b47d31e 100644 Binary files a/app/images/shapeshift logo.png and b/app/images/shapeshift logo.png differ -- cgit v1.2.3 From f0218bdbbbc54bc5b495d813cf295da18000d136 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 10 Jul 2019 16:31:48 -0230 Subject: Rename accountManager usages (#6790) Co-Authored-By: Mark Stacey --- app/scripts/phishing-detect.js | 6 +++--- app/scripts/popup-core.js | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/phishing-detect.js b/app/scripts/phishing-detect.js index b30c76b72..266e4fc31 100644 --- a/app/scripts/phishing-detect.js +++ b/app/scripts/phishing-detect.js @@ -37,11 +37,11 @@ function start () { function setupControllerConnection (connectionStream, cb) { const eventEmitter = new EventEmitter() - const accountManagerDnode = dnode({ + const metaMaskControllerDnode = dnode({ sendUpdate (state) { eventEmitter.emit('update', state) }, }) - connectionStream.pipe(accountManagerDnode).pipe(connectionStream) - accountManagerDnode.once('remote', (accountManager) => cb(null, accountManager)) + connectionStream.pipe(metaMaskControllerDnode).pipe(connectionStream) + metaMaskControllerDnode.once('remote', (backgroundConnection) => cb(null, backgroundConnection)) } diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index e964d001d..c08e9fa24 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -19,7 +19,7 @@ function initializePopup ({ container, connectionStream }, cb) { // setup app async.waterfall([ (cb) => connectToAccountManager(connectionStream, cb), - (accountManager, cb) => launchMetamaskUi({ container, accountManager }, cb), + (backgroundConnection, cb) => launchMetamaskUi({ container, backgroundConnection }, cb), ], cb) } @@ -63,15 +63,15 @@ function setupControllerConnection (connectionStream, cb) { // this is a really sneaky way of adding EventEmitter api // to a bi-directional dnode instance const eventEmitter = new EventEmitter() - const accountManagerDnode = Dnode({ + const backgroundDnode = Dnode({ sendUpdate: function (state) { eventEmitter.emit('update', state) }, }) - connectionStream.pipe(accountManagerDnode).pipe(connectionStream) - accountManagerDnode.once('remote', function (accountManager) { + connectionStream.pipe(backgroundDnode).pipe(connectionStream) + backgroundDnode.once('remote', function (backgroundConnection) { // setup push events - accountManager.on = eventEmitter.on.bind(eventEmitter) - cb(null, accountManager) + backgroundConnection.on = eventEmitter.on.bind(eventEmitter) + cb(null, backgroundConnection) }) } -- cgit v1.2.3 From 1ca23078c44669c1d6d8638e7c18cac85984db27 Mon Sep 17 00:00:00 2001 From: Saxon Knight Date: Thu, 11 Jul 2019 04:04:07 -1000 Subject: Fix wording in readdToken message (#6837) - Removes extra "go" in app/_locales/en/messages.json's readdToken message --- app/_locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 741a92107..49276c92b 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1176,7 +1176,7 @@ "message": "Queue" }, "readdToken": { - "message": "You can add this token back in the future by going go to “Add token” in your accounts options menu." + "message": "You can add this token back in the future by going to “Add token” in your accounts options menu." }, "readMore": { "message": "Read more here." -- cgit v1.2.3 From ded3dc1381decc872b23eb4b706fa6571fe98cdc Mon Sep 17 00:00:00 2001 From: Terry Smith <52763493+tshfx@users.noreply.github.com> Date: Sun, 14 Jul 2019 23:22:20 -0300 Subject: Add translation support for Learn more and All done on end-of-flow (#6847) --- app/_locales/en/messages.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 49276c92b..16f29d6db 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -562,6 +562,12 @@ "endOfFlowMessage8": { "message": "MetaMask cannot recover your seedphrase. Learn more." }, + "endOfFlowMessage9": { + "message": "Learn more." + }, + "endOfFlowMessage10": { + "message": "All Done" + }, "ensNameNotFound": { "message": "ENS name not found" }, @@ -1814,6 +1820,6 @@ "message": "MetaMask will never ask for your seed phrase!" }, "zeroGasPriceOnSpeedUpError": { - "message":"Zero gas price on speed up" + "message": "Zero gas price on speed up" } -} +} \ No newline at end of file -- cgit v1.2.3 From 04ae92a2c03c5115b7b5be63ab2d03ef5c78bccd Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 15 Jul 2019 11:03:22 -0300 Subject: Lint `.json` files (#6852) We've been using the `eslint-plugin-json` plugin for some time, but we haven't been visiting `.json` files in the lint script. The lint script has now been updated to incude `.json` files, which means any invalid JSON will result in a lint error. Unfortunately this JSON plugin doesn't seem to apply the other eslint rules (such as `key-spacing`) to the JSON files. I wasn't able to find a way to get that to work. Instead I manually auto-formatted each of the locale `message.json` files, which fixed many whitespace inconsistencies. The `states.json` file was deleted completely, as it appears to be unused. It wasn't a valid JSON file anyway, it was JavaScript. It looks like a `states.js` file is automatically generated, but an old copy was accidentally saved as `states.json` and included in the repo. Many duplicate key errors were found and fixed in the `development/states/` JSON files. `package-lock.json` was added to `.eslintignore` because it was very slow to lint, and linting it doesn't provide much value. --- app/_locales/en/messages.json | 2 +- app/_locales/es/messages.json | 4 ++-- app/_locales/ph/messages.json | 2 +- app/_locales/sl/messages.json | 4 ++-- app/_locales/vi/messages.json | 2 +- app/_locales/zh_TW/messages.json | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 16f29d6db..e69b3dc36 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1822,4 +1822,4 @@ "zeroGasPriceOnSpeedUpError": { "message": "Zero gas price on speed up" } -} \ No newline at end of file +} diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 06531b1dc..bf466fdc2 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1235,7 +1235,7 @@ }, "pending": { "message": "pendiente" - }, + }, "popularTokens": { "message": "Tokens Corrientes" }, @@ -1504,7 +1504,7 @@ "message": "Tu frase semilla privada" }, "zeroGasPriceOnSpeedUpError": { - "message":"No hubo precio de gas al agilizar" + "message": "No hubo precio de gas al agilizar" }, "currencyConversion": { "message": "Cambio de Monedas" diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index c8cde27f6..9763bd273 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -318,7 +318,7 @@ "message": "i-click ito", "description": "tulad ng -i-click dito- para sa mas maraming impormasyon (kasama ng troubleTokenBalances)" }, - "hide": { + "hide": { "message": "Itago" }, "hideToken": { diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index d04ba1ee7..563bae1b1 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -1145,7 +1145,7 @@ }, "seedPhraseAlert": { "message": "Opozorilo o seed phrase" - }, + }, "select": { "message": "Izberi" }, @@ -1549,6 +1549,6 @@ "message": "Vaš zasebni seed phrase" }, "zeroGasPriceOnSpeedUpError": { - "message":"Ničelni gas price na pospešitvi" + "message": "Ničelni gas price na pospešitvi" } } diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index aee6474b6..622e0d818 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -655,5 +655,5 @@ }, "yourSigRequested": { "message": "Chữ ký của bạn đang được yêu cầu" - } + } } diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 18e30188e..2559fc0ad 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -651,7 +651,7 @@ "description": "status showing that an account has been fully loaded into the keyring" }, "importUsingSeed": { - "message": "利用助憶詞匯入帳戶" , + "message": "利用助憶詞匯入帳戶", "description": "登入頁面下方" }, "importWithSeedPhrase": { @@ -1584,6 +1584,6 @@ "message": "您每一次在交易時,都會看到這個圖案。" }, "zeroGasPriceOnSpeedUpError": { - "message":"加速的 Gas 價格為 0" + "message": "加速的 Gas 價格為 0" } } -- cgit v1.2.3 From 32fffe53f5016b8fc4f2b78f4501fc271705b96d Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 15 Jul 2019 17:10:46 -0300 Subject: Remove Drizzle tests (#6855) The Drizzle tests have not been used for some time. They were used to ensure compatibility with newer versions of `web3` v1. If we want to re-add tests to ensure compatibility with newer `web3` versions, we should find some way of doing that more reliably than was done here - these tests were somewhat flaky and unreliable. --- app/scripts/inpage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 2a0a9ad18..a94787b05 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -134,7 +134,7 @@ inpageProvider._metamask = new Proxy({ }) // Work around for web3@1.0 deleting the bound `sendAsync` but not the unbound -// `sendAsync` method on the prototype, causing `this` reference issues with drizzle +// `sendAsync` method on the prototype, causing `this` reference issues const proxiedInpageProvider = new Proxy(inpageProvider, { // straight up lie that we deleted the property so that it doesnt // throw an error in strict mode -- cgit v1.2.3 From 78cdee23c0f9ba0a6e54bab0ddccc4df3abfe3d9 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Mon, 15 Jul 2019 16:28:04 -0700 Subject: Abstract domain provider from its stream transport (#6670) * Abstract domain provider from its stream transport Creating new provider-consuming extensions, like [a new platform](https://github.com/MetaMask/metamask-extension/blob/develop/docs/porting_to_new_environment.md) can be frustrating for new contributors because our provider construction has been tangled with our streaming interface. Here I've broken up our streaming domain connection from the provider construction, so developers can more easily construct local and domain-restricted providers without dealing with streams. * Abstract public API from stream interface * clean up noop * Document non-streaming interface * getSiteMetadata must be async * Clean up filters on stream end * Document cleaning up filters * Allow named filterMiddleware to be cleaned up * Linted * Require site metadata * Destroy any destroyable middleware during cleanup * Lint --- app/scripts/metamask-controller.js | 45 +++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 393154c60..17d38d43c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1391,6 +1391,32 @@ module.exports = class MetamaskController extends EventEmitter { * @param {string} origin - The URI of the requesting resource. */ setupProviderConnection (outStream, origin, publicApi) { + const getSiteMetadata = publicApi && publicApi.getSiteMetadata + const engine = this.setupProviderEngine(origin, getSiteMetadata) + + // setup connection + const providerStream = createEngineStream({ engine }) + + pump( + outStream, + providerStream, + outStream, + (err) => { + // cleanup filter polyfill middleware + engine._middleware.forEach((mid) => { + if (mid.destroy && typeof mid.destroy === 'function') { + mid.destroy() + } + }) + if (err) log.error(err) + } + ) + } + + /** + * A method for creating a provider that is safely restricted for the requesting domain. + **/ + setupProviderEngine (origin, getSiteMetadata) { // setup json rpc engine stack const engine = new RpcEngine() const provider = this.provider @@ -1398,6 +1424,7 @@ module.exports = class MetamaskController extends EventEmitter { // create filter polyfill middleware const filterMiddleware = createFilterMiddleware({ provider, blockTracker }) + // create subscription polyfill middleware const subscriptionManager = createSubscriptionManager({ provider, blockTracker }) subscriptionManager.events.on('notification', (message) => engine.emit('notification', message)) @@ -1413,24 +1440,11 @@ module.exports = class MetamaskController extends EventEmitter { // requestAccounts engine.push(this.providerApprovalController.createMiddleware({ origin, - getSiteMetadata: publicApi && publicApi.getSiteMetadata, + getSiteMetadata, })) // forward to metamask primary provider engine.push(providerAsMiddleware(provider)) - - // setup connection - const providerStream = createEngineStream({ engine }) - - pump( - outStream, - providerStream, - outStream, - (err) => { - // cleanup filter polyfill middleware - filterMiddleware.destroy() - if (err) log.error(err) - } - ) + return engine } /** @@ -1797,3 +1811,4 @@ module.exports = class MetamaskController extends EventEmitter { return this.keyringController.setLocked() } } + -- cgit v1.2.3 From 7357f011c3ff6580480bcc520ce4127667c412b7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 18 Jul 2019 18:16:30 -0300 Subject: Set minimum browser version in manifest (#6877) Set the minimum browser version supported in the extension manifest. Currently we only ship the extension on Chrome and Firefox, so the minimum version has been set for those two browsers. Relates to #6805 --- app/manifest.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 8639577bb..a89962d5a 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -21,7 +21,8 @@ }, "applications": { "gecko": { - "id": "webextension@metamask.io" + "id": "webextension@metamask.io", + "strict_min_version": "53.0" } }, "default_locale": "en", @@ -85,4 +86,4 @@ "*" ] } -} \ No newline at end of file +} -- cgit v1.2.3 From aea54d1b86e8b3d23afe145428335bffdbfe906c Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Thu, 18 Jul 2019 20:37:51 -0700 Subject: Address resubmit bug (#6886) * Add some notes * Add explanatory comment and TODO * Typo * Improve verbage * Remove contextual comment --- app/scripts/controllers/transactions/index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 1ae925835..c4371c25b 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -68,6 +68,7 @@ class TransactionController extends EventEmitter { this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction this.getGasPrice = opts.getGasPrice + this.inProcessOfSigning = new Set() this.memStore = new ObservableStore({}) this.query = new EthQuery(this.provider) @@ -354,6 +355,15 @@ class TransactionController extends EventEmitter { @param txId {number} - the tx's Id */ async approveTransaction (txId) { + // TODO: Move this safety out of this function. + // Since this transaction is async, + // we need to keep track of what is currently being signed, + // So that we do not increment nonce + resubmit something + // that is already being incrmented & signed. + if (this.inProcessOfSigning.has(txId)) { + return + } + this.inProcessOfSigning.add(txId) let nonceLock try { // approve @@ -387,6 +397,8 @@ class TransactionController extends EventEmitter { if (nonceLock) nonceLock.releaseLock() // continue with error chain throw err + } finally { + this.inProcessOfSigning.delete(txId) } } /** -- cgit v1.2.3 From 437132bf25525dd786bb5da1d1d934a6ef050949 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 23 Jul 2019 13:54:49 -0300 Subject: Replace deprecated Chrome API (#6895) The function `chrome.extension.getURL` has been deprecated since Chrome 58 [1]. It is completely equivalent to `chrome.runtime.getURL`, which has been around since Chrome 31. [1]: https://developer.chrome.com/extensions/extension#method-getURL --- app/scripts/contentscript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 0c55ae39f..db4d5fd63 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -10,7 +10,7 @@ const extension = require('extensionizer') const PortStream = require('extension-port-stream') const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString() -const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n' +const inpageSuffix = '//# sourceURL=' + extension.runtime.getURL('inpage.js') + '\n' const inpageBundle = inpageContent + inpageSuffix // Eventually this streaming injection could be replaced with: -- cgit v1.2.3 From 0f8a9a5d495498d87093c14d3d87c51d3f23c7e2 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 23 Jul 2019 14:10:13 -0300 Subject: Serve CSS as an external file (#6894) The CSS is now served as an external file instead of being injected. This was done to improve performance. Ideally we would come to a middle ground between this and the former behaviour by injecting only the CSS that was required for the initial page load, then lazily loading the rest. However that change would be more complex. The hope was that making all CSS external would at least be a slight improvement. Performance metrics were collected before and after this change to determine whether this change actually helped. The metrics collected were the timing events provided by Chrome DevTools: * DOM Content Loaded (DCL) [1] * Load (L) [2] * First Paint (FP) [3] * First Contentful Paint (FCP) [3] * First Meaningful Paint (FMP) [3] Here are the results (units in milliseconds): Injected CSS: | Run | DCL | L | FP | FCP | FMP | | :--- | ---: | ---: | ---: | ---: | ---: | | 1 | 1569.45 | 1570.97 | 1700.36 | 1700.36 | 1700.36 | | 2 | 1517.37 | 1518.84 | 1630.98 | 1630.98 | 1630.98 | | 3 | 1603.71 | 1605.31 | 1712.56 | 1712.56 | 1712.56 | | 4 | 1522.15 | 1523.72 | 1629.3 | 1629.3 | 1629.3 | | **Min** | 1517.37 | 1518.84 | 1629.3 | 1629.3 | 1629.3 | | **Max** | 1603.71 | 1605.31 | 1712.56 | 1712.56 | 1712.56 | | **Mean** | 1553.17 | 1554.71 | 1668.3 | 1668.3 | 1668.3 | | **Std. dev.** | 33.41 | 33.43 | 38.16 | 38.16 | 38.16 | External CSS: | Run | DCL | L | FP | FCP | FMP | | :--- | ---: | ---: | ---: | ---: | ---: | | 1 | 1595.4 | 1598.91 | 284.97 | 1712.86 | 1712.86 | | 2 | 1537.55 | 1538.99 | 199.38 | 1633.5 | 1633.5 | | 3 | 1571.28 | 1572.74 | 268.65 | 1677.03 | 1677.03 | | 4 | 1510.98 | 1512.33 | 206.72 | 1607.03 | 1607.03 | | **Min** | 1510.98 | 1512.33 | 199.38 | 1607.03 | 1607.03 | | **Max** | 1595.4 | 1598.91 | 284.97 | 1712.86 | 1712.86 | | **Mean** | 1553.8025 | 1555.7425 | 239.93 | 1657.605 | 1657.605 | | **Std. dev.** | 29.5375 | 30.0825 | 36.88 | 37.34 | 37.34 | Unfortunately, using an external CSS file made no discernible improvement to the overall page load time. DCM and L were practically identical, and FCP and FMP were marginally better (well within error margins). However, the first paint time was _dramatically_ improved. This change seems worthwhile for the first paint time improvement alone. It also allows us to delete some code and remove a dependency. The old `css.js` module included two third-party CSS files as well, so those have been imported into the main Sass file. This was easier than bundling them in the gulpfile. The resulting CSS bundle needs to be served from the root because we're using a few `@include` rules that make this assumption. We could move this under `/css/` if desired, but we'd need to update each of these `@include` rules. Relates to #6646 [1]: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded [2]: https://developer.mozilla.org/en-US/docs/Web/Events/load [3]: https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics --- app/home.html | 1 + app/notification.html | 1 + app/popup.html | 1 + app/scripts/ui.js | 4 ---- 4 files changed, 3 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/home.html b/app/home.html index 051133cf8..ac17ed307 100644 --- a/app/home.html +++ b/app/home.html @@ -4,6 +4,7 @@ MetaMask +
diff --git a/app/notification.html b/app/notification.html index 82bf95ada..eba290c15 100644 --- a/app/notification.html +++ b/app/notification.html @@ -28,6 +28,7 @@ margin-top: 1rem; } +
diff --git a/app/popup.html b/app/popup.html index 1ba0fda94..3a6709eaf 100644 --- a/app/popup.html +++ b/app/popup.html @@ -4,6 +4,7 @@ MetaMask +
diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 67ec6bf06..2dde14b48 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -1,5 +1,3 @@ -const injectCss = require('inject-css') -const NewMetaMaskUiCss = require('../../ui/css') const startPopup = require('./popup-core') const PortStream = require('extension-port-stream') const { getEnvironmentType } = require('./lib/util') @@ -53,8 +51,6 @@ async function start () { global.platform.openExtensionInBrowser() return } - - injectCss(NewMetaMaskUiCss()) }) -- cgit v1.2.3 From e81aa6073d30d5a93fce9a2414203e8367ae16b9 Mon Sep 17 00:00:00 2001 From: Alessandro Ricottone Date: Tue, 23 Jul 2019 21:29:20 +0200 Subject: Resolve onion addresses (#6869) * Resolve onion address * npm i content-hash@latest --- app/scripts/lib/ens-ipfs/setup.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index 82679db5d..86f3e7d47 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -51,6 +51,8 @@ function setupEnsIpfsResolver ({ provider }) { } } else if (type === 'swarm-ns') { url = `https://swarm-gateways.net/bzz:/${hash}${path}${search || ''}` + } else if (type === 'onion' || type === 'onion3') { + url = `http://${hash}.onion${path}${search || ''}` } } catch (err) { console.warn(err) -- cgit v1.2.3 From fc3b035aac66c5636ef7d77c0659a157cdf4384d Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 23 Jul 2019 17:14:04 -0230 Subject: Check balance before testing it w/ isZero (#6898) --- app/scripts/controllers/detect-tokens.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index e6940c613..f0ceab8e6 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -47,7 +47,7 @@ class DetectTokensController { } tokensToDetect.forEach((tokenAddress, index) => { const balance = result[index] - if (!balance.isZero()) { + if (balance && !balance.isZero()) { this._preferences.addToken(tokenAddress, contracts[tokenAddress].symbol, contracts[tokenAddress].decimals) } }) -- cgit v1.2.3 From 429030a00e7fb5b8b20fb863ef3ba501a5729eab Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 24 Jul 2019 23:40:22 -0300 Subject: Remove unused `unlockAccountMessage` callback (#6905) This callback has been unused for a long time. It was removed in #1076 --- app/scripts/background.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index cca0d4709..7bedfcc19 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -253,7 +253,6 @@ function setupController (initState, initLangCode) { const controller = new MetamaskController({ // User confirmation callbacks: showUnconfirmedMessage: triggerUi, - unlockAccountMessage: triggerUi, showUnapprovedTx: triggerUi, openPopup: openPopup, closePopup: notificationManager.closePopup.bind(notificationManager), -- cgit v1.2.3 From 1112277cd628378f8b0e659067456677ec9a45ac Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 26 Jul 2019 10:35:21 -0300 Subject: Remove `seedWords` completely from metamask state (#6920) `seedWords` used to be stored on the metamask state temporarily at certain points. This hasn't been the case since #5994, but references to this state remained. All of the logic remained for correctly updating these `seedWords`, handling them during navigation, and scrubbing them from the state. However the state was never updated in practice. The `seedWords` are still returned by `verifySeedPhrase`, and they're still stored in component state in a few places. But they aren't ever set in the Redux metadata state or the Preferences controller. All references to this state have been removed, along with any logic for interacting with this state. A few unused actions were removed as well. --- app/scripts/background.js | 1 - app/scripts/controllers/preferences.js | 9 --------- app/scripts/metamask-controller.js | 34 ---------------------------------- 3 files changed, 44 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 7bedfcc19..8e65bd5a4 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -116,7 +116,6 @@ setupMetamaskMeshMetrics() * @property {boolean} useBlockie - Indicates preferred user identicon format. True for blockie, false for Jazzicon. * @property {Object} featureFlags - An object for optional feature flags. * @property {string} networkEndpointType - TODO: Document - * @property {boolean} isRevealingSeedWords - True if seed words are currently being recovered, and should be shown to user. * @property {boolean} welcomeScreen - True if welcome screen should be shown. * @property {string} currentLocale - A locale string matching the user's preferred display language. * @property {Object} provider - The current selected network provider. diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 86c9517f5..4197781d2 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -49,7 +49,6 @@ class PreferencesController { currentLocale: opts.initLangCode, identities: {}, lostIdentities: {}, - seedWords: null, forgottenPassword: false, preferences: { useNativeCurrencyAsPrimaryCurrency: true, @@ -79,14 +78,6 @@ class PreferencesController { this.store.updateState({ forgottenPassword }) } - /** - * Sets the {@code seedWords} seed words - * @param {string|null} seedWords the seed words - */ - setSeedWords (seedWords) { - this.store.updateState({ seedWords }) - } - /** * Setter for the `useBlockie` property * diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 17d38d43c..84a25b008 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -420,9 +420,7 @@ module.exports = class MetamaskController extends EventEmitter { // primary HD keyring management addNewAccount: nodeify(this.addNewAccount, this), - placeSeedWords: this.placeSeedWords.bind(this), verifySeedPhrase: nodeify(this.verifySeedPhrase, this), - clearSeedWordCache: this.clearSeedWordCache.bind(this), resetAccount: nodeify(this.resetAccount, this), removeAccount: nodeify(this.removeAccount, this), importAccountWithStrategy: nodeify(this.importAccountWithStrategy, this), @@ -844,26 +842,6 @@ module.exports = class MetamaskController extends EventEmitter { return {...keyState, identities} } - /** - * Adds the current vault's seed words to the UI's state tree. - * - * Used when creating a first vault, to allow confirmation. - * Also used when revealing the seed words in the confirmation view. - * - * @param {Function} cb - A callback called on completion. - */ - placeSeedWords (cb) { - - this.verifySeedPhrase() - .then((seedWords) => { - this.preferencesController.setSeedWords(seedWords) - return cb(null, seedWords) - }) - .catch((err) => { - return cb(err) - }) - } - /** * Verifies the validity of the current vault's seed phrase. * @@ -897,18 +875,6 @@ module.exports = class MetamaskController extends EventEmitter { } } - /** - * Remove the primary account seed phrase from the UI's state tree. - * - * The seed phrase remains available in the background process. - * - * @param {function} cb Callback function called with the current address. - */ - clearSeedWordCache (cb) { - this.preferencesController.setSeedWords(null) - cb(null, this.preferencesController.getSelectedAddress()) - } - /** * Clears the transaction history, to allow users to force-reset their nonces. * Mostly used in development environments, when networks are restarted with -- cgit v1.2.3 From 948b6ca80b07169f75259eec62ba6a67b0ca41eb Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Mon, 29 Jul 2019 10:06:17 -0230 Subject: Fix casing of Etherscan (#6927) --- app/scripts/platforms/extension.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 0c2d222b8..1007fe24d 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -68,7 +68,7 @@ class ExtensionPlatform { const nonce = parseInt(txMeta.txParams.nonce, 16) const title = 'Confirmed transaction' - const message = `Transaction ${nonce} confirmed! View on EtherScan` + const message = `Transaction ${nonce} confirmed! View on Etherscan` this._showNotification(title, message, url) } @@ -92,12 +92,12 @@ class ExtensionPlatform { } _subscribeToNotificationClicked () { - if (!extension.notifications.onClicked.hasListener(this._viewOnEtherScan)) { - extension.notifications.onClicked.addListener(this._viewOnEtherScan) + if (!extension.notifications.onClicked.hasListener(this._viewOnEtherscan)) { + extension.notifications.onClicked.addListener(this._viewOnEtherscan) } } - _viewOnEtherScan (txId) { + _viewOnEtherscan (txId) { if (txId.startsWith('http://')) { extension.tabs.create({ url: txId }) } -- cgit v1.2.3 From e9c7df28ed88f6dc3a5074cf873f3920429d1803 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 31 Jul 2019 17:26:44 -0230 Subject: Address book send plus contact list (#6914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Style Send Header * Move Send to-row to send view and restyle * Add "Recents" group to select recipient view * Rename SendToRow to AddRecipient * Basic UI and Layout * New ENSInput component * wip - fuzzy search for input * small refactor * Add Dialog * contact list initial * initial error on invalid address * clean up edit * Click to open modal * Create AddToAddressBookModal component * Modal styling and layout * modal i18n * Add to Addressbook * ens wip * ens wip * ENS Resolution * Reset input * Send to explicit address * Happy Path Complete * Add back error checking * Reset send-to when emptying input * Add back warning object * Fix linter * Fix unit test #1 - fix import paths * Remove dead tests * One more to go * Fix all unit tests * add unit test for reducers and actions * test rendering AddRecipient * Add tests for dialog boxes in AddRecipient * Add test for validating * Fix linter * Fix e2e tests * Token send e2e fix * Style View Contact * Style edit-contact * Fix e2e * Fix from-import-beta-ui e2e spec * Make section header say "add recipient” by default * Auto-focus add recipient input * Update placeholder text * Update input title font size * Auto advance to next step if user paste a valid address * Ellipsify address when recipient is selected * Fix app header background color on desktop * Give each form row a margin of 16px * Use .container/.component naming pattern for ens-input * Auto-focus on input when add to addressbook modal is opened; Save on Enter * Fix and add unit test * Fix selectors name in e2e tests * Correct e2e test token amount for address-book-send changes * Adds e2e test for editing a transaction * Delete test/integration/lib/send-new-ui.js * Add tests for amount max button and high value error on send screen to test/e2e/metamask-ui.spec.js * lint and revert to address as object keys * add chainId based on current network to address book entry * fix test * only display contacts for the current network * Improve ENS message when not found on current network * Add error to indicate when network does not support ENS * bump gaba * address book, resolve comments * Move contact-list to its own component * De-duplicate getaddressbook selector and refactor name selection logic in contact-list-tab/ * Use contact-list component in contact-list-tab.component (i.e. in settings) * Improve/fix settings headers for popup and browser views * Lint fixes related to address book updates * Add 'My accounts' page to settings address book * Update add new contact button in settings to match floating circular design * Improve styles of view contact page * Improve styles and labels of the add-contact.component * Further lint fixes related to address book updates * Update unit tests as per address book updates * Ensure that contact list groups are sorted alphabetically * Refactor settings component to use a container for connection to redux; allow display of addressbook name in settings header * Decouple ens-input.component from send context * Add ens resolution to add contact screen in settings * Switching networks when an ens address is shown on send form removes the ens address. * Resolve send screen search for ensAddress to matching address book entry if it exists * Show resolved ens icon and address if exists (settings: add-contact.component) * Make the displayed and copied address in view-contact.component the checksummed address * Default alias state prop in AddToAddressBookModal to empty string * Use keyCode to detect enter key in AddToAddressBookModal * Ensure add-contact component properly updates after QR code detection * Fix display of all recents after clicking 'Load More' in contact list * Fix send screen contact searching after network switching * Code cleanup related to address book changes * Update unit tests for address book changes * Update ENS name not found on network message * Add ens registration error message * Cancel on edit mode takes user back to view screen * Adds support for memo to settings contact list view and edit screens * Modify designs of edit and view contact in popup environment * Update settings content list UX to show split columns in fullscreen and proper internal navigation * Correct background address book API usages in UI --- app/_locales/en/messages.json | 81 ++++++++++++++++++++++++++++++++++++++ app/images/check-green-solid.svg | 4 ++ app/images/close-gray.svg | 4 ++ app/images/qr-blue.svg | 7 ++++ app/images/search-black.svg | 4 ++ app/scripts/metamask-controller.js | 1 + 6 files changed, 101 insertions(+) create mode 100644 app/images/check-green-solid.svg create mode 100755 app/images/close-gray.svg create mode 100644 app/images/qr-blue.svg create mode 100644 app/images/search-black.svg (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e69b3dc36..1f60bfa57 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -80,12 +80,21 @@ "activityLog": { "message": "activity log" }, + "add": { + "message": "Add" + }, "address": { "message": "Address" }, "addNetwork": { "message": "Add Network" }, + "addRecipient": { + "message": "Add Recipient" + }, + "addressBook": { + "message": "Address Book" + }, "advanced": { "message": "Advanced" }, @@ -98,6 +107,18 @@ "addCustomToken": { "message": "Add custom token" }, + "addToAddressBook": { + "message": "Add to address book" + }, + "addToAddressBookModalPlaceholder": { + "message": "e.g. John D." + }, + "addAlias": { + "message": "Add alias" + }, + "addEthAddress": { + "message": "Add an Ethereum address" + }, "addToken": { "message": "Add Token" }, @@ -172,6 +193,9 @@ "back": { "message": "Back" }, + "backToAll": { + "message": "Back to All" + }, "balance": { "message": "Balance" }, @@ -354,6 +378,12 @@ "connectToTrezor": { "message": "Connect to Trezor" }, + "contactList": { + "message": "Contact List" + }, + "contactListDescription": { + "message": "Add, edit, remove, and manage your contacts" + }, "continue": { "message": "Continue" }, @@ -463,6 +493,9 @@ "delete": { "message": "Delete" }, + "deleteAccount": { + "message": "Delete Account" + }, "denExplainer": { "message": "Your DEN is your password-encrypted storage within MetaMask." }, @@ -529,6 +562,9 @@ "editAccountName": { "message": "Edit Account Name" }, + "editContact":{ + "message": "Edit Contact" + }, "editingTransaction": { "message": "Make changes to your transaction" }, @@ -571,6 +607,15 @@ "ensNameNotFound": { "message": "ENS name not found" }, + "ensRegistrationError": { + "message": "Error in ENS name registration" + }, + "ensNotFoundOnCurrentNetwork": { + "message": "ENS name not found on the current network. Try switching to Main Ethereum Network." + }, + "enterAnAlias": { + "message": "Enter an alias" + }, "enterPassword": { "message": "Enter password" }, @@ -583,6 +628,9 @@ "eth": { "message": "ETH" }, + "ethereumPublicAddress": { + "message": "Ethereum Public Address" + }, "etherscanView": { "message": "View account on Etherscan" }, @@ -893,6 +941,9 @@ "loadingTokens": { "message": "Loading Tokens..." }, + "loadMore": { + "message": "Load More" + }, "localhost": { "message": "Localhost 8545" }, @@ -914,6 +965,9 @@ "memorizePhrase": { "message": "Memorize this phrase." }, + "memo": { + "message": "memo" + }, "menu": { "message": "Menu" }, @@ -947,6 +1001,12 @@ "myAccounts": { "message": "My Accounts" }, + "myWalletAccounts": { + "message": "My Wallet Accounts" + }, + "myWalletAccountsDescription": { + "message": "All of your MetaMask created accounts will automatically be added to this section." + }, "mustSelectOne": { "message": "Must select at least 1 token." }, @@ -979,10 +1039,16 @@ "newAccount": { "message": "New Account" }, + "newAccountDetectedDialogMessage": { + "message": "New address detected! Click here to add to your address book." + }, "newAccountNumberName": { "message": "Account $1", "description": "Default name of next account to be created on create account screen" }, + "newContact": { + "message": "New Contact" + }, "newContract": { "message": "New Contract" }, @@ -1193,9 +1259,15 @@ "receive": { "message": "Receive" }, + "recents": { + "message": "Recents" + }, "recipientAddress": { "message": "Recipient Address" }, + "recipientAddressPlaceholder": { + "message": "Search, public address (0x), or ENS" + }, "refundAddress": { "message": "Your Refund Address" }, @@ -1670,6 +1742,9 @@ "transfer": { "message": "Transfer" }, + "transferBetweenAccounts": { + "message": "Transfer between my accounts" + }, "transferFrom": { "message": "Transfer From" }, @@ -1750,6 +1825,9 @@ "useOldUI": { "message": "Use old UI" }, + "userName":{ + "message": "Username" + }, "validFileImport": { "message": "You must select a valid file to import." }, @@ -1762,6 +1840,9 @@ "viewinExplorer": { "message": "View in Explorer" }, + "viewContact": { + "message": "View Contact" + }, "viewOnCustomBlockExplorer": { "message": "View at $1" }, diff --git a/app/images/check-green-solid.svg b/app/images/check-green-solid.svg new file mode 100644 index 000000000..3e58e8dcc --- /dev/null +++ b/app/images/check-green-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/images/close-gray.svg b/app/images/close-gray.svg new file mode 100755 index 000000000..fca1c4740 --- /dev/null +++ b/app/images/close-gray.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/images/qr-blue.svg b/app/images/qr-blue.svg new file mode 100644 index 000000000..54434295a --- /dev/null +++ b/app/images/qr-blue.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/images/search-black.svg b/app/images/search-black.svg new file mode 100644 index 000000000..7b7db5124 --- /dev/null +++ b/app/images/search-black.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 84a25b008..8ab2bc5dc 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -460,6 +460,7 @@ module.exports = class MetamaskController extends EventEmitter { // AddressController setAddressBook: this.addressBookController.set.bind(this.addressBookController), + removeFromAddressBook: this.addressBookController.delete.bind(this.addressBookController), // AppStateController setLastActiveTime: nodeify(this.appStateController.setLastActiveTime, this.appStateController), -- cgit v1.2.3 From 4d88e1cf862c3ae174780cd888d7703685db23e7 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Wed, 31 Jul 2019 17:47:11 -0230 Subject: Enable indent linting via ESLint (#6936) * Enable indent linting via ESLint * yarn run lint:fix --- app/scripts/controllers/computed-balances.js | 2 +- app/scripts/controllers/detect-tokens.js | 2 +- .../controllers/network/contract-addresses.js | 8 +- app/scripts/controllers/preferences.js | 36 ++++---- app/scripts/controllers/transactions/index.js | 26 +++--- .../transactions/lib/tx-state-history-helper.js | 8 +- app/scripts/controllers/transactions/lib/util.js | 10 +- .../controllers/transactions/pending-tx-tracker.js | 4 +- .../controllers/transactions/tx-state-manager.js | 10 +- app/scripts/edge-encryptor.js | 94 +++++++++---------- app/scripts/lib/account-tracker.js | 18 ++-- app/scripts/lib/backend-metametrics.js | 10 +- app/scripts/lib/message-manager.js | 2 +- app/scripts/lib/personal-message-manager.js | 2 +- app/scripts/metamask-controller.js | 102 ++++++++++----------- app/scripts/migrations/018.js | 6 +- app/scripts/migrations/019.js | 10 +- app/scripts/migrations/024.js | 2 +- app/scripts/migrations/031.js | 10 +- app/scripts/platforms/extension.js | 8 +- 20 files changed, 185 insertions(+), 185 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/computed-balances.js b/app/scripts/controllers/computed-balances.js index e04ce2ef7..caa061df4 100644 --- a/app/scripts/controllers/computed-balances.js +++ b/app/scripts/controllers/computed-balances.js @@ -65,7 +65,7 @@ class ComputedbalancesController { syncAllAccountsFromStore (store) { const upstream = Object.keys(store.accounts) const balances = Object.keys(this.balances) - .map(address => this.balances[address]) + .map(address => this.balances[address]) // Follow new addresses for (const address in balances) { diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index f0ceab8e6..e6e993073 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -54,7 +54,7 @@ class DetectTokensController { }) } - /** + /** * Find if selectedAddress has tokens with contract in contractAddress. * * @param {string} contractAddress Hex address of the token contract to explore. diff --git a/app/scripts/controllers/network/contract-addresses.js b/app/scripts/controllers/network/contract-addresses.js index 5cd7da1d0..f9385accd 100644 --- a/app/scripts/controllers/network/contract-addresses.js +++ b/app/scripts/controllers/network/contract-addresses.js @@ -4,8 +4,8 @@ const SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN = '0xb8e671734ce5c8d7dfbbea5574fa4cf3 const SINGLE_CALL_BALANCES_ADDRESS_KOVAN = '0xb1d3fbb2f83aecd196f474c16ca5d9cffa0d0ffc' module.exports = { - SINGLE_CALL_BALANCES_ADDRESS, - SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, - SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, - SINGLE_CALL_BALANCES_ADDRESS_KOVAN, + SINGLE_CALL_BALANCES_ADDRESS, + SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, + SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, + SINGLE_CALL_BALANCES_ADDRESS_KOVAN, } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 4197781d2..24df29c1d 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -68,7 +68,7 @@ class PreferencesController { return this.setFeatureFlag(key, value) } } -// PUBLIC METHODS + // PUBLIC METHODS /** * Sets the {@code forgottenPassword} state property @@ -129,9 +129,9 @@ class PreferencesController { * @param {String} type Indicates the type of first time flow - create or import - the user wishes to follow * */ - setFirstTimeFlowType (type) { - this.store.updateState({ firstTimeFlowType: type }) - } + setFirstTimeFlowType (type) { + this.store.updateState({ firstTimeFlowType: type }) + } getSuggestedTokens () { @@ -493,22 +493,22 @@ class PreferencesController { * @returns {Promise} Promise resolving to updated frequentRpcList. * */ - addToFrequentRpcList (url, chainId, ticker = 'ETH', nickname = '', rpcPrefs = {}) { - const rpcList = this.getFrequentRpcListDetail() - const index = rpcList.findIndex((element) => { return element.rpcUrl === url }) - if (index !== -1) { - rpcList.splice(index, 1) - } - if (url !== 'http://localhost:8545') { - let checkedChainId - if (!!chainId && !Number.isNaN(parseInt(chainId))) { - checkedChainId = chainId - } - rpcList.push({ rpcUrl: url, chainId: checkedChainId, ticker, nickname, rpcPrefs }) + addToFrequentRpcList (url, chainId, ticker = 'ETH', nickname = '', rpcPrefs = {}) { + const rpcList = this.getFrequentRpcListDetail() + const index = rpcList.findIndex((element) => { return element.rpcUrl === url }) + if (index !== -1) { + rpcList.splice(index, 1) + } + if (url !== 'http://localhost:8545') { + let checkedChainId + if (!!chainId && !Number.isNaN(parseInt(chainId))) { + checkedChainId = chainId } - this.store.updateState({ frequentRpcListDetail: rpcList }) - return Promise.resolve(rpcList) + rpcList.push({ rpcUrl: url, chainId: checkedChainId, ticker, nickname, rpcPrefs }) } + this.store.updateState({ frequentRpcListDetail: rpcList }) + return Promise.resolve(rpcList) + } /** * Removes custom RPC url from state. diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index c4371c25b..a33b46851 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -129,7 +129,7 @@ class TransactionController extends EventEmitter { } } -/** + /** Adds a tx to the txlist @emits ${txMeta.id}:unapproved */ @@ -220,7 +220,7 @@ class TransactionController extends EventEmitter { return txMeta } -/** + /** adds the tx gas defaults: gas && gasPrice @param txMeta {Object} - the txMeta object @returns {Promise} resolves with txMeta @@ -495,9 +495,9 @@ class TransactionController extends EventEmitter { this.txStateManager.updateTx(txMeta, 'transactions#setTxHash') } -// -// PRIVATE METHODS -// + // + // PRIVATE METHODS + // /** maps methods for convenience*/ _mapMethods () { /** @returns the state in transaction controller */ @@ -537,14 +537,14 @@ class TransactionController extends EventEmitter { loadingDefaults: true, }).forEach((tx) => { this.addTxGasDefaults(tx) - .then((txMeta) => { - txMeta.loadingDefaults = false - this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') - }).catch((error) => { - tx.loadingDefaults = false - this.txStateManager.updateTx(tx, 'failed to estimate gas during boot cleanup.') - this.txStateManager.setTxStatusFailed(tx.id, error) - }) + .then((txMeta) => { + txMeta.loadingDefaults = false + this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') + }).catch((error) => { + tx.loadingDefaults = false + this.txStateManager.updateTx(tx, 'failed to estimate gas during boot cleanup.') + this.txStateManager.setTxStatusFailed(tx.id, error) + }) }) this.txStateManager.getFilteredTxList({ diff --git a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js index 4562568e9..76fc5c35b 100644 --- a/app/scripts/controllers/transactions/lib/tx-state-history-helper.js +++ b/app/scripts/controllers/transactions/lib/tx-state-history-helper.js @@ -17,10 +17,10 @@ function migrateFromSnapshotsToDiffs (longHistory) { return ( longHistory // convert non-initial history entries into diffs - .map((entry, index) => { - if (index === 0) return entry - return generateHistoryEntry(longHistory[index - 1], entry) - }) + .map((entry, index) => { + if (index === 0) return entry + return generateHistoryEntry(longHistory[index - 1], entry) + }) ) } diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index 5a8a0cefe..0d2ddddef 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -26,7 +26,7 @@ const normalizers = { gasPrice: gasPrice => addHexPrefix(gasPrice), } - /** +/** normalizes txParams @param txParams {object} @returns {object} normalized txParams @@ -40,7 +40,7 @@ function normalizeTxParams (txParams, LowerCase) { return normalizedTxParams } - /** +/** validates txParams @param txParams {object} */ @@ -59,7 +59,7 @@ function validateTxParams (txParams) { } } - /** +/** validates the from field in txParams @param txParams {object} */ @@ -68,7 +68,7 @@ function validateFrom (txParams) { if (!isValidAddress(txParams.from)) throw new Error('Invalid from address') } - /** +/** validates the to field in txParams @param txParams {object} */ @@ -85,7 +85,7 @@ function validateRecipient (txParams) { return txParams } - /** +/** @returns an {array} of states that can be considered final */ function getFinalStates () { diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index bc11f6633..1ef3be36e 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -186,7 +186,7 @@ class PendingTransactionTracker extends EventEmitter { this.emit('tx:warning', txMeta, err) } } - /** + /** checks to see if if the tx's nonce has been used by another transaction @param txMeta {Object} - txMeta object @emits tx:dropped @@ -198,7 +198,7 @@ class PendingTransactionTracker extends EventEmitter { const nextNonce = await this.query.getTransactionCount(from) const { blockNumber } = await this.query.getTransactionByHash(hash) || {} if (!blockNumber && parseInt(nextNonce) > parseInt(nonce)) { - return true + return true } return false } diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 2aa28c270..a91b59918 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -34,7 +34,7 @@ class TransactionStateManager extends EventEmitter { this.store = new ObservableStore( extend({ transactions: [], - }, initState)) + }, initState)) this.txHistoryLimit = txHistoryLimit this.getNetwork = getNetwork } @@ -245,7 +245,7 @@ class TransactionStateManager extends EventEmitter { }) } -/** + /** @param opts {object} - an object of fields to search for eg:
let thingsToLookFor = {
to: '0x0..',
@@ -403,9 +403,9 @@ class TransactionStateManager extends EventEmitter { // Update state this._saveTxList(otherAccountTxs) } -// -// PRIVATE METHODS -// + // + // PRIVATE METHODS + // // STATUS METHODS // statuses: diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js index cfb241ec9..012672ed2 100644 --- a/app/scripts/edge-encryptor.js +++ b/app/scripts/edge-encryptor.js @@ -14,23 +14,23 @@ class EdgeEncryptor { * @returns {Promise} Promise resolving to an object with ciphertext */ encrypt (password, dataObject) { - var salt = this._generateSalt() - return this._keyFromPassword(password, salt) - .then(function (key) { - var data = JSON.stringify(dataObject) - var dataBuffer = Unibabel.utf8ToBuffer(data) - var vector = global.crypto.getRandomValues(new Uint8Array(16)) - var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) + var salt = this._generateSalt() + return this._keyFromPassword(password, salt) + .then(function (key) { + var data = JSON.stringify(dataObject) + var dataBuffer = Unibabel.utf8ToBuffer(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) - var buffer = new Uint8Array(resultbuffer) - var vectorStr = Unibabel.bufferToBase64(vector) - var vaultStr = Unibabel.bufferToBase64(buffer) - return JSON.stringify({ - data: vaultStr, - iv: vectorStr, - salt: salt, - }) - }) + var buffer = new Uint8Array(resultbuffer) + var vectorStr = Unibabel.bufferToBase64(vector) + var vaultStr = Unibabel.bufferToBase64(buffer) + return JSON.stringify({ + data: vaultStr, + iv: vectorStr, + salt: salt, + }) + }) } /** @@ -41,25 +41,25 @@ class EdgeEncryptor { * @returns {Promise} Promise resolving to copy of decrypted object */ decrypt (password, text) { - const payload = JSON.parse(text) - const salt = payload.salt - return this._keyFromPassword(password, salt) - .then(function (key) { - const encryptedData = Unibabel.base64ToBuffer(payload.data) - const vector = Unibabel.base64ToBuffer(payload.iv) - return new Promise((resolve, reject) => { - var result - try { - result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) - } catch (err) { - return reject(new Error('Incorrect password')) - } - const decryptedData = new Uint8Array(result) - const decryptedStr = Unibabel.bufferToUtf8(decryptedData) - const decryptedObj = JSON.parse(decryptedStr) - resolve(decryptedObj) - }) - }) + const payload = JSON.parse(text) + const salt = payload.salt + return this._keyFromPassword(password, salt) + .then(function (key) { + const encryptedData = Unibabel.base64ToBuffer(payload.data) + const vector = Unibabel.base64ToBuffer(payload.iv) + return new Promise((resolve, reject) => { + var result + try { + result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) + } catch (err) { + return reject(new Error('Incorrect password')) + } + const decryptedData = new Uint8Array(result) + const decryptedStr = Unibabel.bufferToUtf8(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + resolve(decryptedObj) + }) + }) } /** @@ -72,14 +72,14 @@ class EdgeEncryptor { */ _keyFromPassword (password, salt) { - var passBuffer = Unibabel.utf8ToBuffer(password) - var saltBuffer = Unibabel.base64ToBuffer(salt) - const iterations = 10000 - const length = 32 // SHA256 hash size - return new Promise((resolve) => { - var key = asmcrypto.Pbkdf2HmacSha256(passBuffer, saltBuffer, iterations, length) - resolve(key) - }) + var passBuffer = Unibabel.utf8ToBuffer(password) + var saltBuffer = Unibabel.base64ToBuffer(salt) + const iterations = 10000 + const length = 32 // SHA256 hash size + return new Promise((resolve) => { + var key = asmcrypto.Pbkdf2HmacSha256(passBuffer, saltBuffer, iterations, length) + resolve(key) + }) } /** @@ -89,10 +89,10 @@ class EdgeEncryptor { * @returns {string} Randomized base64 encoded data */ _generateSalt (byteCount = 32) { - var view = new Uint8Array(byteCount) - global.crypto.getRandomValues(view) - var b64encoded = btoa(String.fromCharCode.apply(null, view)) - return b64encoded + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded } } diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 24c5ef7ee..1cbf867cb 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -183,23 +183,23 @@ class AccountTracker { switch (currentNetwork) { case MAINNET_CODE: - await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS) - break + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS) + break case RINKEYBY_CODE: - await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY) - break + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY) + break case ROPSTEN_CODE: - await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN) - break + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN) + break case KOVAN_CODE: - await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_KOVAN) - break + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_KOVAN) + break default: - await Promise.all(addresses.map(this._updateAccount.bind(this))) + await Promise.all(addresses.map(this._updateAccount.bind(this))) } } diff --git a/app/scripts/lib/backend-metametrics.js b/app/scripts/lib/backend-metametrics.js index e3c163c1a..ad7874ead 100644 --- a/app/scripts/lib/backend-metametrics.js +++ b/app/scripts/lib/backend-metametrics.js @@ -15,11 +15,11 @@ function backEndMetaMetricsEvent (metaMaskState, eventData) { const stateEventData = getMetaMetricState({ metamask: metaMaskState }) if (stateEventData.participateInMetaMetrics) { - sendMetaMetricsEvent({ - ...stateEventData, - ...eventData, - url: METAMETRICS_TRACKING_URL + '/backend', - }) + sendMetaMetricsEvent({ + ...stateEventData, + ...eventData, + url: METAMETRICS_TRACKING_URL + '/backend', + }) } } diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index ac41de523..898378389 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -61,7 +61,7 @@ module.exports = class MessageManager extends EventEmitter { */ getUnapprovedMsgs () { return this.messages.filter(msg => msg.status === 'unapproved') - .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) + .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) } /** diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 7c13e521a..b5e28be13 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -64,7 +64,7 @@ module.exports = class PersonalMessageManager extends EventEmitter { */ getUnapprovedMsgs () { return this.messages.filter(msg => msg.status === 'unapproved') - .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) + .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) } /** diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 8ab2bc5dc..26dde8288 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -68,7 +68,7 @@ module.exports = class MetamaskController extends EventEmitter { * @constructor * @param {Object} opts */ - constructor (opts) { + constructor (opts) { super() this.defaultMaxListeners = 20 @@ -362,9 +362,9 @@ module.exports = class MetamaskController extends EventEmitter { return publicConfigStore } -//============================================================================= -// EXPOSED TO THE UI SUBSYSTEM -//============================================================================= + //============================================================================= + // EXPOSED TO THE UI SUBSYSTEM + //============================================================================= /** * The metamask-state of the various controllers, made available to the UI @@ -503,9 +503,9 @@ module.exports = class MetamaskController extends EventEmitter { } -//============================================================================= -// VAULT / KEYRING RELATED METHODS -//============================================================================= + //============================================================================= + // VAULT / KEYRING RELATED METHODS + //============================================================================= /** * Creates a new Vault and create a new keychain. @@ -615,7 +615,7 @@ module.exports = class MetamaskController extends EventEmitter { * with the mobile client for syncing purposes * @returns Promise Parts of the state that we want to syncx */ - async fetchInfoToSync () { + async fetchInfoToSync () { // Preferences const { accountTokens, @@ -744,14 +744,14 @@ module.exports = class MetamaskController extends EventEmitter { const keyring = await this.getKeyringForDevice(deviceName, hdPath) let accounts = [] switch (page) { - case -1: - accounts = await keyring.getPreviousPage() - break - case 1: - accounts = await keyring.getNextPage() - break - default: - accounts = await keyring.getFirstPage() + case -1: + accounts = await keyring.getPreviousPage() + break + case 1: + accounts = await keyring.getNextPage() + break + default: + accounts = await keyring.getFirstPage() } // Merge with existing accounts @@ -808,7 +808,7 @@ module.exports = class MetamaskController extends EventEmitter { const { identities } = this.preferencesController.store.getState() return { ...keyState, identities } - } + } // @@ -975,16 +975,16 @@ module.exports = class MetamaskController extends EventEmitter { // sets the status op the message to 'approved' // and removes the metamaskId for signing return this.messageManager.approveMessage(msgParams) - .then((cleanMsgParams) => { + .then((cleanMsgParams) => { // signs the message - return this.keyringController.signMessage(cleanMsgParams) - }) - .then((rawSig) => { + return this.keyringController.signMessage(cleanMsgParams) + }) + .then((rawSig) => { // tells the listener that the message has been signed // and can be returned to the dapp - this.messageManager.setMsgStatusSigned(msgId, rawSig) - return this.getState() - }) + this.messageManager.setMsgStatusSigned(msgId, rawSig) + return this.getState() + }) } /** @@ -1033,16 +1033,16 @@ module.exports = class MetamaskController extends EventEmitter { // sets the status op the message to 'approved' // and removes the metamaskId for signing return this.personalMessageManager.approveMessage(msgParams) - .then((cleanMsgParams) => { + .then((cleanMsgParams) => { // signs the message - return this.keyringController.signPersonalMessage(cleanMsgParams) - }) - .then((rawSig) => { + return this.keyringController.signPersonalMessage(cleanMsgParams) + }) + .then((rawSig) => { // tells the listener that the message has been signed // and can be returned to the dapp - this.personalMessageManager.setMsgStatusSigned(msgId, rawSig) - return this.getState() - }) + this.personalMessageManager.setMsgStatusSigned(msgId, rawSig) + return this.getState() + }) } /** @@ -1142,7 +1142,7 @@ module.exports = class MetamaskController extends EventEmitter { restoreOldVaultAccounts (migratorOutput) { const { serialized } = migratorOutput return this.keyringController.restoreKeyring(serialized) - .then(() => migratorOutput) + .then(() => migratorOutput) } /** @@ -1185,9 +1185,9 @@ module.exports = class MetamaskController extends EventEmitter { }) } -//============================================================================= -// END (VAULT / KEYRING RELATED METHODS) -//============================================================================= + //============================================================================= + // END (VAULT / KEYRING RELATED METHODS) + //============================================================================= /** * Allows a user to try to speed up a transaction by retrying it @@ -1236,9 +1236,9 @@ module.exports = class MetamaskController extends EventEmitter { }) } -//============================================================================= -// PASSWORD MANAGEMENT -//============================================================================= + //============================================================================= + // PASSWORD MANAGEMENT + //============================================================================= /** * Allows a user to begin the seed phrase recovery process. @@ -1260,9 +1260,9 @@ module.exports = class MetamaskController extends EventEmitter { cb() } -//============================================================================= -// SETUP -//============================================================================= + //============================================================================= + // SETUP + //============================================================================= /** * Used to create a multiplexed stream for connecting to an untrusted context @@ -1531,13 +1531,13 @@ module.exports = class MetamaskController extends EventEmitter { return GWEI_BN } return block.gasPrices - .map(hexPrefix => hexPrefix.substr(2)) - .map(hex => new BN(hex, 16)) - .sort((a, b) => { - return a.gt(b) ? 1 : -1 - })[0] + .map(hexPrefix => hexPrefix.substr(2)) + .map(hex => new BN(hex, 16)) + .sort((a, b) => { + return a.gt(b) ? 1 : -1 + })[0] }) - .map(number => number.div(GWEI_BN).toNumber()) + .map(number => number.div(GWEI_BN).toNumber()) const percentileNum = percentile(65, lowestPrices) const percentileNumBn = new BN(percentileNum) @@ -1557,9 +1557,9 @@ module.exports = class MetamaskController extends EventEmitter { return pendingNonce } -//============================================================================= -// CONFIG -//============================================================================= + //============================================================================= + // CONFIG + //============================================================================= // Log blocks @@ -1754,7 +1754,7 @@ module.exports = class MetamaskController extends EventEmitter { this.tokenRatesController.isActive = active } - /** + /** * Creates RPC engine middleware for processing eth_signTypedData requests * * @param {Object} req - request object diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index ffbf24a4b..f6442dacc 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -43,9 +43,9 @@ function transformState (state) { const newHistory = ( txStateHistoryHelper.migrateFromSnapshotsToDiffs(txMeta.history) // remove empty diffs - .filter((entry) => { - return !Array.isArray(entry) || entry.length > 0 - }) + .filter((entry) => { + return !Array.isArray(entry) || entry.length > 0 + }) ) txMeta.history = newHistory return txMeta diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index ce5da6859..7b726c3e8 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -38,13 +38,13 @@ function transformState (state) { if (txMeta.status !== 'submitted') return txMeta const confirmedTxs = txList.filter((tx) => tx.status === 'confirmed') - .filter((tx) => tx.txParams.from === txMeta.txParams.from) - .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) const highestConfirmedNonce = getHighestNonce(confirmedTxs) const pendingTxs = txList.filter((tx) => tx.status === 'submitted') - .filter((tx) => tx.txParams.from === txMeta.txParams.from) - .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) const highestContinuousNonce = getHighestContinuousFrom(pendingTxs, highestConfirmedNonce) const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) @@ -78,7 +78,7 @@ function getHighestContinuousFrom (txList, startPoint) { function getHighestNonce (txList) { const nonces = txList.map((txMeta) => { - const nonce = txMeta.txParams.nonce + const nonce = txMeta.txParams.nonce return parseInt(nonce || '0x0', 16) }) const highestNonce = Math.max.apply(null, nonces) diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js index 6239bab13..5ffaea377 100644 --- a/app/scripts/migrations/024.js +++ b/app/scripts/migrations/024.js @@ -32,7 +32,7 @@ function transformState (state) { txMeta.status === 'unapproved' && txMeta.txParams && txMeta.txParams.from - ) { + ) { txMeta.txParams.from = txMeta.txParams.from.toLowerCase() } return txMeta diff --git a/app/scripts/migrations/031.js b/app/scripts/migrations/031.js index 98d182828..9c8cbeb09 100644 --- a/app/scripts/migrations/031.js +++ b/app/scripts/migrations/031.js @@ -2,14 +2,14 @@ const version = 31 const clone = require('clone') - /* +/* * The purpose of this migration is to properly set the completedOnboarding flag baesd on the state * of the KeyringController. */ module.exports = { version, - migrate: async function (originalVersionedData) { + migrate: async function (originalVersionedData) { const versionedData = clone(originalVersionedData) versionedData.meta.version = version const state = versionedData.data @@ -19,13 +19,13 @@ module.exports = { }, } - function transformState (state) { +function transformState (state) { const { KeyringController, PreferencesController } = state - if (KeyringController && PreferencesController) { + if (KeyringController && PreferencesController) { const { vault } = KeyringController PreferencesController.completedOnboarding = Boolean(vault) } - return state + return state } diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 1007fe24d..43820515d 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -84,10 +84,10 @@ class ExtensionPlatform { extension.notifications.create( url, { - 'type': 'basic', - 'title': title, - 'iconUrl': extension.extension.getURL('../../images/icon-64.png'), - 'message': message, + 'type': 'basic', + 'title': title, + 'iconUrl': extension.extension.getURL('../../images/icon-64.png'), + 'message': message, }) } -- cgit v1.2.3 From e9a63d5d5b428e8ace6423652d8691205bb129f0 Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Thu, 1 Aug 2019 10:54:33 -0230 Subject: Default Privacy Mode to ON, allow force sharing address (#6904) --- app/_locales/en/messages.json | 12 +++ app/images/icons/connect.svg | 7 ++ app/images/icons/info.svg | 5 ++ app/scripts/contentscript.js | 8 ++ app/scripts/controllers/preferences.js | 8 ++ app/scripts/controllers/provider-approval.js | 74 ++++++++++++---- app/scripts/metamask-controller.js | 8 ++ app/scripts/migrations/034.js | 33 +++++++ app/scripts/popup-core.js | 77 ----------------- app/scripts/ui.js | 125 +++++++++++++++++++++++---- 10 files changed, 245 insertions(+), 112 deletions(-) create mode 100644 app/images/icons/connect.svg create mode 100644 app/images/icons/info.svg create mode 100644 app/scripts/migrations/034.js delete mode 100644 app/scripts/popup-core.js (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 1f60bfa57..f15dff386 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1,4 +1,16 @@ { + "shareAddress": { + "message": "Share Address" + }, + "shareAddressToConnect": { + "message": "Share your address to connect to $1?" + }, + "shareAddressInfo": { + "message": "Sharing your address with $1 will allow you to interact with this dapp. This permission is to protect your privacy by default." + }, + "privacyModeDefault": { + "message": "Privacy Mode is now enabled by default" + }, "privacyMode": { "message": "Privacy Mode" }, diff --git a/app/images/icons/connect.svg b/app/images/icons/connect.svg new file mode 100644 index 000000000..24543e8d8 --- /dev/null +++ b/app/images/icons/connect.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/images/icons/info.svg b/app/images/icons/info.svg new file mode 100644 index 000000000..138811bae --- /dev/null +++ b/app/images/icons/info.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index db4d5fd63..7415c5fe9 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -114,6 +114,7 @@ function forwardTrafficBetweenMuxers (channelName, muxA, muxB) { async function setupPublicApi (outStream) { const api = { + forceReloadSite: (cb) => cb(null, forceReloadSite()), getSiteMetadata: (cb) => cb(null, getSiteMetadata()), } const dnode = Dnode(api) @@ -306,3 +307,10 @@ async function domIsReady () { // wait for load await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve, { once: true })) } + +/** + * Reloads the site + */ +function forceReloadSite () { + window.location.reload() +} diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 24df29c1d..d480834f5 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -54,6 +54,7 @@ class PreferencesController { useNativeCurrencyAsPrimaryCurrency: true, }, completedOnboarding: false, + migratedPrivacyMode: false, metaMetricsId: null, metaMetricsSendCount: 0, }, opts.initState) @@ -603,6 +604,13 @@ class PreferencesController { return Promise.resolve(true) } + unsetMigratedPrivacyMode () { + this.store.updateState({ + migratedPrivacyMode: false, + }) + return Promise.resolve() + } + // // PRIVATE METHODS // diff --git a/app/scripts/controllers/provider-approval.js b/app/scripts/controllers/provider-approval.js index 06c499780..00ec0aea1 100644 --- a/app/scripts/controllers/provider-approval.js +++ b/app/scripts/controllers/provider-approval.js @@ -18,12 +18,12 @@ class ProviderApprovalController extends SafeEventEmitter { */ constructor ({ closePopup, keyringController, openPopup, preferencesController } = {}) { super() - this.approvedOrigins = {} this.closePopup = closePopup this.keyringController = keyringController this.openPopup = openPopup this.preferencesController = preferencesController this.store = new ObservableStore({ + approvedOrigins: {}, providerRequests: [], }) } @@ -45,7 +45,7 @@ class ProviderApprovalController extends SafeEventEmitter { } // register the provider request const metadata = await getSiteMetadata(origin) - this._handleProviderRequest(origin, metadata.name, metadata.icon, false, null) + this._handleProviderRequest(origin, metadata.name, metadata.icon) // wait for resolution of request const approved = await new Promise(resolve => this.once(`resolvedRequest:${origin}`, ({ approved }) => resolve(approved))) if (approved) { @@ -63,10 +63,10 @@ class ProviderApprovalController extends SafeEventEmitter { * @param {string} siteTitle - The title of the document requesting full provider access * @param {string} siteImage - The icon of the window requesting full provider access */ - _handleProviderRequest (origin, siteTitle, siteImage, force, tabID) { - this.store.updateState({ providerRequests: [{ origin, siteTitle, siteImage, tabID }] }) + _handleProviderRequest (origin, siteTitle, siteImage) { + this.store.updateState({ providerRequests: [{ origin, siteTitle, siteImage }] }) const isUnlocked = this.keyringController.memStore.getState().isUnlocked - if (!force && this.approvedOrigins[origin] && this.caching && isUnlocked) { + if (this.store.getState().approvedOrigins[origin] && this.caching && isUnlocked) { return } this.openPopup && this.openPopup() @@ -78,11 +78,19 @@ class ProviderApprovalController extends SafeEventEmitter { * @param {string} origin - origin of the domain that had provider access approved */ approveProviderRequestByOrigin (origin) { - this.closePopup && this.closePopup() - const requests = this.store.getState().providerRequests - const providerRequests = requests.filter(request => request.origin !== origin) - this.store.updateState({ providerRequests }) - this.approvedOrigins[origin] = true + if (this.closePopup) { + this.closePopup() + } + + const { approvedOrigins, providerRequests } = this.store.getState() + const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) + this.store.updateState({ + approvedOrigins: { + ...approvedOrigins, + [origin]: true, + }, + providerRequests: remainingProviderRequests, + }) this.emit(`resolvedRequest:${origin}`, { approved: true }) } @@ -92,19 +100,50 @@ class ProviderApprovalController extends SafeEventEmitter { * @param {string} origin - origin of the domain that had provider access approved */ rejectProviderRequestByOrigin (origin) { - this.closePopup && this.closePopup() - const requests = this.store.getState().providerRequests - const providerRequests = requests.filter(request => request.origin !== origin) - this.store.updateState({ providerRequests }) - delete this.approvedOrigins[origin] + if (this.closePopup) { + this.closePopup() + } + + const { approvedOrigins, providerRequests } = this.store.getState() + const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) + + // We're cloning and deleting keys here because we don't want to keep unneeded keys + const _approvedOrigins = Object.assign({}, approvedOrigins) + delete _approvedOrigins[origin] + + this.store.putState({ + approvedOrigins: _approvedOrigins, + providerRequests: remainingProviderRequests, + }) this.emit(`resolvedRequest:${origin}`, { approved: false }) } + /** + * Silently approves access to a full Ethereum provider API for the origin + * + * @param {string} origin - origin of the domain that had provider access approved + */ + forceApproveProviderRequestByOrigin (origin) { + const { approvedOrigins, providerRequests } = this.store.getState() + const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) + this.store.updateState({ + approvedOrigins: { + ...approvedOrigins, + [origin]: true, + }, + providerRequests: remainingProviderRequests, + }) + + this.emit(`forceResolvedRequest:${origin}`, { approved: true, forced: true }) + } + /** * Clears any cached approvals for user-approved origins */ clearApprovedOrigins () { - this.approvedOrigins = {} + this.store.updateState({ + approvedOrigins: {}, + }) } /** @@ -115,8 +154,7 @@ class ProviderApprovalController extends SafeEventEmitter { */ shouldExposeAccounts (origin) { const privacyMode = this.preferencesController.getFeatureFlags().privacyMode - const result = !privacyMode || Boolean(this.approvedOrigins[origin]) - return result + return !privacyMode || Boolean(this.store.getState().approvedOrigins[origin]) } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 26dde8288..158fb3079 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -454,6 +454,7 @@ module.exports = class MetamaskController extends EventEmitter { setPreference: nodeify(preferencesController.setPreference, preferencesController), completeOnboarding: nodeify(preferencesController.completeOnboarding, preferencesController), addKnownMethodData: nodeify(preferencesController.addKnownMethodData, preferencesController), + unsetMigratedPrivacyMode: nodeify(preferencesController.unsetMigratedPrivacyMode, preferencesController), // BlacklistController whitelistPhishingDomain: this.whitelistPhishingDomain.bind(this), @@ -498,6 +499,7 @@ module.exports = class MetamaskController extends EventEmitter { // provider approval approveProviderRequestByOrigin: providerApprovalController.approveProviderRequestByOrigin.bind(providerApprovalController), rejectProviderRequestByOrigin: providerApprovalController.rejectProviderRequestByOrigin.bind(providerApprovalController), + forceApproveProviderRequestByOrigin: providerApprovalController.forceApproveProviderRequestByOrigin.bind(providerApprovalController), clearApprovedOrigins: providerApprovalController.clearApprovedOrigins.bind(providerApprovalController), } } @@ -1285,6 +1287,8 @@ module.exports = class MetamaskController extends EventEmitter { const publicApi = this.setupPublicApi(mux.createStream('publicApi'), originDomain) this.setupProviderConnection(mux.createStream('provider'), originDomain, publicApi) this.setupPublicConfig(mux.createStream('publicConfig'), originDomain) + + this.providerApprovalController.on(`forceResolvedRequest:${originDomain}`, publicApi.forceReloadSite) } /** @@ -1465,6 +1469,10 @@ module.exports = class MetamaskController extends EventEmitter { const publicApi = { // wrap with an await remote + forceReloadSite: async () => { + const remote = await getRemote() + return await pify(remote.forceReloadSite)() + }, getSiteMetadata: async () => { const remote = await getRemote() return await pify(remote.getSiteMetadata)() diff --git a/app/scripts/migrations/034.js b/app/scripts/migrations/034.js new file mode 100644 index 000000000..7c852de96 --- /dev/null +++ b/app/scripts/migrations/034.js @@ -0,0 +1,33 @@ +const version = 34 +const clone = require('clone') + +/** + * The purpose of this migration is to enable the {@code privacyMode} feature flag and set the user as being migrated + * if it was {@code false}. + */ +module.exports = { + version, + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + versionedData.data = transformState(state) + return versionedData + }, +} + +function transformState (state) { + const { PreferencesController } = state + + if (PreferencesController) { + const featureFlags = PreferencesController.featureFlags || {} + + if (!featureFlags.privacyMode && typeof PreferencesController.migratedPrivacyMode === 'undefined') { + // Mark the state has being migrated and enable Privacy Mode + PreferencesController.migratedPrivacyMode = true + featureFlags.privacyMode = true + } + } + + return state +} diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js deleted file mode 100644 index c08e9fa24..000000000 --- a/app/scripts/popup-core.js +++ /dev/null @@ -1,77 +0,0 @@ -const {EventEmitter} = require('events') -const async = require('async') -const Dnode = require('dnode') -const Eth = require('ethjs') -const EthQuery = require('eth-query') -const launchMetamaskUi = require('../../ui') -const StreamProvider = require('web3-stream-provider') -const {setupMultiplex} = require('./lib/stream-utils.js') - -module.exports = initializePopup - -/** - * Asynchronously initializes the MetaMask popup UI - * - * @param {{ container: Element, connectionStream: * }} config Popup configuration object - * @param {Function} cb Called when initialization is complete - */ -function initializePopup ({ container, connectionStream }, cb) { - // setup app - async.waterfall([ - (cb) => connectToAccountManager(connectionStream, cb), - (backgroundConnection, cb) => launchMetamaskUi({ container, backgroundConnection }, cb), - ], cb) -} - -/** - * Establishes streamed connections to background scripts and a Web3 provider - * - * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection - * @param {Function} cb Called when controller connection is established - */ -function connectToAccountManager (connectionStream, cb) { - // setup communication with background - // setup multiplexing - const mx = setupMultiplex(connectionStream) - // connect features - setupControllerConnection(mx.createStream('controller'), cb) - setupWeb3Connection(mx.createStream('provider')) -} - -/** - * Establishes a streamed connection to a Web3 provider - * - * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection - */ -function setupWeb3Connection (connectionStream) { - const providerStream = new StreamProvider() - providerStream.pipe(connectionStream).pipe(providerStream) - connectionStream.on('error', console.error.bind(console)) - providerStream.on('error', console.error.bind(console)) - global.ethereumProvider = providerStream - global.ethQuery = new EthQuery(providerStream) - global.eth = new Eth(providerStream) -} - -/** - * Establishes a streamed connection to the background account manager - * - * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection - * @param {Function} cb Called when the remote account manager connection is established - */ -function setupControllerConnection (connectionStream, cb) { - // this is a really sneaky way of adding EventEmitter api - // to a bi-directional dnode instance - const eventEmitter = new EventEmitter() - const backgroundDnode = Dnode({ - sendUpdate: function (state) { - eventEmitter.emit('update', state) - }, - }) - connectionStream.pipe(backgroundDnode).pipe(connectionStream) - backgroundDnode.once('remote', function (backgroundConnection) { - // setup push events - backgroundConnection.on = eventEmitter.on.bind(eventEmitter) - cb(null, backgroundConnection) - }) -} diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 2dde14b48..a1f904f61 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -1,12 +1,19 @@ -const startPopup = require('./popup-core') const PortStream = require('extension-port-stream') const { getEnvironmentType } = require('./lib/util') -const { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN } = require('./lib/enums') +const { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_POPUP } = require('./lib/enums') const extension = require('extensionizer') const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() const setupSentry = require('./lib/setupSentry') +const {EventEmitter} = require('events') +const Dnode = require('dnode') +const Eth = require('ethjs') +const EthQuery = require('eth-query') +const urlUtil = require('url') +const launchMetaMaskUi = require('../../ui') +const StreamProvider = require('web3-stream-provider') +const {setupMultiplex} = require('./lib/stream-utils.js') const log = require('loglevel') start().catch(log.error) @@ -39,20 +46,8 @@ async function start () { const extensionPort = extension.runtime.connect({ name: windowType }) const connectionStream = new PortStream(extensionPort) - // start ui - const container = document.getElementById('app-content') - startPopup({ container, connectionStream }, (err, store) => { - if (err) return displayCriticalError(err) - - const state = store.getState() - const { metamask: { completedOnboarding } = {} } = state - - if (!completedOnboarding && windowType !== ENVIRONMENT_TYPE_FULLSCREEN) { - global.platform.openExtensionInBrowser() - return - } - }) - + const activeTab = await queryCurrentActiveTab(windowType) + initializeUiWithTab(activeTab) function closePopupIfOpen (windowType) { if (windowType !== ENVIRONMENT_TYPE_NOTIFICATION) { @@ -61,11 +56,107 @@ async function start () { } } - function displayCriticalError (err) { + function displayCriticalError (container, err) { container.innerHTML = '
The MetaMask app failed to load: please open and close MetaMask again to restart.
' container.style.height = '80px' log.error(err.stack) throw err } + function initializeUiWithTab (tab) { + const container = document.getElementById('app-content') + initializeUi(tab, container, connectionStream, (err, store) => { + if (err) { + return displayCriticalError(container, err) + } + + const state = store.getState() + const { metamask: { completedOnboarding } = {} } = state + + if (!completedOnboarding && windowType !== ENVIRONMENT_TYPE_FULLSCREEN) { + global.platform.openExtensionInBrowser() + } + }) + } +} + +async function queryCurrentActiveTab (windowType) { + return new Promise((resolve) => { + // At the time of writing we only have the `activeTab` permission which means + // that this query will only succeed in the popup context (i.e. after a "browserAction") + if (windowType !== ENVIRONMENT_TYPE_POPUP) { + resolve({}) + return + } + + extension.tabs.query({active: true, currentWindow: true}, (tabs) => { + const [activeTab] = tabs + const {title, url} = activeTab + const origin = url ? urlUtil.parse(url).hostname : null + resolve({ + title, origin, url, + }) + }) + }) +} + +function initializeUi (activeTab, container, connectionStream, cb) { + connectToAccountManager(connectionStream, (err, backgroundConnection) => { + if (err) { + return cb(err) + } + + launchMetaMaskUi({ + activeTab, + container, + backgroundConnection, + }, cb) + }) +} + +/** + * Establishes a connection to the background and a Web3 provider + * + * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection + * @param {Function} cb Called when controller connection is established + */ +function connectToAccountManager (connectionStream, cb) { + const mx = setupMultiplex(connectionStream) + setupControllerConnection(mx.createStream('controller'), cb) + setupWeb3Connection(mx.createStream('provider')) +} + +/** + * Establishes a streamed connection to a Web3 provider + * + * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection + */ +function setupWeb3Connection (connectionStream) { + const providerStream = new StreamProvider() + providerStream.pipe(connectionStream).pipe(providerStream) + connectionStream.on('error', console.error.bind(console)) + providerStream.on('error', console.error.bind(console)) + global.ethereumProvider = providerStream + global.ethQuery = new EthQuery(providerStream) + global.eth = new Eth(providerStream) +} + +/** + * Establishes a streamed connection to the background account manager + * + * @param {PortDuplexStream} connectionStream PortStream instance establishing a background connection + * @param {Function} cb Called when the remote account manager connection is established + */ +function setupControllerConnection (connectionStream, cb) { + const eventEmitter = new EventEmitter() + const backgroundDnode = Dnode({ + sendUpdate: function (state) { + eventEmitter.emit('update', state) + }, + }) + connectionStream.pipe(backgroundDnode).pipe(connectionStream) + backgroundDnode.once('remote', function (backgroundConnection) { + backgroundConnection.on = eventEmitter.on.bind(eventEmitter) + cb(null, backgroundConnection) + }) } -- cgit v1.2.3 From 3eff4787757ac22d0a469c91599cdcfd97a2a98c Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 2 Aug 2019 01:27:26 -0230 Subject: I5849 incremental account security (#6874) * Implements ability to defer seed phrase backup to later * Adds incremental-security.spec.js, including test dapp that sends signed tx with stand alone localhost provider * Update metamask-responsive-ui for incremental account security changes * Update backup-notification style and fix responsiveness of seed phrase screen * Remove uneeded files from send-eth-with-private-key-test/ * Apply linguist flags in .gitattributes for send-eth-with-private-key-test/ethereumjs-tx.js * Improve docs in controllers/onboarding.js * Clean up metamask-extension/test/e2e/send-eth-with-private-key-test/index.html * Remove unnecessary newlines in a couple first-time-flow/ files * Fix import of backup-notification in home.component * Fix git attrs file --- app/_locales/en/messages.json | 6 +++++ app/images/meta-shield.svg | 3 +++ app/scripts/controllers/onboarding.js | 43 +++++++++++++++++++++++++++++++++++ app/scripts/metamask-controller.js | 11 +++++++++ 4 files changed, 63 insertions(+) create mode 100644 app/images/meta-shield.svg create mode 100644 app/scripts/controllers/onboarding.js (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index f15dff386..4f9dff0c8 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -208,6 +208,9 @@ "backToAll": { "message": "Back to All" }, + "backupNow": { + "message": "Backup now" + }, "balance": { "message": "Balance" }, @@ -1310,6 +1313,9 @@ "deleteNetworkDescription": { "message": "Are you sure you want to delete this network?" }, + "remindMeLater": { + "message": "Remind me later" + }, "restoreFromSeed": { "message": "Restore account?" }, diff --git a/app/images/meta-shield.svg b/app/images/meta-shield.svg new file mode 100644 index 000000000..346934dbc --- /dev/null +++ b/app/images/meta-shield.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/scripts/controllers/onboarding.js b/app/scripts/controllers/onboarding.js new file mode 100644 index 000000000..18fec4993 --- /dev/null +++ b/app/scripts/controllers/onboarding.js @@ -0,0 +1,43 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +/** + * @typedef {Object} InitState + * @property {Boolean} seedPhraseBackedUp Indicates whether the user has completed the seed phrase backup challenge + */ + +/** + * @typedef {Object} OnboardingOptions + * @property {InitState} initState The initial controller state + */ + +/** + * Controller responsible for maintaining + * a cache of account balances in local storage + */ +class OnboardingController { + /** + * Creates a new controller instance + * + * @param {OnboardingOptions} [opts] Controller configuration parameters + */ + constructor (opts = {}) { + const initState = extend({ + seedPhraseBackedUp: null, + }, opts.initState) + this.store = new ObservableStore(initState) + } + + setSeedPhraseBackedUp (newSeedPhraseBackUpState) { + this.store.updateState({ + seedPhraseBackedUp: newSeedPhraseBackUpState, + }) + } + + getSeedPhraseBackedUp () { + return this.store.getState().seedPhraseBackedUp + } + +} + +module.exports = OnboardingController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 158fb3079..d999bb790 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -28,6 +28,7 @@ const PreferencesController = require('./controllers/preferences') const AppStateController = require('./controllers/app-state') const InfuraController = require('./controllers/infura') const CachedBalancesController = require('./controllers/cached-balances') +const OnboardingController = require('./controllers/onboarding') const RecentBlocksController = require('./controllers/recent-blocks') const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') @@ -158,6 +159,10 @@ module.exports = class MetamaskController extends EventEmitter { initState: initState.CachedBalancesController, }) + this.onboardingController = new OnboardingController({ + initState: initState.OnboardingController, + }) + // ensure accountTracker updates balances after network change this.networkController.on('networkDidChange', () => { this.accountTracker._updateAccounts() @@ -262,6 +267,7 @@ module.exports = class MetamaskController extends EventEmitter { NetworkController: this.networkController.store, InfuraController: this.infuraController.store, CachedBalancesController: this.cachedBalancesController.store, + OnboardingController: this.onboardingController.store, }) this.memStore = new ComposableObservableStore(null, { @@ -283,6 +289,7 @@ module.exports = class MetamaskController extends EventEmitter { ShapeshiftController: this.shapeshiftController, InfuraController: this.infuraController.store, ProviderApprovalController: this.providerApprovalController.store, + OnboardingController: this.onboardingController.store, }) this.memStore.subscribe(this.sendUpdate.bind(this)) } @@ -398,6 +405,7 @@ module.exports = class MetamaskController extends EventEmitter { const txController = this.txController const networkController = this.networkController const providerApprovalController = this.providerApprovalController + const onboardingController = this.onboardingController return { // etc @@ -501,6 +509,9 @@ module.exports = class MetamaskController extends EventEmitter { rejectProviderRequestByOrigin: providerApprovalController.rejectProviderRequestByOrigin.bind(providerApprovalController), forceApproveProviderRequestByOrigin: providerApprovalController.forceApproveProviderRequestByOrigin.bind(providerApprovalController), clearApprovedOrigins: providerApprovalController.clearApprovedOrigins.bind(providerApprovalController), + + // onboarding controller + setSeedPhraseBackedUp: nodeify(onboardingController.setSeedPhraseBackedUp, onboardingController), } } -- cgit v1.2.3 From bb87a0b92ce2392ef0d0dc173fb094513ddb10f7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 2 Aug 2019 10:28:25 -0230 Subject: Add migration to remove `seedWords` state (#6937) The `seedWords` state was removed from the PreferencesController recently in #6920. That state hadn't been used in some time, and there was a long period during which `seedWords` was periodically scrubbed from the state, so it's highly unlikely that it still exists in state for most users. It's hard to guarantee that it _doesn't_ though, especially if a user hasn't opened MetaMask in a few months. --- app/scripts/migrations/035.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/scripts/migrations/035.js (limited to 'app') diff --git a/app/scripts/migrations/035.js b/app/scripts/migrations/035.js new file mode 100644 index 000000000..02b01f588 --- /dev/null +++ b/app/scripts/migrations/035.js @@ -0,0 +1,28 @@ +// next version number +const version = 35 + +/* + +Removes the deprecated 'seedWords' state + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + versionedData.data = transformState(versionedData.data) + return versionedData + }, +} + +function transformState (state) { + if (state.PreferencesController && state.PreferencesController.seedWords !== undefined) { + delete state.PreferencesController.seedWords + } + return state +} -- cgit v1.2.3 From decc604eb8325422ad32bdc3ccdb417b41d1226a Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 2 Aug 2019 10:28:41 -0230 Subject: Increase minimum version of Firefox supported (#6939) The minimum version supported is now Firefox 60. This is the current Extended Support Release. Various features we use were not supported by Firefox 53, such as `browser_action.default_popup`, `tabs.query`, and `permissions:unlimitedStorage`. --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a89962d5a..d14149d81 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -22,7 +22,7 @@ "applications": { "gecko": { "id": "webextension@metamask.io", - "strict_min_version": "53.0" + "strict_min_version": "60.0" } }, "default_locale": "en", -- cgit v1.2.3 From 75d53745826fd7927ec24240f4462bf4226464de Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Fri, 2 Aug 2019 16:29:28 -0230 Subject: Restrict unconnected notice to specific protocols (#6954) The notice asking whether you wanted to connect to a site was showing up in places it shouldn't, like on the Firefox/Chrome settings pages and on our fullscreen extension. It has now been restricted to only be displayed for active tabs with specific protocols: * http * https * dat * dweb * ipfs * ipns * ssb This prevents the notice from being shown on settings pages, browser extensions, and files such as PDFs. --- app/scripts/ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/ui.js b/app/scripts/ui.js index a1f904f61..a99da37a0 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -92,9 +92,9 @@ async function queryCurrentActiveTab (windowType) { extension.tabs.query({active: true, currentWindow: true}, (tabs) => { const [activeTab] = tabs const {title, url} = activeTab - const origin = url ? urlUtil.parse(url).hostname : null + const { hostname: origin, protocol } = url ? urlUtil.parse(url) : {} resolve({ - title, origin, url, + title, origin, protocol, url, }) }) }) -- cgit v1.2.3 From 9d5be5d29fcdab1273e30810f87de4624b8622a1 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 2 Aug 2019 18:01:26 -0230 Subject: New notification fixes (#6955) * Replace use of backup-notification with use of home notification * Pin notifications relative to window * Remove unneeded isRequired condition on some home.component properties * Refactor rendering of home notifications * UX for multiple notifications * Adds dismissal to provider request notification. * Fix test failures The e2e tests have been updated to reference `home-notification` classnames instead of the removed `background-notification`. The active tab proptypes and default values were updated as well. --- app/_locales/en/messages.json | 9 ++++++++ app/scripts/controllers/provider-approval.js | 31 ++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4f9dff0c8..430d1b50c 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -208,6 +208,12 @@ "backToAll": { "message": "Back to All" }, + "backupApprovalNotice": { + "message": "Backup your Secret Recovery code to keep your wallet and funds secure." + }, + "backupApprovalInfo": { + "message": "This secret code is required to recover your wallet in case you lose your device, forget your password, have to re-install MetaMask, or want to access your wallet on another device." + }, "backupNow": { "message": "Backup now" }, @@ -550,6 +556,9 @@ "directDepositEtherExplainer": { "message": "If you already have some Ether, the quickest way to get Ether in your new wallet by direct deposit." }, + "dismiss": { + "message": "Dismiss" + }, "done": { "message": "Done" }, diff --git a/app/scripts/controllers/provider-approval.js b/app/scripts/controllers/provider-approval.js index 00ec0aea1..5d565c385 100644 --- a/app/scripts/controllers/provider-approval.js +++ b/app/scripts/controllers/provider-approval.js @@ -24,6 +24,7 @@ class ProviderApprovalController extends SafeEventEmitter { this.preferencesController = preferencesController this.store = new ObservableStore({ approvedOrigins: {}, + dismissedOrigins: {}, providerRequests: [], }) } @@ -66,7 +67,9 @@ class ProviderApprovalController extends SafeEventEmitter { _handleProviderRequest (origin, siteTitle, siteImage) { this.store.updateState({ providerRequests: [{ origin, siteTitle, siteImage }] }) const isUnlocked = this.keyringController.memStore.getState().isUnlocked - if (this.store.getState().approvedOrigins[origin] && this.caching && isUnlocked) { + const { approvedOrigins, dismissedOrigins } = this.store.getState() + const originAlreadyHandled = approvedOrigins[origin] || dismissedOrigins[origin] + if (originAlreadyHandled && this.caching && isUnlocked) { return } this.openPopup && this.openPopup() @@ -82,13 +85,21 @@ class ProviderApprovalController extends SafeEventEmitter { this.closePopup() } - const { approvedOrigins, providerRequests } = this.store.getState() + const { approvedOrigins, dismissedOrigins, providerRequests } = this.store.getState() + + let _dismissedOrigins = dismissedOrigins + if (dismissedOrigins[origin]) { + _dismissedOrigins = Object.assign({}, dismissedOrigins) + delete _dismissedOrigins[origin] + } + const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) this.store.updateState({ approvedOrigins: { ...approvedOrigins, [origin]: true, }, + dismissedOrigins: _dismissedOrigins, providerRequests: remainingProviderRequests, }) this.emit(`resolvedRequest:${origin}`, { approved: true }) @@ -104,7 +115,7 @@ class ProviderApprovalController extends SafeEventEmitter { this.closePopup() } - const { approvedOrigins, providerRequests } = this.store.getState() + const { approvedOrigins, providerRequests, dismissedOrigins } = this.store.getState() const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) // We're cloning and deleting keys here because we don't want to keep unneeded keys @@ -114,6 +125,10 @@ class ProviderApprovalController extends SafeEventEmitter { this.store.putState({ approvedOrigins: _approvedOrigins, providerRequests: remainingProviderRequests, + dismissedOrigins: { + ...dismissedOrigins, + [origin]: true, + }, }) this.emit(`resolvedRequest:${origin}`, { approved: false }) } @@ -124,13 +139,21 @@ class ProviderApprovalController extends SafeEventEmitter { * @param {string} origin - origin of the domain that had provider access approved */ forceApproveProviderRequestByOrigin (origin) { - const { approvedOrigins, providerRequests } = this.store.getState() + const { approvedOrigins, dismissedOrigins, providerRequests } = this.store.getState() const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin) + + let _dismissedOrigins = dismissedOrigins + if (dismissedOrigins[origin]) { + _dismissedOrigins = Object.assign({}, dismissedOrigins) + delete _dismissedOrigins[origin] + } + this.store.updateState({ approvedOrigins: { ...approvedOrigins, [origin]: true, }, + dismissedOrigins: _dismissedOrigins, providerRequests: remainingProviderRequests, }) -- cgit v1.2.3 From 0e51292acf5146b4eaad01e1616a5241fb6aaacc Mon Sep 17 00:00:00 2001 From: Whymarrh Whitby Date: Tue, 6 Aug 2019 14:46:46 -0230 Subject: Bump manifest version to 7.0.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 17c12493f..1ca2215eb 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "6.7.3", + "version": "7.0.0", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", -- cgit v1.2.3