diff options
Merge branch 'master' into i3580-InternationalizeCurrency
104 files changed, 5310 insertions, 3163 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 14d693d7d..ee2054130 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,7 +23,7 @@ workflows: requires: - prep-deps-npm - prep-build - - job-announce: + - job-publish: requires: - prep-deps-npm - prep-build @@ -67,7 +67,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Install deps via npm command: npm install @@ -75,6 +75,10 @@ jobs: key: dependency-cache-{{ checksum "package-lock.json" }} paths: - node_modules + - save_cache: + key: dependency-cache-{{ .Revision }} + paths: + - node_modules prep-deps-firefox: docker: @@ -97,7 +101,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: build:dist command: npm run dist @@ -116,7 +120,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Get Scss Cache key # this allows us to checksum against a whole directory @@ -135,7 +139,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Test command: npm run lint @@ -146,7 +150,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - restore_cache: key: build-cache-{{ .Revision }} - run: @@ -162,7 +166,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - restore_cache: key: build-cache-{{ .Revision }} - run: @@ -173,13 +177,13 @@ jobs: paths: - test-artifacts - job-announce: + job-publish: docker: - image: circleci/node:8-browsers steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - restore_cache: key: build-cache-{{ .Revision }} - restore_cache: @@ -188,6 +192,9 @@ jobs: path: dist/mascara destination: builds/mascara - store_artifacts: + path: dist/sourcemaps + destination: builds/sourcemaps + - store_artifacts: path: builds destination: builds - store_artifacts: @@ -196,6 +203,9 @@ jobs: - run: name: build:announce command: ./development/metamaskbot-build-announce.js + - run: + name: sentry sourcemaps upload + command: npm run sentry:publish test-unit: docker: @@ -203,7 +213,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: test:coverage command: npm run test:coverage @@ -225,7 +235,7 @@ jobs: && sudo mv /usr/bin/firefox /usr/bin/firefox-old && sudo ln -s /opt/firefox58/firefox /usr/bin/firefox - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Get Scss Cache key # this allows us to checksum against a whole directory @@ -244,7 +254,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Get Scss Cache key # this allows us to checksum against a whole directory @@ -272,7 +282,7 @@ jobs: && sudo mv /usr/bin/firefox /usr/bin/firefox-old && sudo ln -s /opt/firefox58/firefox /usr/bin/firefox - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Get Scss Cache key # this allows us to checksum against a whole directory @@ -291,7 +301,7 @@ jobs: steps: - checkout - restore_cache: - key: dependency-cache-{{ checksum "package-lock.json" }} + key: dependency-cache-{{ .Revision }} - run: name: Get Scss Cache key # this allows us to checksum against a whole directory diff --git a/CHANGELOG.md b/CHANGELOG.md index f39312c7e..ad0e9b3ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,34 @@ ## Current Master - Correctly format currency conversion for locally selected preferred currency. +## 4.5.5 Fri Apr 06 2018 + +- Graceful handling of unknown keys in txParams +- Fixes buggy handling of historical transactions with unknown keys in txParams +- Fix link for 'Learn More' in the Add Token Screen to open to a new tab. +- Fix Download State Logs button [#3791](https://github.com/MetaMask/metamask-extension/issues/3791) +- Enhanced migration error handling + reporting + +## 4.5.4 (aborted) Thu Apr 05 2018 + +- Graceful handling of unknown keys in txParams +- Fix link for 'Learn More' in the Add Token Screen to open to a new tab. +- Fix Download State Logs button [#3791](https://github.com/MetaMask/metamask-extension/issues/3791) +- Fix migration error reporting + +## 4.5.3 Wed Apr 04 2018 + +- Fix bug where checksum address are messing with balance issue [#3843](https://github.com/MetaMask/metamask-extension/issues/3843) +- new ui: fix the confirm transaction screen + +## 4.5.2 Wed Apr 04 2018 + +- Fix overly strict validation where transactions were rejected with hex encoded "chainId" + +## 4.5.1 Tue Apr 03 2018 + +- Fix default network (should be mainnet not Rinkeby) +- Fix Sentry automated error reporting endpoint ## 4.5.0 Mon Apr 02 2018 diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 34575b4dd..b372326ee 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -56,7 +56,7 @@ "message": "Balance:" }, "balances": { - "message": "Your balances" + "message": "Token balance(s)" }, "balanceIsInsufficientGas": { "message": "Insufficient balance for current gas total" diff --git a/app/manifest.json b/app/manifest.json index 73496adfa..dc46f1ca4 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "4.5.0", + "version": "4.5.5", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", diff --git a/app/scripts/background.js b/app/scripts/background.js index 3ad0a7863..5878cd2e8 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -20,6 +20,7 @@ const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const EdgeEncryptor = require('./edge-encryptor') const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code') +const getObjStructure = require('./lib/getObjStructure') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = process.env.METAMASK_DEBUG @@ -77,6 +78,38 @@ async function loadStateFromPersistence () { diskStore.getState() || migrator.generateInitialState(firstTimeState) + // check if somehow state is empty + // this should never happen but new error reporting suggests that it has + // for a small number of users + // https://github.com/metamask/metamask-extension/issues/3919 + if (versionedData && !versionedData.data) { + // try to recover from diskStore incase only localStore is bad + const diskStoreState = diskStore.getState() + if (diskStoreState && diskStoreState.data) { + // we were able to recover (though it might be old) + versionedData = diskStoreState + const vaultStructure = getObjStructure(versionedData) + raven.captureMessage('MetaMask - Empty vault found - recovered from diskStore', { + // "extra" key is required by Sentry + extra: { vaultStructure }, + }) + } else { + // unable to recover, clear state + versionedData = migrator.generateInitialState(firstTimeState) + raven.captureMessage('MetaMask - Empty vault found - unable to recover') + } + } + + // report migration errors to sentry + migrator.on('error', (err) => { + // get vault structure without secrets + const vaultStructure = getObjStructure(versionedData) + raven.captureException(err, { + // "extra" key is required by Sentry + extra: { vaultStructure }, + }) + }) + // migrate data versionedData = await migrator.migrateData(versionedData) if (!versionedData) { @@ -84,7 +117,14 @@ async function loadStateFromPersistence () { } // write to disk - if (localStore.isSupported) localStore.set(versionedData) + if (localStore.isSupported) { + localStore.set(versionedData) + } else { + // throw in setTimeout so as to not block boot + setTimeout(() => { + throw new Error('MetaMask - Localstore not supported') + }) + } // return just the data return versionedData.data @@ -122,9 +162,9 @@ function setupController (initState, initLangCode) { asStream(controller.store), debounce(1000), storeTransform(versionifyData), - storeTransform(syncDataWithExtension), + storeTransform(persistData), (error) => { - log.error('pump hit error', error) + log.error('MetaMask - Persistence pipeline failed', error) } ) @@ -133,7 +173,13 @@ function setupController (initState, initLangCode) { return versionedData } - function syncDataWithExtension(state) { + function persistData(state) { + if (!state) { + throw new Error('MetaMask - updated state is missing', state) + } + if (!state.data) { + throw new Error('MetaMask - updated state does not have data', state) + } if (localStore.isSupported) { localStore.set(state) .catch((err) => { diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 2098fae27..fe1766273 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -131,7 +131,11 @@ function documentElementCheck () { } function blacklistedDomainCheck () { - var blacklistedDomains = ['uscourts.gov', 'dropbox.com'] + var blacklistedDomains = [ + 'uscourts.gov', + 'dropbox.com', + 'webbyawards.com', + ] var currentUrl = window.location.href var currentRegex for (let i = 0; i < blacklistedDomains.length; i++) { diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index 33c31dab9..df41c90c0 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -41,9 +41,9 @@ class BlacklistController { scheduleUpdates () { if (this._phishingUpdateIntervalRef) return - this.updatePhishingList() + this.updatePhishingList().catch(log.warn) this._phishingUpdateIntervalRef = setInterval(() => { - this.updatePhishingList() + this.updatePhishingList().catch(log.warn) }, POLLING_INTERVAL) } @@ -57,4 +57,3 @@ class BlacklistController { } module.exports = BlacklistController - diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 930fc52e8..36b8808aa 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -43,20 +43,19 @@ class CurrencyController { this.store.updateState({ conversionDate }) } - updateConversionRate () { - const currentCurrency = this.getCurrentCurrency() - return fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) - .then(response => response.json()) - .then((parsedResponse) => { + async updateConversionRate () { + let currentCurrency + try { + currentCurrency = this.getCurrentCurrency() + const response = await fetch(`https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`) + const parsedResponse = await response.json() this.setConversionRate(Number(parsedResponse.bid)) this.setConversionDate(Number(parsedResponse.timestamp)) - }).catch((err) => { - if (err) { - console.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) - this.setConversionRate(0) - this.setConversionDate('N/A') - } - }) + } catch (err) { + log.warn(`MetaMask - Failed to query currency conversion:`, currentCurrency, err) + this.setConversionRate(0) + this.setConversionDate('N/A') + } } scheduleConversionInterval () { diff --git a/app/scripts/controllers/infura.js b/app/scripts/controllers/infura.js index 10adb1004..c6b4c9de2 100644 --- a/app/scripts/controllers/infura.js +++ b/app/scripts/controllers/infura.js @@ -19,15 +19,13 @@ class InfuraController { // Responsible for retrieving the status of Infura's nodes. Can return either // ok, degraded, or down. - checkInfuraNetworkStatus () { - return fetch('https://api.infura.io/v1/status/metamask') - .then(response => response.json()) - .then((parsedResponse) => { - this.store.updateState({ - infuraNetworkStatus: parsedResponse, - }) - return parsedResponse - }) + async checkInfuraNetworkStatus () { + const response = await fetch('https://api.infura.io/v1/status/metamask') + const parsedResponse = await response.json() + this.store.updateState({ + infuraNetworkStatus: parsedResponse, + }) + return parsedResponse } scheduleInfuraNetworkCheck () { @@ -35,7 +33,7 @@ class InfuraController { clearInterval(this.conversionInterval) } this.conversionInterval = setInterval(() => { - this.checkInfuraNetworkStatus() + this.checkInfuraNetworkStatus().catch(log.warn) }, POLLING_INTERVAL) } } diff --git a/app/scripts/controllers/shapeshift.js b/app/scripts/controllers/shapeshift.js index 3d955c01f..3bbfaa1c5 100644 --- a/app/scripts/controllers/shapeshift.js +++ b/app/scripts/controllers/shapeshift.js @@ -45,18 +45,19 @@ class ShapeshiftController { }) } - updateTx (tx) { - const url = `https://shapeshift.io/txStat/${tx.depositAddress}` - return fetch(url) - .then((response) => { - return response.json() - }).then((json) => { + async updateTx (tx) { + try { + const url = `https://shapeshift.io/txStat/${tx.depositAddress}` + const response = await fetch(url) + const json = await response.json() tx.response = json if (tx.response.status === 'complete') { tx.time = new Date().getTime() } return tx - }) + } catch (err) { + log.warn(err) + } } saveTx (tx) { diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 31e53554d..336b0d8f7 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -185,9 +185,10 @@ module.exports = class TransactionController extends EventEmitter { async addUnapprovedTransaction (txParams) { // validate - await this.txGasUtil.validateTxParams(txParams) + const normalizedTxParams = this._normalizeTxParams(txParams) + this._validateTxParams(normalizedTxParams) // construct txMeta - let txMeta = this.txStateManager.generateTxMeta({txParams}) + let txMeta = this.txStateManager.generateTxMeta({ txParams: normalizedTxParams }) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) // add default tx params @@ -215,7 +216,6 @@ module.exports = class TransactionController extends EventEmitter { } txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.value = txParams.value || '0x0' - if (txParams.to === null) delete txParams.to // set gasLimit return await this.txGasUtil.analyzeGasUsage(txMeta) } @@ -314,6 +314,60 @@ module.exports = class TransactionController extends EventEmitter { // PRIVATE METHODS // + _normalizeTxParams (txParams) { + // functions that handle normalizing of that key in txParams + const whiteList = { + from: from => ethUtil.addHexPrefix(from).toLowerCase(), + to: to => ethUtil.addHexPrefix(txParams.to).toLowerCase(), + nonce: nonce => ethUtil.addHexPrefix(nonce), + value: value => ethUtil.addHexPrefix(value), + data: data => ethUtil.addHexPrefix(data), + gas: gas => ethUtil.addHexPrefix(gas), + gasPrice: gasPrice => ethUtil.addHexPrefix(gasPrice), + } + + // apply only keys in the whiteList + const normalizedTxParams = {} + Object.keys(whiteList).forEach((key) => { + if (txParams[key]) normalizedTxParams[key] = whiteList[key](txParams[key]) + }) + + return normalizedTxParams + } + + _validateTxParams (txParams) { + this._validateFrom(txParams) + this._validateRecipient(txParams) + if ('value' in txParams) { + const value = txParams.value.toString() + if (value.includes('-')) { + throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) + } + + if (value.includes('.')) { + throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`) + } + } + } + + _validateFrom (txParams) { + if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`) + if (!ethUtil.isValidAddress(txParams.from)) throw new Error('Invalid from address') + } + + _validateRecipient (txParams) { + if (txParams.to === '0x' || txParams.to === null ) { + if (txParams.data) { + delete txParams.to + } else { + throw new Error('Invalid recipient address') + } + } else if ( txParams.to !== undefined && !ethUtil.isValidAddress(txParams.to) ) { + throw new Error('Invalid recipient address') + } + return txParams + } + _markNonceDuplicatesDropped (txId) { this.txStateManager.setTxStatusConfirmed(txId) // get the confirmed transactions nonce and from address diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 28612f763..e3635434e 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -2,14 +2,16 @@ const extension = require('extensionizer') const promisify = require('pify') const allLocales = require('../../_locales/index.json') -const existingLocaleCodes = allLocales.map(locale => locale.code) +const existingLocaleCodes = allLocales.map(locale => locale.code.toLowerCase().replace('_', '-')) async function getFirstPreferredLangCode () { const userPreferredLocaleCodes = await promisify( extension.i18n.getAcceptLanguages, { errorFirst: false } )() - const firstPreferredLangCode = userPreferredLocaleCodes.find(code => existingLocaleCodes.includes(code)) + const firstPreferredLangCode = userPreferredLocaleCodes + .map(code => code.toLowerCase()) + .find(code => existingLocaleCodes.includes(code)) return firstPreferredLangCode || 'en' } diff --git a/app/scripts/lib/getObjStructure.js b/app/scripts/lib/getObjStructure.js new file mode 100644 index 000000000..3db389507 --- /dev/null +++ b/app/scripts/lib/getObjStructure.js @@ -0,0 +1,33 @@ +const clone = require('clone') + +module.exports = getObjStructure + +// This will create an object that represents the structure of the given object +// it replaces all values with the result of their type + +// { +// "data": { +// "CurrencyController": { +// "conversionDate": "number", +// "conversionRate": "number", +// "currentCurrency": "string" +// } +// } + +function getObjStructure(obj) { + const structure = clone(obj) + return deepMap(structure, (value) => { + return value === null ? 'null' : typeof value + }) +} + +function deepMap(target = {}, visit) { + Object.entries(target).forEach(([key, value]) => { + if (typeof value === 'object' && value !== null) { + target[key] = deepMap(value, visit) + } else { + target[key] = visit(value) + } + }) + return target +} diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js index e2999411f..ad3e825c0 100644 --- a/app/scripts/lib/is-popup-or-notification.js +++ b/app/scripts/lib/is-popup-or-notification.js @@ -3,7 +3,8 @@ module.exports = function isPopupOrNotification () { // if (url.match(/popup.html$/) || url.match(/home.html$/)) { // Below regexes needed for feature toggles (e.g. see line ~340 in ui/app/app.js) // Revert below regexes to above commented out regexes before merge to master - if (url.match(/popup.html(?:\?.+)*$/) || url.match(/home.html(?:\?.+)*$/)) { + if (url.match(/popup.html(?:\?.+)*$/) || + url.match(/home.html(?:\?.+)*$/) || url.match(/home.html(?:#.*)*$/)) { return 'popup' } else { return 'notification' diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 4fd2cae92..85c2717ea 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -1,6 +1,9 @@ -class Migrator { +const EventEmitter = require('events') + +class Migrator extends EventEmitter { constructor (opts = {}) { + super() const migrations = opts.migrations || [] // sort migrations by version this.migrations = migrations.sort((a, b) => a.version - b.version) @@ -12,13 +15,29 @@ class Migrator { // run all pending migrations on meta in place async migrateData (versionedData = this.generateInitialState()) { + // get all migrations that have not yet been run const pendingMigrations = this.migrations.filter(migrationIsPending) + // perform each migration for (const index in pendingMigrations) { const migration = pendingMigrations[index] - versionedData = await migration.migrate(versionedData) - if (!versionedData.data) throw new Error('Migrator - migration returned empty data') - if (versionedData.version !== undefined && versionedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') + try { + // attempt migration and validate + const migratedData = await migration.migrate(versionedData) + if (!migratedData.data) throw new Error('Migrator - migration returned empty data') + if (migratedData.version !== undefined && migratedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') + // accept the migration as good + versionedData = migratedData + } catch (err) { + // rewrite error message to add context without clobbering stack + const originalErrorMessage = err.message + err.message = `MetaMask Migration Error #${migration.version}: ${originalErrorMessage}` + console.warn(err.stack) + // emit error instead of throw so as to not break the run (gracefully fail) + this.emit('error', err) + // stop migrating and use state as is + return versionedData + } } return versionedData diff --git a/app/scripts/lib/tx-gas-utils.js b/app/scripts/lib/tx-gas-utils.js index 829b4c421..c579e462a 100644 --- a/app/scripts/lib/tx-gas-utils.js +++ b/app/scripts/lib/tx-gas-utils.js @@ -4,7 +4,7 @@ const { BnMultiplyByFraction, bnToHex, } = require('./util') -const { addHexPrefix, isValidAddress } = require('ethereumjs-util') +const { addHexPrefix } = require('ethereumjs-util') const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. /* @@ -100,37 +100,4 @@ module.exports = class TxGasUtil { // otherwise use blockGasLimit return bnToHex(upperGasLimitBn) } - - async validateTxParams (txParams) { - this.validateFrom(txParams) - this.validateRecipient(txParams) - if ('value' in txParams) { - const value = txParams.value.toString() - if (value.includes('-')) { - throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`) - } - - if (value.includes('.')) { - throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`) - } - } - } - - validateFrom (txParams) { - if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`) - if (!isValidAddress(txParams.from)) throw new Error('Invalid from address') - } - - validateRecipient (txParams) { - if (txParams.to === '0x' || txParams.to === null ) { - if (txParams.data) { - delete txParams.to - } else { - throw new Error('Invalid recipient address') - } - } else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) { - throw new Error('Invalid recipient address') - } - return txParams - } }
\ No newline at end of file diff --git a/app/scripts/lib/tx-state-manager.js b/app/scripts/lib/tx-state-manager.js index 23c915a61..c6d10ee62 100644 --- a/app/scripts/lib/tx-state-manager.js +++ b/app/scripts/lib/tx-state-manager.js @@ -92,8 +92,10 @@ module.exports = class TransactionStateManager extends EventEmitter { // or rejected tx's. // not tx's that are pending or unapproved if (txCount > txHistoryLimit - 1) { - const index = transactions.findIndex((metaTx) => metaTx.status === 'confirmed' || metaTx.status === 'rejected') - transactions.splice(index, 1) + let index = transactions.findIndex((metaTx) => metaTx.status === 'confirmed' || metaTx.status === 'rejected') + if (index !== -1) { + transactions.splice(index, 1) + } } transactions.push(txMeta) this._saveTxList(transactions) @@ -108,6 +110,10 @@ module.exports = class TransactionStateManager extends EventEmitter { updateTx (txMeta, note) { // validate txParams if (txMeta.txParams) { + if (typeof txMeta.txParams.data === 'undefined') { + delete txMeta.txParams.data + } + this.validateTxParams(txMeta.txParams) } @@ -140,8 +146,16 @@ module.exports = class TransactionStateManager extends EventEmitter { validateTxParams(txParams) { Object.keys(txParams).forEach((key) => { const value = txParams[key] - if (typeof value !== 'string') throw new Error(`${key}: ${value} in txParams is not a string`) - if (!ethUtil.isHexPrefixed(value)) throw new Error('is not hex prefixed, everything on txParams must be hex prefixed') + // validate types + switch (key) { + case 'chainId': + if (typeof value !== 'number' && typeof value !== 'string') throw new Error(`${key} in txParams is not a Number or hex string. got: (${value})`) + break + default: + if (typeof value !== 'string') throw new Error(`${key} in txParams is not a string. got: (${value})`) + if (!ethUtil.isHexPrefixed(value)) throw new Error(`${key} in txParams is not hex prefixed. got: (${value})`) + break + } }) } diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js index 8f11e510e..15a9b28d4 100644 --- a/app/scripts/migrations/013.js +++ b/app/scripts/migrations/013.js @@ -27,8 +27,11 @@ module.exports = { function transformState (state) { const newState = state - if (newState.config.provider.type === 'testnet') { - newState.config.provider.type = 'ropsten' + const { config } = newState + if ( config && config.provider ) { + if (config.provider.type === 'testnet') { + newState.config.provider.type = 'ropsten' + } } return newState } diff --git a/app/scripts/migrations/015.js b/app/scripts/migrations/015.js index 4b839580b..5e2f9e63b 100644 --- a/app/scripts/migrations/015.js +++ b/app/scripts/migrations/015.js @@ -28,11 +28,14 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (!txMeta.err) return txMeta - else if (txMeta.err.message === 'Gave up submitting tx.') txMeta.status = 'failed' - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (!txMeta.err) return txMeta + else if (txMeta.err.message === 'Gave up submitting tx.') txMeta.status = 'failed' + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/016.js b/app/scripts/migrations/016.js index 4fc534f1c..048c7a40e 100644 --- a/app/scripts/migrations/016.js +++ b/app/scripts/migrations/016.js @@ -28,14 +28,18 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (!txMeta.err) return txMeta - if (txMeta.err === 'transaction with the same hash was already imported.') { - txMeta.status = 'submitted' - delete txMeta.err - } - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (!txMeta.err) return txMeta + if (txMeta.err === 'transaction with the same hash was already imported.') { + txMeta.status = 'submitted' + delete txMeta.err + } + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/017.js b/app/scripts/migrations/017.js index 24959cd3a..5f6d906d6 100644 --- a/app/scripts/migrations/017.js +++ b/app/scripts/migrations/017.js @@ -27,14 +27,17 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (!txMeta.status === 'failed') return txMeta - if (txMeta.retryCount > 0 && txMeta.retryCount < 2) { - txMeta.status = 'submitted' - delete txMeta.err - } - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (!txMeta.status === 'failed') return txMeta + if (txMeta.retryCount > 0 && txMeta.retryCount < 2) { + txMeta.status = 'submitted' + delete txMeta.err + } + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/018.js b/app/scripts/migrations/018.js index d27fe3f46..bea1fe3da 100644 --- a/app/scripts/migrations/018.js +++ b/app/scripts/migrations/018.js @@ -29,24 +29,27 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - newState.TransactionController.transactions = transactions.map((txMeta) => { - // no history: initialize - if (!txMeta.history || txMeta.history.length === 0) { - const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) - txMeta.history = [snapshot] + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + // no history: initialize + if (!txMeta.history || txMeta.history.length === 0) { + const snapshot = txStateHistoryHelper.snapshotFromTxMeta(txMeta) + txMeta.history = [snapshot] + return txMeta + } + // has history: migrate + const newHistory = ( + txStateHistoryHelper.migrateFromSnapshotsToDiffs(txMeta.history) + // remove empty diffs + .filter((entry) => { + return !Array.isArray(entry) || entry.length > 0 + }) + ) + txMeta.history = newHistory return txMeta - } - // has history: migrate - const newHistory = ( - txStateHistoryHelper.migrateFromSnapshotsToDiffs(txMeta.history) - // remove empty diffs - .filter((entry) => { - return !Array.isArray(entry) || entry.length > 0 - }) - ) - txMeta.history = newHistory - return txMeta - }) + }) + } return newState } diff --git a/app/scripts/migrations/019.js b/app/scripts/migrations/019.js index 072c96370..ce5da6859 100644 --- a/app/scripts/migrations/019.js +++ b/app/scripts/migrations/019.js @@ -29,32 +29,36 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { - newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { - if (txMeta.status !== 'submitted') return txMeta + const transactions = newState.TransactionController.transactions - const confirmedTxs = txList.filter((tx) => tx.status === 'confirmed') - .filter((tx) => tx.txParams.from === txMeta.txParams.from) - .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) - const highestConfirmedNonce = getHighestNonce(confirmedTxs) + newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { + if (txMeta.status !== 'submitted') return txMeta - const pendingTxs = txList.filter((tx) => tx.status === 'submitted') - .filter((tx) => tx.txParams.from === txMeta.txParams.from) - .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) - const highestContinuousNonce = getHighestContinuousFrom(pendingTxs, highestConfirmedNonce) + const confirmedTxs = txList.filter((tx) => tx.status === 'confirmed') + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + const highestConfirmedNonce = getHighestNonce(confirmedTxs) - const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) + const pendingTxs = txList.filter((tx) => tx.status === 'submitted') + .filter((tx) => tx.txParams.from === txMeta.txParams.from) + .filter((tx) => tx.metamaskNetworkId.from === txMeta.metamaskNetworkId.from) + const highestContinuousNonce = getHighestContinuousFrom(pendingTxs, highestConfirmedNonce) - if (parseInt(txMeta.txParams.nonce, 16) > maxNonce + 1) { - txMeta.status = 'failed' - txMeta.err = { - message: 'nonce too high', - note: 'migration 019 custom error', + const maxNonce = Math.max(highestContinuousNonce, highestConfirmedNonce) + + if (parseInt(txMeta.txParams.nonce, 16) > maxNonce + 1) { + txMeta.status = 'failed' + txMeta.err = { + message: 'nonce too high', + note: 'migration 019 custom error', + } } - } - return txMeta - }) + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/022.js b/app/scripts/migrations/022.js index c3c0d53ef..1fbe241e6 100644 --- a/app/scripts/migrations/022.js +++ b/app/scripts/migrations/022.js @@ -28,12 +28,15 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - - newState.TransactionController.transactions = transactions.map((txMeta) => { - if (txMeta.status !== 'submitted' || txMeta.submittedTime) return txMeta - txMeta.submittedTime = (new Date()).getTime() - return txMeta - }) + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (txMeta.status !== 'submitted' || txMeta.submittedTime) return txMeta + txMeta.submittedTime = (new Date()).getTime() + return txMeta + }) + } return newState } diff --git a/app/scripts/migrations/023.js b/app/scripts/migrations/023.js index bce0a5bea..151496b06 100644 --- a/app/scripts/migrations/023.js +++ b/app/scripts/migrations/023.js @@ -28,23 +28,27 @@ module.exports = { function transformState (state) { const newState = state - const transactions = newState.TransactionController.transactions - - if (transactions.length <= 40) return newState - - let reverseTxList = transactions.reverse() - let stripping = true - while (reverseTxList.length > 40 && stripping) { - let txIndex = reverseTxList.findIndex((txMeta) => { - return (txMeta.status === 'failed' || - txMeta.status === 'rejected' || - txMeta.status === 'confirmed' || - txMeta.status === 'dropped') - }) - if (txIndex < 0) stripping = false - else reverseTxList.splice(txIndex, 1) - } - newState.TransactionController.transactions = reverseTxList.reverse() + const { TransactionController } = newState + if (TransactionController && TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + + if (transactions.length <= 40) return newState + + let reverseTxList = transactions.reverse() + let stripping = true + while (reverseTxList.length > 40 && stripping) { + let txIndex = reverseTxList.findIndex((txMeta) => { + return (txMeta.status === 'failed' || + txMeta.status === 'rejected' || + txMeta.status === 'confirmed' || + txMeta.status === 'dropped') + }) + if (txIndex < 0) stripping = false + else reverseTxList.splice(txIndex, 1) + } + + newState.TransactionController.transactions = reverseTxList.reverse() + } return newState } diff --git a/app/scripts/migrations/024.js b/app/scripts/migrations/024.js new file mode 100644 index 000000000..d0b276a79 --- /dev/null +++ b/app/scripts/migrations/024.js @@ -0,0 +1,41 @@ + +const version = 24 + +/* + +This migration ensures that the from address in txParams is to lower case for +all unapproved transactions + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + return versionedData + }, +} + +function transformState (state) { + const newState = state + if (!newState.TransactionController) return newState + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => { + if ( + txMeta.status === 'unapproved' && + txMeta.txParams && + txMeta.txParams.from + ) { + txMeta.txParams.from = txMeta.txParams.from.toLowerCase() + } + return txMeta + }) + return newState +} diff --git a/app/scripts/migrations/025.js b/app/scripts/migrations/025.js new file mode 100644 index 000000000..fc3b20a44 --- /dev/null +++ b/app/scripts/migrations/025.js @@ -0,0 +1,61 @@ +// next version number +const version = 25 + +/* + +normalizes txParams on unconfirmed txs + +*/ +const ethUtil = require('ethereumjs-util') +const clone = require('clone') + +module.exports = { + version, + + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + return versionedData + }, +} + +function transformState (state) { + const newState = state + + if (newState.TransactionController) { + if (newState.TransactionController.transactions) { + const transactions = newState.TransactionController.transactions + newState.TransactionController.transactions = transactions.map((txMeta) => { + if (txMeta.status !== 'unapproved') return txMeta + txMeta.txParams = normalizeTxParams(txMeta.txParams) + return txMeta + }) + } + } + + return newState +} + +function normalizeTxParams (txParams) { + // functions that handle normalizing of that key in txParams + const whiteList = { + from: from => ethUtil.addHexPrefix(from).toLowerCase(), + to: to => ethUtil.addHexPrefix(txParams.to).toLowerCase(), + nonce: nonce => ethUtil.addHexPrefix(nonce), + value: value => ethUtil.addHexPrefix(value), + data: data => ethUtil.addHexPrefix(data), + gas: gas => ethUtil.addHexPrefix(gas), + gasPrice: gasPrice => ethUtil.addHexPrefix(gasPrice), + } + + // apply only keys in the whiteList + const normalizedTxParams = {} + Object.keys(whiteList).forEach((key) => { + if (txParams[key]) normalizedTxParams[key] = whiteList[key](txParams[key]) + }) + + return normalizedTxParams +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 811e06b6b..6c4a51b32 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -34,4 +34,6 @@ module.exports = [ require('./021'), require('./022'), require('./023'), + require('./024'), + require('./025'), ] diff --git a/app/scripts/migrations/template.js b/app/scripts/migrations/template.js new file mode 100644 index 000000000..0915c6bdf --- /dev/null +++ b/app/scripts/migrations/template.js @@ -0,0 +1,29 @@ +// next version number +const version = 0 + +/* + +description of migration and what it does + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: async function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + return versionedData + }, +} + +function transformState (state) { + const newState = state + // transform state here + return newState +} diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 41e2796b4..88614ca5c 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -1,51 +1,62 @@ #!/usr/bin/env node const request = require('request-promise') -const { version } = require('../dist/chrome/manifest.json') - -const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN -const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST -console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST) -const CIRCLE_SHA1 = process.env.CIRCLE_SHA1 -console.log('CIRCLE_SHA1', CIRCLE_SHA1) -const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM -console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM) - -const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop() -const SHORT_SHA1 = CIRCLE_SHA1.slice(0,7) -const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0` - -const MASCARA = `${BUILD_LINK_BASE}/builds/mascara/home.html` -const CHROME = `${BUILD_LINK_BASE}/builds/metamask-chrome-${version}.zip` -const FIREFOX = `${BUILD_LINK_BASE}/builds/metamask-firefox-${version}.zip` -const EDGE = `${BUILD_LINK_BASE}/builds/metamask-edge-${version}.zip` -const OPERA = `${BUILD_LINK_BASE}/builds/metamask-opera-${version}.zip` -const WALKTHROUGH = `${BUILD_LINK_BASE}/test-artifacts/screens/walkthrough%20%28en%29.gif` - -const commentBody = ` -<details> - <summary> - Builds ready [${SHORT_SHA1}]: - <a href="${MASCARA}">mascara</a>, - <a href="${CHROME}">chrome</a>, - <a href="${FIREFOX}">firefox</a>, - <a href="${EDGE}">edge</a>, - <a href="${OPERA}">opera</a> - </summary> - <image src="${WALKTHROUGH}"> -</details> -` - -const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) -const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments` -console.log(`Announcement:\n${commentBody}`) -console.log(`Posting to: ${POST_COMMENT_URI}`) - -request({ - method: 'POST', - uri: POST_COMMENT_URI, - body: JSON_PAYLOAD, - headers: { - 'User-Agent': 'metamaskbot', - 'Authorization': `token ${GITHUB_COMMENT_TOKEN}`, - }, -}) +const VERSION = require('../dist/chrome/manifest.json').version + +start().catch(console.error) + +async function start() { + + const GITHUB_COMMENT_TOKEN = process.env.GITHUB_COMMENT_TOKEN + const CIRCLE_PULL_REQUEST = process.env.CIRCLE_PULL_REQUEST + console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST) + const CIRCLE_SHA1 = process.env.CIRCLE_SHA1 + console.log('CIRCLE_SHA1', CIRCLE_SHA1) + const CIRCLE_BUILD_NUM = process.env.CIRCLE_BUILD_NUM + console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM) + + if (!CIRCLE_PULL_REQUEST) { + console.warn(`No pull request detected for commit "${CIRCLE_SHA1}"`) + return + } + + const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop() + const SHORT_SHA1 = CIRCLE_SHA1.slice(0,7) + const BUILD_LINK_BASE = `https://${CIRCLE_BUILD_NUM}-42009758-gh.circle-artifacts.com/0` + + const MASCARA = `${BUILD_LINK_BASE}/builds/mascara/home.html` + const CHROME = `${BUILD_LINK_BASE}/builds/metamask-chrome-${VERSION}.zip` + const FIREFOX = `${BUILD_LINK_BASE}/builds/metamask-firefox-${VERSION}.zip` + const EDGE = `${BUILD_LINK_BASE}/builds/metamask-edge-${VERSION}.zip` + const OPERA = `${BUILD_LINK_BASE}/builds/metamask-opera-${VERSION}.zip` + const WALKTHROUGH = `${BUILD_LINK_BASE}/test-artifacts/screens/walkthrough%20%28en%29.gif` + + const commentBody = ` + <details> + <summary> + Builds ready [${SHORT_SHA1}]: + <a href="${MASCARA}">mascara</a>, + <a href="${CHROME}">chrome</a>, + <a href="${FIREFOX}">firefox</a>, + <a href="${EDGE}">edge</a>, + <a href="${OPERA}">opera</a> + </summary> + <image src="${WALKTHROUGH}"> + </details> + ` + + const JSON_PAYLOAD = JSON.stringify({ body: commentBody }) + const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments` + console.log(`Announcement:\n${commentBody}`) + console.log(`Posting to: ${POST_COMMENT_URI}`) + + await request({ + method: 'POST', + uri: POST_COMMENT_URI, + body: JSON_PAYLOAD, + headers: { + 'User-Agent': 'metamaskbot', + 'Authorization': `token ${GITHUB_COMMENT_TOKEN}`, + }, + }) + +} diff --git a/development/mock-dev.js b/development/mock-dev.js index a1fb3a86d..f332633d5 100644 --- a/development/mock-dev.js +++ b/development/mock-dev.js @@ -36,15 +36,28 @@ log.setLevel('debug') // const qs = require('qs') -let queryString = qs.parse(window.location.href.split('#')[1]) -let selectedView = queryString.view || 'first time' +const routerPath = window.location.href.split('#')[1] +let queryString = {} +let selectedView + +if (routerPath) { + queryString = qs.parse(routerPath.split('?')[1]) +} + +selectedView = queryString.view || 'first time' const firstState = states[selectedView] updateQueryParams(selectedView) -function updateQueryParams(newView) { +function updateQueryParams (newView) { queryString.view = newView const params = qs.stringify(queryString) - window.location.href = window.location.href.split('#')[0] + `#${params}` + const locationPaths = window.location.href.split('#') + const routerPath = locationPaths[1] || '' + const newPath = locationPaths[0] + '#' + routerPath.split('?')[0] + `?${params}` + + if (window.location.href !== newPath) { + window.location.href = newPath + } } // diff --git a/development/sentry-publish.js b/development/sentry-publish.js new file mode 100644 index 000000000..ab3acabbd --- /dev/null +++ b/development/sentry-publish.js @@ -0,0 +1,55 @@ +#!/usr/bin/env node +const pify = require('pify') +const exec = pify(require('child_process').exec, { multiArgs: true }) +const VERSION = require('../dist/chrome/manifest.json').version + +start().catch(console.error) + +async function start(){ + const authWorked = await checkIfAuthWorks() + if (!authWorked) { + console.log(`Sentry auth failed...`) + } + // check if version exists or not + const versionAlreadyExists = await checkIfVersionExists() + // abort if versions exists + if (versionAlreadyExists) { + console.log(`Version "${VERSION}" already exists on Sentry, aborting sourcemap upload.`) + return + } + + // create sentry release + console.log(`creating Sentry release for "${VERSION}"...`) + await exec(`sentry-cli releases --org 'metamask' --project 'metamask' new ${VERSION}`) + console.log(`removing any existing files from Sentry release "${VERSION}"...`) + await exec(`sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} delete --all`) + // upload sentry source and sourcemaps + console.log(`uploading source files Sentry release "${VERSION}"...`) + await exec(`for FILEPATH in ./dist/chrome/*.js; do [ -e $FILEPATH ] || continue; export FILE=\`basename $FILEPATH\` && echo uploading $FILE && sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} upload $FILEPATH metamask/$FILE; done;`) + console.log(`uploading sourcemaps Sentry release "${VERSION}"...`) + await exec(`sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} upload-sourcemaps ./dist/sourcemaps/ --url-prefix 'sourcemaps'`) + console.log('all done!') +} + +async function checkIfAuthWorks() { + const itWorked = await doesNotFail(async () => { + await exec(`sentry-cli releases --org 'metamask' --project 'metamask' list`) + }) + return itWorked +} + +async function checkIfVersionExists() { + const versionAlreadyExists = await doesNotFail(async () => { + await exec(`sentry-cli releases --org 'metamask' --project 'metamask' info ${VERSION}`) + }) + return versionAlreadyExists +} + +async function doesNotFail(asyncFn) { + try { + await asyncFn() + return true + } catch (err) { + return false + } +} diff --git a/development/states/tx-list-items.js b/development/states/tx-list-items.json index d567e3fed..d567e3fed 100644 --- a/development/states/tx-list-items.js +++ b/development/states/tx-list-items.json diff --git a/docs/QA_Guide.md b/docs/QA_Guide.md new file mode 100644 index 000000000..0b7c0e023 --- /dev/null +++ b/docs/QA_Guide.md @@ -0,0 +1,48 @@ +# QA Guide + +Steps to mark a full pass of QA complete. +* Browsers: Opera, Chrome, Firefox, Edge. +* OS: Ubuntu, Mac OSX, Windows +* Load older version of MetaMask and attempt to simulate updating the extension. +* Open Developer Console in background and popup, inspect errors. +* Watch the state logs + * Transactions (unapproved txs -> rejected/submitted -> confirmed) + * Nonces/LocalNonces +* Vault integrity + * create vault + * Log out + * Log in again + * Log out + * Restore from seed + * Create a second account + * Import a loose account (not related to HD Wallet) + * Import old existing vault seed phrase (pref with test Ether) + * Download State Logs, Priv key file, seed phrase file. +* Send Ether + * by address + * by ens name +* Web3 API Stability + * Create a contract from a Ðapp (remix) + * Load a Ðapp that reads using events/logs (ENS) + * Connect to MEW/MyCypto + * Send a transaction from any Ðapp + - MEW + - EtherDelta + - Leeroy + - Aragon + - (https://tmashuang.github.io/demo-dapp) + * Check account balances +* Token Management + * create a token with tokenfactory (http://tokenfactory.surge.sh/#/factory) + * Add that token to the token view + * Send that token to another metamask address. + * confirm the token arrived. +* Send a transaction and sign a message (https://danfinlay.github.io/js-eth-personal-sign-examples/) for each keyring type + * hd keyring + * imported keyring +* Change network from mainnet → ropsten → rinkeby → localhost (ganache) +* Ganache set blocktime to simulate retryTx in MetaMask +* Copy public key to clipboard +* Export private key + +* Explore changes in master, target features that have been changed and break. diff --git a/mascara/src/app/first-time/confirm-seed-screen.js b/mascara/src/app/first-time/confirm-seed-screen.js new file mode 100644 index 000000000..438f383b1 --- /dev/null +++ b/mascara/src/app/first-time/confirm-seed-screen.js @@ -0,0 +1,151 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import classnames from 'classnames' +import shuffle from 'lodash.shuffle' +import { compose } from 'recompose' +import Identicon from '../../../../ui/app/components/identicon' +import { confirmSeedWords, showModal } from '../../../../ui/app/actions' +import Breadcrumbs from './breadcrumbs' +import LoadingScreen from './loading-screen' +import { DEFAULT_ROUTE } from '../../../../ui/app/routes' + +class ConfirmSeedScreen extends Component { + static propTypes = { + isLoading: PropTypes.bool, + address: PropTypes.string, + seedWords: PropTypes.string, + confirmSeedWords: PropTypes.func, + history: PropTypes.object, + openBuyEtherModal: PropTypes.func, + }; + + static defaultProps = { + seedWords: '', + } + + constructor (props) { + super(props) + const { seedWords } = props + this.state = { + selectedSeeds: [], + shuffledSeeds: seedWords && shuffle(seedWords.split(' ')) || [], + } + } + + componentWillMount () { + const { seedWords, history } = this.props + + if (!seedWords) { + history.push(DEFAULT_ROUTE) + } + } + + handleClick () { + const { confirmSeedWords, history, openBuyEtherModal } = this.props + + confirmSeedWords() + .then(() => { + history.push(DEFAULT_ROUTE) + openBuyEtherModal() + }) + } + + render () { + const { seedWords } = this.props + const { selectedSeeds, shuffledSeeds } = this.state + const isValid = seedWords === selectedSeeds.map(([_, seed]) => seed).join(' ') + + return ( + <div className="first-time-flow"> + { + this.props.isLoading + ? <LoadingScreen loadingMessage="Creating your new account" /> + : ( + <div className="first-view-main-wrapper"> + <div className="first-view-main"> + <div className="backup-phrase"> + <Identicon address={this.props.address} diameter={70} /> + <div className="backup-phrase__content-wrapper"> + <div> + <div className="backup-phrase__title"> + Confirm your Secret Backup Phrase + </div> + <div className="backup-phrase__body-text"> + Please select each phrase in order to make sure it is correct. + </div> + <div className="backup-phrase__confirm-secret"> + {selectedSeeds.map(([_, word], i) => ( + <button + key={i} + className="backup-phrase__confirm-seed-option" + > + {word} + </button> + ))} + </div> + <div className="backup-phrase__confirm-seed-options"> + {shuffledSeeds.map((word, i) => { + const isSelected = selectedSeeds + .filter(([index, seed]) => seed === word && index === i) + .length + + return ( + <button + key={i} + className={classnames('backup-phrase__confirm-seed-option', { + 'backup-phrase__confirm-seed-option--selected': isSelected, + })} + onClick={() => { + if (!isSelected) { + this.setState({ + selectedSeeds: [...selectedSeeds, [i, word]], + }) + } else { + this.setState({ + selectedSeeds: selectedSeeds + .filter(([index, seed]) => !(seed === word && index === i)), + }) + } + }} + > + {word} + </button> + ) + })} + </div> + <button + className="first-time-flow__button" + onClick={() => isValid && this.handleClick()} + disabled={!isValid} + > + Confirm + </button> + </div> + </div> + <Breadcrumbs total={3} currentIndex={1} /> + </div> + </div> + </div> + ) + } + </div> + ) + } +} + +export default compose( + withRouter, + connect( + ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({ + seedWords, + isLoading, + address: selectedAddress, + }), + dispatch => ({ + confirmSeedWords: () => dispatch(confirmSeedWords()), + openBuyEtherModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER'})), + }) + ) +)(ConfirmSeedScreen) diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index 192da3399..6ec05e11d 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -1,20 +1,26 @@ -import EventEmitter from 'events' import React, { Component } from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' -import classnames from 'classnames' -import {createNewVaultAndKeychain} from '../../../../ui/app/actions' -import LoadingScreen from './loading-screen' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' +import { createNewVaultAndKeychain } from '../../../../ui/app/actions' import Breadcrumbs from './breadcrumbs' +import EventEmitter from 'events' import Mascot from '../../../../ui/app/components/mascot' +import classnames from 'classnames' +import { + INITIALIZE_UNIQUE_IMAGE_ROUTE, + INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, + INITIALIZE_NOTICE_ROUTE, +} from '../../../../ui/app/routes' class CreatePasswordScreen extends Component { static propTypes = { isLoading: PropTypes.bool.isRequired, createAccount: PropTypes.func.isRequired, - goToImportWithSeedPhrase: PropTypes.func.isRequired, - goToImportAccount: PropTypes.func.isRequired, - next: PropTypes.func.isRequired, + history: PropTypes.object.isRequired, + isInitialized: PropTypes.bool, + isUnlocked: PropTypes.bool, isMascara: PropTypes.bool.isRequired, } @@ -23,13 +29,21 @@ class CreatePasswordScreen extends Component { confirmPassword: '', } - constructor () { - super() + constructor (props) { + super(props) this.animationEventEmitter = new EventEmitter() } + componentWillMount () { + const { isInitialized, history } = this.props + + if (isInitialized) { + history.push(INITIALIZE_NOTICE_ROUTE) + } + } + isValid () { - const {password, confirmPassword} = this.state + const { password, confirmPassword } = this.state if (!password || !confirmPassword) { return false @@ -47,93 +61,182 @@ class CreatePasswordScreen extends Component { return } - const {password} = this.state - const {createAccount, next} = this.props + const { password } = this.state + const { createAccount, history } = this.props + this.setState({ isLoading: true }) createAccount(password) - .then(next) + .then(() => history.push(INITIALIZE_UNIQUE_IMAGE_ROUTE)) + } + + renderFields () { + const { isMascara, history } = this.props + + return ( + <div className={classnames({ 'first-view-main-wrapper': !isMascara })}> + <div className={classnames({ + 'first-view-main': !isMascara, + 'first-view-main__mascara': isMascara, + })}> + {isMascara && <div className="mascara-info first-view-phone-invisible"> + <Mascot + animationEventEmitter={this.animationEventEmitter} + width="225" + height="225" + /> + <div className="info"> + MetaMask is a secure identity vault for Ethereum. + </div> + <div className="info"> + It allows you to hold ether & tokens, and interact with decentralized applications. + </div> + </div>} + <div className="create-password"> + <div className="create-password__title"> + Create Password + </div> + <input + className="first-time-flow__input" + type="password" + placeholder="New Password (min 8 characters)" + onChange={e => this.setState({password: e.target.value})} + /> + <input + className="first-time-flow__input create-password__confirm-input" + type="password" + placeholder="Confirm Password" + onChange={e => this.setState({confirmPassword: e.target.value})} + /> + <button + className="first-time-flow__button" + disabled={!this.isValid()} + onClick={this.createAccount} + > + Create + </button> + <a + href="" + className="first-time-flow__link create-password__import-link" + onClick={e => { + e.preventDefault() + history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE) + }} + > + Import with seed phrase + </a> + { /* } + <a + href="" + className="first-time-flow__link create-password__import-link" + onClick={e => { + e.preventDefault() + history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE) + }} + > + Import an account + </a> + { */ } + <Breadcrumbs total={3} currentIndex={0} /> + </div> + </div> + </div> + ) } render () { - const { isLoading, goToImportWithSeedPhrase, isMascara } = this.props - - return isLoading - ? <LoadingScreen loadingMessage="Creating your new account" /> - : ( - <div className={classnames({ 'first-view-main-wrapper': !isMascara })}> - <div className={classnames({ - 'first-view-main': !isMascara, - 'first-view-main__mascara': isMascara, - })}> - {isMascara && <div className="mascara-info first-view-phone-invisible"> - <Mascot - animationEventEmitter={this.animationEventEmitter} - width="225" - height="225" - /> - <div className="info"> - MetaMask is a secure identity vault for Ethereum. - </div> - <div className="info"> - It allows you to hold ether & tokens, and interact with decentralized applications. - </div> - </div>} - <div className="create-password"> - <div className="create-password__title"> - Create Password - </div> - <input - className="first-time-flow__input" - type="password" - placeholder="New Password (min 8 characters)" - onChange={e => this.setState({password: e.target.value})} - /> - <input - className="first-time-flow__input create-password__confirm-input" - type="password" - placeholder="Confirm Password" - onChange={e => this.setState({confirmPassword: e.target.value})} - /> - <button - className="first-time-flow__button" - disabled={!this.isValid()} - onClick={this.createAccount} - > - Create - </button> - <a - href="" - className="first-time-flow__link create-password__import-link" - onClick={e => { - e.preventDefault() - goToImportWithSeedPhrase() - }} - > - Import with seed phrase - </a> - { /* } - <a - href="" - className="first-time-flow__link create-password__import-link" - onClick={e => { - e.preventDefault() - goToImportAccount() - }} - > - Import an account - </a> - { */ } - <Breadcrumbs total={3} currentIndex={0} /> + const { history, isMascara } = this.props + + return ( + <div className={classnames({ 'first-view-main-wrapper': !isMascara })}> + <div className={classnames({ + 'first-view-main': !isMascara, + 'first-view-main__mascara': isMascara, + })}> + {isMascara && <div className="mascara-info first-view-phone-invisible"> + <Mascot + animationEventEmitter={this.animationEventEmitter} + width="225" + height="225" + /> + <div className="info"> + MetaMask is a secure identity vault for Ethereum. + </div> + <div className="info"> + It allows you to hold ether & tokens, and interact with decentralized applications. </div> + </div>} + <div className="create-password"> + <div className="create-password__title"> + Create Password + </div> + <input + className="first-time-flow__input" + type="password" + placeholder="New Password (min 8 characters)" + onChange={e => this.setState({password: e.target.value})} + /> + <input + className="first-time-flow__input create-password__confirm-input" + type="password" + placeholder="Confirm Password" + onChange={e => this.setState({confirmPassword: e.target.value})} + /> + <button + className="first-time-flow__button" + disabled={!this.isValid()} + onClick={this.createAccount} + > + Create + </button> + <a + href="" + className="first-time-flow__link create-password__import-link" + onClick={e => { + e.preventDefault() + history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE) + }} + > + Import with seed phrase + </a> + { /* } + <a + href="" + className="first-time-flow__link create-password__import-link" + onClick={e => { + e.preventDefault() + history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE) + }} + > + Import an account + </a> + { */ } + <Breadcrumbs total={3} currentIndex={0} /> </div> </div> - ) + </div> + ) + } +} + +const mapStateToProps = ({ metamask, appState }) => { + const { isInitialized, isUnlocked, isMascara, noActiveNotices } = metamask + const { isLoading } = appState + + return { + isLoading, + isInitialized, + isUnlocked, + isMascara, + noActiveNotices, } } -export default connect( - ({ appState: { isLoading }, metamask: { isMascara } }) => ({ isLoading, isMascara }), - dispatch => ({ - createAccount: password => dispatch(createNewVaultAndKeychain(password)), - }) +export default compose( + withRouter, + connect( + mapStateToProps, + dispatch => ({ + createAccount: password => dispatch(createNewVaultAndKeychain(password)), + }) + ) )(CreatePasswordScreen) diff --git a/mascara/src/app/first-time/import-seed-phrase-screen.js b/mascara/src/app/first-time/import-seed-phrase-screen.js index 86f02ceac..5c2b21b0a 100644 --- a/mascara/src/app/first-time/import-seed-phrase-screen.js +++ b/mascara/src/app/first-time/import-seed-phrase-screen.js @@ -8,16 +8,16 @@ import { displayWarning, unMarkPasswordForgotten, } from '../../../../ui/app/actions' +import { DEFAULT_ROUTE, INITIALIZE_NOTICE_ROUTE } from '../../../../ui/app/routes' class ImportSeedPhraseScreen extends Component { static propTypes = { warning: PropTypes.string, - back: PropTypes.func.isRequired, - next: PropTypes.func.isRequired, createNewVaultAndRestore: PropTypes.func.isRequired, hideWarning: PropTypes.func.isRequired, displayWarning: PropTypes.func, leaveImportSeedScreenState: PropTypes.func, + history: PropTypes.object, }; state = { @@ -64,14 +64,14 @@ class ImportSeedPhraseScreen extends Component { const { password, seedPhrase } = this.state const { createNewVaultAndRestore, - next, displayWarning, leaveImportSeedScreenState, + history, } = this.props leaveImportSeedScreenState() createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase)) - .then(next) + .then(() => history.push(INITIALIZE_NOTICE_ROUTE)) } render () { @@ -86,7 +86,7 @@ class ImportSeedPhraseScreen extends Component { className="import-account__back-button" onClick={e => { e.preventDefault() - this.props.back() + this.props.history.goBack() }} href="#" > diff --git a/mascara/src/app/first-time/index.js b/mascara/src/app/first-time/index.js index 0cc3b4b0e..01e5d67a6 100644 --- a/mascara/src/app/first-time/index.js +++ b/mascara/src/app/first-time/index.js @@ -1,17 +1,26 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' +import { withRouter, Switch, Route } from 'react-router-dom' +import { compose } from 'recompose' import CreatePasswordScreen from './create-password-screen' import UniqueImageScreen from './unique-image-screen' import NoticeScreen from './notice-screen' -import BackupPhraseScreen from './backup-phrase-screen' +import BackupPhraseScreen from './seed-screen' import ImportAccountScreen from './import-account-screen' import ImportSeedPhraseScreen from './import-seed-phrase-screen' +import ConfirmSeed from './confirm-seed-screen' import { - onboardingBuyEthView, - unMarkPasswordForgotten, - showModal, -} from '../../../../ui/app/actions' + INITIALIZE_ROUTE, + INITIALIZE_IMPORT_ACCOUNT_ROUTE, + INITIALIZE_UNIQUE_IMAGE_ROUTE, + INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, + INITIALIZE_NOTICE_ROUTE, + INITIALIZE_BACKUP_PHRASE_ROUTE, + INITIALIZE_CONFIRM_SEED_ROUTE, + INITIALIZE_CREATE_PASSWORD_ROUTE, +} from '../../../../ui/app/routes' +import WelcomeScreen from '../../../../ui/app/welcome-screen' class FirstTimeFlow extends Component { @@ -20,6 +29,10 @@ class FirstTimeFlow extends Component { seedWords: PropTypes.string, address: PropTypes.string, noActiveNotices: PropTypes.bool, + goToBuyEtherView: PropTypes.func, + isUnlocked: PropTypes.bool, + history: PropTypes.object, + welcomeScreenSeen: PropTypes.bool, }; static defaultProps = { @@ -28,145 +41,53 @@ class FirstTimeFlow extends Component { noActiveNotices: false, }; - static SCREEN_TYPE = { - CREATE_PASSWORD: 'create_password', - IMPORT_ACCOUNT: 'import_account', - IMPORT_SEED_PHRASE: 'import_seed_phrase', - UNIQUE_IMAGE: 'unique_image', - NOTICE: 'notice', - BACK_UP_PHRASE: 'back_up_phrase', - CONFIRM_BACK_UP_PHRASE: 'confirm_back_up_phrase', - LOADING: 'loading', - }; - - constructor (props) { - super(props) - this.state = { - screenType: this.getScreenType(), - } - } - - setScreenType (screenType) { - this.setState({ screenType }) - } - - getScreenType () { - const { - isInitialized, - seedWords, - noActiveNotices, - forgottenPassword, - } = this.props - const {SCREEN_TYPE} = FirstTimeFlow - - // return SCREEN_TYPE.NOTICE - - if (forgottenPassword) { - return SCREEN_TYPE.IMPORT_SEED_PHRASE - } - if (!isInitialized) { - return SCREEN_TYPE.CREATE_PASSWORD - } - - if (!noActiveNotices) { - return SCREEN_TYPE.NOTICE - } - - if (seedWords) { - return SCREEN_TYPE.BACK_UP_PHRASE - } - }; - - renderScreen () { - const {SCREEN_TYPE} = FirstTimeFlow - const { - openBuyEtherModal, - address, - restoreCreatePasswordScreen, - forgottenPassword, - leaveImportSeedScreenState, - } = this.props - - switch (this.state.screenType) { - case SCREEN_TYPE.CREATE_PASSWORD: - return ( - <CreatePasswordScreen - next={() => this.setScreenType(SCREEN_TYPE.UNIQUE_IMAGE)} - goToImportAccount={() => this.setScreenType(SCREEN_TYPE.IMPORT_ACCOUNT)} - goToImportWithSeedPhrase={() => this.setScreenType(SCREEN_TYPE.IMPORT_SEED_PHRASE)} - /> - ) - case SCREEN_TYPE.IMPORT_ACCOUNT: - return ( - <ImportAccountScreen - back={() => this.setScreenType(SCREEN_TYPE.CREATE_PASSWORD)} - next={() => this.setScreenType(SCREEN_TYPE.NOTICE)} - /> - ) - case SCREEN_TYPE.IMPORT_SEED_PHRASE: - return ( - <ImportSeedPhraseScreen - back={() => { - leaveImportSeedScreenState() - this.setScreenType(SCREEN_TYPE.CREATE_PASSWORD) - }} - next={() => { - const newScreenType = forgottenPassword ? null : SCREEN_TYPE.NOTICE - this.setScreenType(newScreenType) - }} - /> - ) - case SCREEN_TYPE.UNIQUE_IMAGE: - return ( - <UniqueImageScreen - next={() => this.setScreenType(SCREEN_TYPE.NOTICE)} - /> - ) - case SCREEN_TYPE.NOTICE: - return ( - <NoticeScreen - next={() => this.setScreenType(SCREEN_TYPE.BACK_UP_PHRASE)} - /> - ) - case SCREEN_TYPE.BACK_UP_PHRASE: - return ( - <BackupPhraseScreen - next={() => openBuyEtherModal()} - /> - ) - default: - return <noscript /> - } - } - render () { return ( <div className="first-time-flow"> - {this.renderScreen()} + <Switch> + <Route exact path={INITIALIZE_IMPORT_ACCOUNT_ROUTE} component={ImportAccountScreen} /> + <Route + exact + path={INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE} + component={ImportSeedPhraseScreen} + /> + <Route exact path={INITIALIZE_UNIQUE_IMAGE_ROUTE} component={UniqueImageScreen} /> + <Route exact path={INITIALIZE_NOTICE_ROUTE} component={NoticeScreen} /> + <Route exact path={INITIALIZE_BACKUP_PHRASE_ROUTE} component={BackupPhraseScreen} /> + <Route exact path={INITIALIZE_CONFIRM_SEED_ROUTE} component={ConfirmSeed} /> + <Route exact path={INITIALIZE_CREATE_PASSWORD_ROUTE} component={CreatePasswordScreen} /> + <Route exact path={INITIALIZE_ROUTE} component={WelcomeScreen} /> + </Switch> </div> ) } - } -export default connect( - ({ - metamask: { - isInitialized, - seedWords, - noActiveNotices, - selectedAddress, - forgottenPassword, - } - }) => ({ +const mapStateToProps = ({ metamask }) => { + const { + isInitialized, + seedWords, + noActiveNotices, + selectedAddress, + forgottenPassword, + isMascara, + isUnlocked, + welcomeScreenSeen, + } = metamask + + return { + isMascara, isInitialized, seedWords, noActiveNotices, address: selectedAddress, forgottenPassword, - }), - dispatch => ({ - leaveImportSeedScreenState: () => dispatch(unMarkPasswordForgotten()), - openBuyEtherModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER'})), - }) + isUnlocked, + welcomeScreenSeen, + } +} + +export default compose( + withRouter, + connect(mapStateToProps) )(FirstTimeFlow) diff --git a/mascara/src/app/first-time/notice-screen.js b/mascara/src/app/first-time/notice-screen.js index cbd8f9f5b..a449ccfa9 100644 --- a/mascara/src/app/first-time/notice-screen.js +++ b/mascara/src/app/first-time/notice-screen.js @@ -1,11 +1,14 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import Markdown from 'react-markdown' -import {connect} from 'react-redux' +import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' import debounce from 'lodash.debounce' -import {markNoticeRead} from '../../../../ui/app/actions' +import { markNoticeRead } from '../../../../ui/app/actions' import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' +import { INITIALIZE_BACKUP_PHRASE_ROUTE } from '../../../../ui/app/routes' import LoadingScreen from './loading-screen' class NoticeScreen extends Component { @@ -16,8 +19,15 @@ class NoticeScreen extends Component { date: PropTypes.string, body: PropTypes.string, }), - next: PropTypes.func.isRequired, + location: PropTypes.shape({ + state: PropTypes.shape({ + next: PropTypes.func.isRequired, + }), + }), markNoticeRead: PropTypes.func, + history: PropTypes.object, + isLoading: PropTypes.bool, + noActiveNotices: PropTypes.bool, }; static defaultProps = { @@ -29,17 +39,24 @@ class NoticeScreen extends Component { } componentDidMount () { + if (this.props.noActiveNotices) { + this.props.history.push(INITIALIZE_BACKUP_PHRASE_ROUTE) + } + this.onScroll() } acceptTerms = () => { - const { markNoticeRead, lastUnreadNotice, next } = this.props - const defer = markNoticeRead(lastUnreadNotice) - .then(() => this.setState({ atBottom: false })) - - if ((/terms/gi).test(lastUnreadNotice.title)) { - defer.then(next) - } + const { markNoticeRead, lastUnreadNotice, history } = this.props + markNoticeRead(lastUnreadNotice) + .then(hasActiveNotices => { + if (!hasActiveNotices) { + history.push(INITIALIZE_BACKUP_PHRASE_ROUTE) + } else { + this.setState({ atBottom: false }) + this.onScroll() + } + }) } onScroll = debounce(() => { @@ -64,27 +81,29 @@ class NoticeScreen extends Component { isLoading ? <LoadingScreen /> : ( - <div className="first-view-main-wrapper"> - <div className="first-view-main"> - <div - className="tou" - onScroll={this.onScroll} - > - <Identicon address={address} diameter={70} /> - <div className="tou__title">{title}</div> - <Markdown - className="tou__body markdown" - source={body} - skipHtml - /> - <button - className="first-time-flow__button" - onClick={atBottom && this.acceptTerms} - disabled={!atBottom} + <div className="first-time-flow"> + <div className="first-view-main-wrapper"> + <div className="first-view-main"> + <div + className="tou" + onScroll={this.onScroll} > - Accept - </button> - <Breadcrumbs total={3} currentIndex={2} /> + <Identicon address={address} diameter={70} /> + <div className="tou__title">{title}</div> + <Markdown + className="tou__body markdown" + source={body} + skipHtml + /> + <button + className="first-time-flow__button" + onClick={atBottom && this.acceptTerms} + disabled={!atBottom} + > + Accept + </button> + <Breadcrumbs total={3} currentIndex={2} /> + </div> </div> </div> </div> @@ -93,12 +112,24 @@ class NoticeScreen extends Component { } } -export default connect( - ({ metamask: { selectedAddress, lastUnreadNotice }, appState: { isLoading } }) => ({ - lastUnreadNotice, +const mapStateToProps = ({ metamask, appState }) => { + const { selectedAddress, lastUnreadNotice, noActiveNotices } = metamask + const { isLoading } = appState + + return { address: selectedAddress, - }), - dispatch => ({ - markNoticeRead: notice => dispatch(markNoticeRead(notice)), - }) + lastUnreadNotice, + noActiveNotices, + isLoading, + } +} + +export default compose( + withRouter, + connect( + mapStateToProps, + dispatch => ({ + markNoticeRead: notice => dispatch(markNoticeRead(notice)), + }) + ) )(NoticeScreen) diff --git a/mascara/src/app/first-time/backup-phrase-screen.js b/mascara/src/app/first-time/seed-screen.js index 6819abcf3..d004be77b 100644 --- a/mascara/src/app/first-time/backup-phrase-screen.js +++ b/mascara/src/app/first-time/seed-screen.js @@ -1,13 +1,13 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import {connect} from 'react-redux' +import { connect } from 'react-redux' import classnames from 'classnames' -import shuffle from 'lodash.shuffle' -import {compose, onlyUpdateForPropTypes} from 'recompose' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' import Identicon from '../../../../ui/app/components/identicon' -import {confirmSeedWords} from '../../../../ui/app/actions' import Breadcrumbs from './breadcrumbs' import LoadingScreen from './loading-screen' +import { DEFAULT_ROUTE, INITIALIZE_CONFIRM_SEED_ROUTE } from '../../../../ui/app/routes' const LockIcon = props => ( <svg @@ -36,34 +36,32 @@ const LockIcon = props => ( /> </g> </svg> -); +) class BackupPhraseScreen extends Component { static propTypes = { isLoading: PropTypes.bool.isRequired, address: PropTypes.string.isRequired, - seedWords: PropTypes.string.isRequired, - next: PropTypes.func.isRequired, - confirmSeedWords: PropTypes.func.isRequired, + seedWords: PropTypes.string, + history: PropTypes.object, }; static defaultProps = { - seedWords: '' - }; - - static PAGE = { - SECRET: 'secret', - CONFIRM: 'confirm' - }; + seedWords: '', + } - constructor(props) { - const {seedWords} = props + constructor (props) { super(props) this.state = { isShowingSecret: false, - page: BackupPhraseScreen.PAGE.SECRET, - selectedSeeds: [], - shuffledSeeds: seedWords && shuffle(seedWords.split(' ')), + } + } + + componentWillMount () { + const { seedWords, history } = this.props + + if (!seedWords) { + history.push(DEFAULT_ROUTE) } } @@ -73,7 +71,7 @@ class BackupPhraseScreen extends Component { return ( <div className="backup-phrase__secret"> <div className={classnames('backup-phrase__secret-words', { - 'backup-phrase__secret-words--hidden': !isShowingSecret + 'backup-phrase__secret-words--hidden': !isShowingSecret, })}> {this.props.seedWords} </div> @@ -96,6 +94,7 @@ class BackupPhraseScreen extends Component { renderSecretScreen () { const { isShowingSecret } = this.state + const { history } = this.props return ( <div className="backup-phrase__content-wrapper"> @@ -124,10 +123,7 @@ class BackupPhraseScreen extends Component { <div className="backup-phrase__next-button"> <button className="first-time-flow__button" - onClick={() => isShowingSecret && this.setState({ - isShowingSecret: false, - page: BackupPhraseScreen.PAGE.CONFIRM, - })} + onClick={() => isShowingSecret && history.push(INITIALIZE_CONFIRM_SEED_ROUTE)} disabled={!isShowingSecret} > Next @@ -138,99 +134,6 @@ class BackupPhraseScreen extends Component { ) } - renderConfirmationScreen() { - const { seedWords, confirmSeedWords, next } = this.props; - const { selectedSeeds, shuffledSeeds } = this.state; - const isValid = seedWords === selectedSeeds.map(([_, seed]) => seed).join(' ') - - return ( - <div className="backup-phrase__content-wrapper"> - <div> - <div className="backup-phrase__title">Confirm your Secret Backup Phrase</div> - <div className="backup-phrase__body-text"> - Please select each phrase in order to make sure it is correct. - </div> - <div className="backup-phrase__confirm-secret"> - {selectedSeeds.map(([_, word], i) => ( - <button - key={i} - className="backup-phrase__confirm-seed-option" - > - {word} - </button> - ))} - </div> - <div className="backup-phrase__confirm-seed-options"> - {shuffledSeeds.map((word, i) => { - const isSelected = selectedSeeds - .filter(([index, seed]) => seed === word && index === i) - .length - - return ( - <button - key={i} - className={classnames('backup-phrase__confirm-seed-option', { - 'backup-phrase__confirm-seed-option--selected': isSelected - })} - onClick={() => { - if (!isSelected) { - this.setState({ - selectedSeeds: [...selectedSeeds, [i, word]] - }) - } else { - this.setState({ - selectedSeeds: selectedSeeds - .filter(([index, seed]) => !(seed === word && index === i)) - }) - } - }} - > - {word} - </button> - ) - })} - </div> - <button - className="first-time-flow__button" - onClick={() => isValid && confirmSeedWords().then(next)} - disabled={!isValid} - > - Confirm - </button> - </div> - </div> - ) - } - - renderBack () { - return this.state.page === BackupPhraseScreen.PAGE.CONFIRM - ? ( - <a - className="backup-phrase__back-button" - onClick={e => { - e.preventDefault() - this.setState({ - page: BackupPhraseScreen.PAGE.SECRET - }) - }} - href="#" - > - {`< Back`} - </a> - ) - : null - } - - renderContent () { - switch (this.state.page) { - case BackupPhraseScreen.PAGE.CONFIRM: - return this.renderConfirmationScreen() - case BackupPhraseScreen.PAGE.SECRET: - default: - return this.renderSecretScreen() - } - } - render () { return this.props.isLoading ? <LoadingScreen loadingMessage="Creating your new account" /> @@ -238,9 +141,8 @@ class BackupPhraseScreen extends Component { <div className="first-view-main-wrapper"> <div className="first-view-main"> <div className="backup-phrase"> - {this.renderBack()} <Identicon address={this.props.address} diameter={70} /> - {this.renderContent()} + {this.renderSecretScreen()} </div> </div> </div> @@ -249,15 +151,12 @@ class BackupPhraseScreen extends Component { } export default compose( - onlyUpdateForPropTypes, + withRouter, connect( ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({ seedWords, isLoading, address: selectedAddress, - }), - dispatch => ({ - confirmSeedWords: () => dispatch(confirmSeedWords()), }) ) )(BackupPhraseScreen) diff --git a/mascara/src/app/first-time/unique-image-screen.js b/mascara/src/app/first-time/unique-image-screen.js index ede17ee3d..9555e5318 100644 --- a/mascara/src/app/first-time/unique-image-screen.js +++ b/mascara/src/app/first-time/unique-image-screen.js @@ -1,13 +1,16 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' import {connect} from 'react-redux' import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' +import { INITIALIZE_NOTICE_ROUTE } from '../../../../ui/app/routes' class UniqueImageScreen extends Component { static propTypes = { address: PropTypes.string, - next: PropTypes.func.isRequired, + history: PropTypes.object, } render () { @@ -25,7 +28,7 @@ class UniqueImageScreen extends Component { </div> <button className="first-time-flow__button" - onClick={this.props.next} + onClick={() => this.props.history.push(INITIALIZE_NOTICE_ROUTE)} > Next </button> @@ -37,8 +40,11 @@ class UniqueImageScreen extends Component { } } -export default connect( - ({ metamask: { selectedAddress } }) => ({ - address: selectedAddress, - }) +export default compose( + withRouter, + connect( + ({ metamask: { selectedAddress } }) => ({ + address: selectedAddress, + }) + ) )(UniqueImageScreen) diff --git a/old-ui/app/util.js b/old-ui/app/util.js index 3f8b4dcc3..962832ce7 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -231,6 +231,7 @@ function exportAsFile (filename, data) { window.navigator.msSaveBlob(blob, filename) } else { const elem = window.document.createElement('a') + elem.target = '_blank' elem.href = window.URL.createObjectURL(blob) elem.download = filename document.body.appendChild(elem) diff --git a/package-lock.json b/package-lock.json index 278d4028c..836a66bd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -188,7 +188,7 @@ "integrity": "sha1-AtD3eBwe5eG+WkMSoyX76LGzcjE=", "dev": true, "requires": { - "https-proxy-agent": "2.2.0", + "https-proxy-agent": "2.2.1", "node-fetch": "1.7.3", "progress": "2.0.0", "proxy-from-env": "1.0.0" @@ -213,9 +213,9 @@ } }, "https-proxy-agent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz", - "integrity": "sha512-uUWcfXHvy/dwfM9bqa6AozvAjS32dZSTUYd/4SEpYKRg6LEcPLshksnQYRudM9AyNvUARMfAg5TLjUDyX/K4vA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { "agent-base": "4.2.0", @@ -5127,7 +5127,7 @@ "lodash": "4.17.4", "object.assign": "4.1.0", "object.values": "1.0.4", - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "enzyme-adapter-utils": { @@ -5138,7 +5138,7 @@ "requires": { "lodash": "4.17.4", "object.assign": "4.1.0", - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "errno": { @@ -5469,7 +5469,7 @@ "doctrine": "2.0.2", "has": "1.0.1", "jsx-ast-utils": "2.0.1", - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "eslint-scope": { @@ -10409,6 +10409,18 @@ "request": "2.83.0" } }, + "history": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", + "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", + "requires": { + "invariant": "2.2.2", + "loose-envify": "1.3.1", + "resolve-pathname": "2.2.0", + "value-equal": "0.4.0", + "warning": "3.0.0" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -18906,9 +18918,9 @@ } }, "prop-types": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", - "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", @@ -19336,7 +19348,7 @@ "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1", - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "react-addons-css-transition-group": { @@ -19355,7 +19367,7 @@ "chain-function": "1.0.0", "dom-helpers": "3.3.1", "loose-envify": "1.3.1", - "prop-types": "15.6.0", + "prop-types": "15.6.1", "warning": "3.0.0" } } @@ -19375,7 +19387,7 @@ "fbjs": "0.8.16", "loose-envify": "1.3.1", "object-assign": "4.1.1", - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "react-hyperscript": { @@ -19388,7 +19400,7 @@ "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.1.2.tgz", "integrity": "sha512-uAfIE4XEfBNXqjqQvd31Eoo20UkVk0xHJpfgP8HRT8gLczaN4LEmB1e2d8CJ5ziEt4clWnsk/1+QhTN27iO/EA==", "requires": { - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "react-markdown": { @@ -19396,7 +19408,7 @@ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-3.1.4.tgz", "integrity": "sha512-i8WueytRXbYzyJ2GemIOTMRx/NigPo8r4m3R/KvWD7r+PxPyc9ke66cI3DR7MBRSS+nVG82VWEgRDE1VaZUCqA==", "requires": { - "prop-types": "15.6.0", + "prop-types": "15.6.1", "remark-parse": "4.0.0", "unified": "6.1.6", "unist-util-visit": "1.3.0", @@ -19409,7 +19421,7 @@ "integrity": "sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ==", "requires": { "performance-now": "0.2.0", - "prop-types": "15.6.0", + "prop-types": "15.6.1", "raf": "3.4.0" }, "dependencies": { @@ -19430,7 +19442,49 @@ "lodash": "4.17.4", "lodash-es": "4.17.4", "loose-envify": "1.3.1", - "prop-types": "15.6.0" + "prop-types": "15.6.1" + } + }, + "react-router": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", + "integrity": "sha512-DY6pjwRhdARE4TDw7XjxjZsbx9lKmIcyZoZ+SDO7SBJ1KUeWNxT22Kara2AC7u6/c2SYEHlEDLnzBCcNhLE8Vg==", + "requires": { + "history": "4.7.2", + "hoist-non-react-statics": "2.3.1", + "invariant": "2.2.2", + "loose-envify": "1.3.1", + "path-to-regexp": "1.7.0", + "prop-types": "15.6.1", + "warning": "3.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.2.2.tgz", + "integrity": "sha512-cHMFC1ZoLDfEaMFoKTjN7fry/oczMgRt5BKfMAkTu5zEuJvUiPp1J8d0eXSVTnBh6pxlbdqDhozunOOLtmKfPA==", + "requires": { + "history": "4.7.2", + "invariant": "2.2.2", + "loose-envify": "1.3.1", + "prop-types": "15.6.1", + "react-router": "4.2.0", + "warning": "3.0.0" } }, "react-select": { @@ -19439,7 +19493,7 @@ "integrity": "sha512-c4CdxweEHN9ra85HGWjSjIMBlJ5c0fsIXOymLFZS5UbZEQCiJGHnZTVLTt6/wDh8RKQnxl85gHUwzhG5XZLcyw==", "requires": { "classnames": "2.2.5", - "prop-types": "15.6.0", + "prop-types": "15.6.1", "react-input-autosize": "2.1.2" } }, @@ -19448,7 +19502,7 @@ "resolved": "https://registry.npmjs.org/react-simple-file-input/-/react-simple-file-input-2.0.1.tgz", "integrity": "sha1-Fa1P/Hj+sbiCZJrWsBwDPvJ1ceY=", "requires": { - "prop-types": "15.6.0" + "prop-types": "15.6.1" } }, "react-test-renderer": { @@ -19492,7 +19546,7 @@ "resolved": "https://registry.npmjs.org/react-toggle-button/-/react-toggle-button-2.2.0.tgz", "integrity": "sha1-obkhQ6oN9BRkL8sUHwh59UW8Wok=", "requires": { - "prop-types": "15.6.0", + "prop-types": "15.6.1", "react-motion": "0.5.2" } }, @@ -19519,7 +19573,7 @@ "classnames": "2.2.5", "dom-helpers": "3.3.1", "loose-envify": "1.3.1", - "prop-types": "15.6.0", + "prop-types": "15.6.1", "warning": "3.0.0" } }, @@ -20078,6 +20132,11 @@ "value-or-function": "3.0.0" } }, + "resolve-pathname": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", + "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -23756,6 +23815,11 @@ "spdx-expression-parse": "1.0.4" } }, + "value-equal": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", + "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" + }, "value-or-function": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", diff --git a/package.json b/package.json index 441ccbc6e..65e2cff9f 100644 --- a/package.json +++ b/package.json @@ -31,13 +31,7 @@ "test:mascara:build:background": "browserify mascara/src/background.js -o dist/mascara/background.js", "test:mascara:build:tests": "browserify test/integration/lib/first-time.js -o dist/mascara/tests.js", "ganache:start": "ganache-cli -m 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'", - "sentry": "export RELEASE=`cat app/manifest.json| jq -r .version` && npm run sentry:release && npm run sentry:upload", - "sentry:release": "npm run sentry:release:new && npm run sentry:release:clean", - "sentry:release:new": "sentry-cli releases --org 'metamask' --project 'metamask' new $RELEASE", - "sentry:release:clean": "sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE delete --all", - "sentry:upload": "npm run sentry:upload:source && npm run sentry:upload:maps", - "sentry:upload:source": "for FILEPATH in ./dist/chrome/scripts/*.js; do [ -e $FILEPATH ] || continue; export FILE=`basename $FILEPATH` && echo uploading $FILE && sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE upload $FILEPATH metamask/scripts/$FILE; done;", - "sentry:upload:maps": "sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE upload-sourcemaps ./dist/sourcemaps/ --url-prefix 'sourcemaps' --rewrite", + "sentry:publish": "node ./development/sentry-publish.js", "lint": "gulp lint", "lint:fix": "gulp lint:fix", "ui": "npm run test:flat:build:states && beefy development/ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", @@ -152,6 +146,7 @@ "post-message-stream": "^3.0.0", "promise-filter": "^1.1.0", "promise-to-callback": "^1.0.0", + "prop-types": "^15.6.1", "pump": "^3.0.0", "pumpify": "^1.3.4", "qrcode-npm": "0.0.3", @@ -163,6 +158,7 @@ "react-hyperscript": "^3.0.0", "react-markdown": "^3.0.0", "react-redux": "^5.0.5", + "react-router-dom": "^4.2.2", "react-select": "^1.0.0", "react-simple-file-input": "^2.0.0", "react-tippy": "^1.2.2", diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js index cc04beb21..1840bdd39 100644 --- a/test/integration/lib/add-token.js +++ b/test/integration/lib/add-token.js @@ -75,7 +75,7 @@ async function runAddTokenFlowTest (assert, done) { // Confirm Add token assert.equal( $('.add-token__description')[0].textContent, - 'Would you like to add these tokens?', + 'Token balance(s)', 'confirm add token rendered' ) assert.ok($('button.btn-primary--lg')[0], 'confirm add token button found') diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js index f1116d1a6..3936ac5fa 100644 --- a/test/integration/lib/confirm-sig-requests.js +++ b/test/integration/lib/confirm-sig-requests.js @@ -21,11 +21,22 @@ async function runConfirmSigRequestsTest(assert, done) { selectState.val('confirm sig requests') reactTriggerChange(selectState[0]) + // await timeout(1000000) + + const pendingRequestItem = $.find('.tx-list-item.tx-list-pending-item-container.tx-list-clickable') + + if (pendingRequestItem[0]) { + pendingRequestItem[0].click() + } + let confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') + let confirmSigMessage = await queryAsync($, '.request-signature__notice') + assert.ok(confirmSigMessage[0].textContent.match(/^Signing\sthis\smessage/)) + let confirmSigRowValue = await queryAsync($, '.request-signature__row-value') - assert.ok(confirmSigRowValue[0].textContent.match(/^\#\sTerms\sof\sUse/)) + assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') let confirmSigSignButton = await queryAsync($, 'button.btn-primary--lg') confirmSigSignButton[0].click() @@ -33,11 +44,8 @@ async function runConfirmSigRequestsTest(assert, done) { confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') - let confirmSigMessage = await queryAsync($, '.request-signature__notice') - assert.ok(confirmSigMessage[0].textContent.match(/^Signing\sthis\smessage/)) - confirmSigRowValue = await queryAsync($, '.request-signature__row-value') - assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') + assert.ok(confirmSigRowValue[0].textContent.match(/^\#\sTerms\sof\sUse/)) confirmSigSignButton = await queryAsync($, 'button.btn-primary--lg') confirmSigSignButton[0].click() diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js index 564852585..5e07ab0b4 100644 --- a/test/integration/lib/mascara-first-time.js +++ b/test/integration/lib/mascara-first-time.js @@ -13,6 +13,9 @@ async function runFirstTimeUsageTest (assert, done) { await skipNotices(app) + const welcomeButton = (await findAsync(app, '.welcome-screen__button'))[0] + welcomeButton.click() + // Scroll through terms const title = (await findAsync(app, '.create-password__title')).text() assert.equal(title, 'Create Password', 'create password screen') diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index 163f3658c..4731117d7 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -53,7 +53,7 @@ async function runSendFlowTest(assert, done) { assert.equal(sendFromDropdownList.children().length, 4, 'send from dropdown shows all accounts') sendFromDropdownList.children()[1].click() - sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name') + sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name') assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field dropdown changes account name') let sendToFieldInput = await queryAsync($, '.send-v2__to-autocomplete__input') @@ -164,17 +164,27 @@ async function runSendFlowTest(assert, done) { const sendButtonInEdit = await queryAsync($, '.btn-primary--lg.page-container__footer-button') assert.equal(sendButtonInEdit[0].textContent, 'Next', 'next button in edit rendered') - sendButtonInEdit[0].click() - // TODO: Need a way to mock background so that we can test correct transition from editing to confirm - selectState.val('confirm new ui') + selectState.val('send new ui') reactTriggerChange(selectState[0]) - const confirmScreenConfirmButton = await queryAsync($, '.btn-confirm.page-container__footer-button') - console.log(`+++++++++++++++++++++++++++++++= confirmScreenConfirmButton[0]`, confirmScreenConfirmButton[0]); - confirmScreenConfirmButton[0].click() - const txView = await queryAsync($, '.tx-view') - console.log(`++++++++++++++++++++++++++++++++ txView[0]`, txView[0]); + const cancelButtonInEdit = await queryAsync($, '.btn-secondary--lg.page-container__footer-button') + cancelButtonInEdit[0].click() + // sendButtonInEdit[0].click() + + // // TODO: Need a way to mock background so that we can test correct transition from editing to confirm + // selectState.val('confirm new ui') + // reactTriggerChange(selectState[0]) + + + // const confirmScreenConfirmButton = await queryAsync($, '.btn-confirm.page-container__footer-button') + // console.log(`+++++++++++++++++++++++++++++++= confirmScreenConfirmButton[0]`, confirmScreenConfirmButton[0]); + // confirmScreenConfirmButton[0].click() + + // await timeout(10000000) + + // const txView = await queryAsync($, '.tx-view') + // console.log(`++++++++++++++++++++++++++++++++ txView[0]`, txView[0]); - assert.ok(txView[0], 'Should return to the account details screen after confirming') + // assert.ok(txView[0], 'Should return to the account details screen after confirming') } diff --git a/test/unit/migrations/024-test.js b/test/unit/migrations/024-test.js new file mode 100644 index 000000000..c3c03d06b --- /dev/null +++ b/test/unit/migrations/024-test.js @@ -0,0 +1,49 @@ +const assert = require('assert') +const migration24 = require('../../../app/scripts/migrations/024') +const firstTimeState = { + meta: {}, + data: require('../../../app/scripts/first-time-state'), +} +const properTime = (new Date()).getTime() +const storage = { + "meta": {}, + "data": { + "TransactionController": { + "transactions": [ + ] + }, + }, +} + +const transactions = [] + + +while (transactions.length <= 10) { + transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'unapproved' }) + transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' }) +} + + +storage.data.TransactionController.transactions = transactions + +describe('storage is migrated successfully and the txParams.from are lowercase', () => { + it('should lowercase the from for unapproved txs', (done) => { + migration24.migrate(storage) + .then((migratedData) => { + const migratedTransactions = migratedData.data.TransactionController.transactions + migratedTransactions.forEach((tx) => { + if (tx.status === 'unapproved') assert.equal(tx.txParams.from, '0x8acce2391c0d510a6c5e5d8f819a678f79b7e675') + else assert.equal(tx.txParams.from, '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675') + }) + done() + }).catch(done) + }) + + it('should migrate first time state', (done) => { + migration24.migrate(firstTimeState) + .then((migratedData) => { + assert.equal(migratedData.meta.version, 24) + done() + }).catch(done) + }) +}) diff --git a/test/unit/migrations/025-test.js b/test/unit/migrations/025-test.js new file mode 100644 index 000000000..76c25dbb6 --- /dev/null +++ b/test/unit/migrations/025-test.js @@ -0,0 +1,49 @@ +const assert = require('assert') +const migration25 = require('../../../app/scripts/migrations/025') +const firstTimeState = { + meta: {}, + data: require('../../../app/scripts/first-time-state'), +} + +const storage = { + "meta": {}, + "data": { + "TransactionController": { + "transactions": [ + ] + }, + }, +} + +const transactions = [] + + +while (transactions.length <= 10) { + transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675', random: 'stuff', chainId: 2 }, status: 'unapproved' }) + transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' }) +} + + +storage.data.TransactionController.transactions = transactions + +describe('storage is migrated successfully and the txParams.from are lowercase', () => { + it('should lowercase the from for unapproved txs', (done) => { + migration25.migrate(storage) + .then((migratedData) => { + const migratedTransactions = migratedData.data.TransactionController.transactions + migratedTransactions.forEach((tx) => { + if (tx.status === 'unapproved') assert(!tx.txParams.random) + if (tx.status === 'unapproved') assert(!tx.txParams.chainId) + }) + done() + }).catch(done) + }) + + it('should migrate first time state', (done) => { + migration25.migrate(firstTimeState) + .then((migratedData) => { + assert.equal(migratedData.meta.version, 25) + done() + }).catch(done) + }) +}) diff --git a/test/unit/migrations/template-test.js b/test/unit/migrations/template-test.js new file mode 100644 index 000000000..35060e2fe --- /dev/null +++ b/test/unit/migrations/template-test.js @@ -0,0 +1,17 @@ +const assert = require('assert') +const migrationTemplate = require('../../../app/scripts/migrations/template') +const properTime = (new Date()).getTime() +const storage = { + meta: {}, + data: {}, +} + +describe('storage is migrated successfully', () => { + it('should work', (done) => { + migrationTemplate.migrate(storage) + .then((migratedData) => { + assert.equal(migratedData.meta.version, 0) + done() + }).catch(done) + }) +}) diff --git a/test/unit/migrator-test.js b/test/unit/migrator-test.js index 16066fefe..4404e1dc4 100644 --- a/test/unit/migrator-test.js +++ b/test/unit/migrator-test.js @@ -1,7 +1,8 @@ const assert = require('assert') const clone = require('clone') const Migrator = require('../../app/scripts/lib/migrator/') -const migrations = [ +const liveMigrations = require('../../app/scripts/migrations/') +const stubMigrations = [ { version: 1, migrate: (data) => { @@ -29,13 +30,39 @@ const migrations = [ }, ] const versionedData = {meta: {version: 0}, data: {hello: 'world'}} + +const firstTimeState = { + meta: { version: 0 }, + data: require('../../app/scripts/first-time-state'), +} + describe('Migrator', () => { - const migrator = new Migrator({ migrations }) + const migrator = new Migrator({ migrations: stubMigrations }) it('migratedData version should be version 3', (done) => { migrator.migrateData(versionedData) .then((migratedData) => { - assert.equal(migratedData.meta.version, migrations[2].version) + assert.equal(migratedData.meta.version, stubMigrations[2].version) done() }).catch(done) }) + + it('should match the last version in live migrations', (done) => { + const migrator = new Migrator({ migrations: liveMigrations }) + migrator.migrateData(firstTimeState) + .then((migratedData) => { + const last = liveMigrations.length - 1 + assert.equal(migratedData.meta.version, liveMigrations[last].version) + done() + }).catch(done) + }) + + it('should emit an error', function (done) { + this.timeout(15000) + const migrator = new Migrator({ migrations: [{ version: 1, migrate: async () => { throw new Error('test') } } ] }) + migrator.on('error', () => done()) + migrator.migrateData({ meta: {version: 0} }) + .then((migratedData) => { + }).catch(done) + }) + }) diff --git a/test/unit/tx-controller-test.js b/test/unit/tx-controller-test.js index 6bd010e7a..824574ff2 100644 --- a/test/unit/tx-controller-test.js +++ b/test/unit/tx-controller-test.js @@ -210,31 +210,99 @@ describe('Transaction Controller', function () { }) }) - describe('#validateTxParams', function () { - it('does not throw for positive values', function (done) { + describe('#_validateTxParams', function () { + it('does not throw for positive values', function () { var sample = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', value: '0x01', } - txController.txGasUtil.validateTxParams(sample).then(() => { - done() - }).catch(done) + txController._validateTxParams(sample) }) - it('returns error for negative values', function (done) { + it('returns error for negative values', function () { var sample = { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', value: '-0x01', } - txController.txGasUtil.validateTxParams(sample) - .then(() => done('expected to thrown on negativity values but didn\'t')) - .catch((err) => { + try { + txController._validateTxParams(sample) + } catch (err) { assert.ok(err, 'error') - done() - }) + } }) }) + describe('#_normalizeTxParams', () => { + it('should normalize txParams', () => { + let txParams = { + chainId: '0x1', + from: 'a7df1beDBF813f57096dF77FCd515f0B3900e402', + to: null, + data: '68656c6c6f20776f726c64', + random: 'hello world', + } + + let normalizedTxParams = txController._normalizeTxParams(txParams) + + assert(!normalizedTxParams.chainId, 'their should be no chainId') + assert(!normalizedTxParams.to, 'their should be no to address if null') + assert.equal(normalizedTxParams.from.slice(0, 2), '0x', 'from should be hexPrefixd') + assert.equal(normalizedTxParams.data.slice(0, 2), '0x', 'data should be hexPrefixd') + assert(!('random' in normalizedTxParams), 'their should be no random key in normalizedTxParams') + + txParams.to = 'a7df1beDBF813f57096dF77FCd515f0B3900e402' + normalizedTxParams = txController._normalizeTxParams(txParams) + assert.equal(normalizedTxParams.to.slice(0, 2), '0x', 'to should be hexPrefixd') + + }) + }) + + describe('#_validateRecipient', () => { + it('removes recipient for txParams with 0x when contract data is provided', function () { + const zeroRecipientandDataTxParams = { + from: '0x1678a085c290ebd122dc42cba69373b5953b831d', + to: '0x', + data: 'bytecode', + } + const sanitizedTxParams = txController._validateRecipient(zeroRecipientandDataTxParams) + assert.deepEqual(sanitizedTxParams, { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', data: 'bytecode' }, 'no recipient with 0x') + }) + + it('should error when recipient is 0x', function () { + const zeroRecipientTxParams = { + from: '0x1678a085c290ebd122dc42cba69373b5953b831d', + to: '0x', + } + assert.throws(() => { txController._validateRecipient(zeroRecipientTxParams) }, Error, 'Invalid recipient address') + }) + }) + + + describe('#_validateFrom', () => { + it('should error when from is not a hex string', function () { + + // where from is undefined + const txParams = {} + assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`) + + // where from is array + txParams.from = [] + assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`) + + // where from is a object + txParams.from = {} + assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`) + + // where from is a invalid address + txParams.from = 'im going to fail' + assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address`) + + // should run + txParams.from ='0x1678a085c290ebd122dc42cba69373b5953b831d' + txController._validateFrom(txParams) + }) + }) + describe('#addTx', function () { it('should emit updates', function (done) { const txMeta = { diff --git a/test/unit/tx-gas-util-test.js b/test/unit/tx-gas-util-test.js index 15d412c72..40ea8a7d6 100644 --- a/test/unit/tx-gas-util-test.js +++ b/test/unit/tx-gas-util-test.js @@ -11,46 +11,4 @@ describe('Tx Gas Util', function () { provider, }) }) - - it('removes recipient for txParams with 0x when contract data is provided', function () { - const zeroRecipientandDataTxParams = { - from: '0x1678a085c290ebd122dc42cba69373b5953b831d', - to: '0x', - data: 'bytecode', - } - const sanitizedTxParams = txGasUtil.validateRecipient(zeroRecipientandDataTxParams) - assert.deepEqual(sanitizedTxParams, { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', data: 'bytecode' }, 'no recipient with 0x') - }) - - it('should error when recipient is 0x', function () { - const zeroRecipientTxParams = { - from: '0x1678a085c290ebd122dc42cba69373b5953b831d', - to: '0x', - } - assert.throws(() => { txGasUtil.validateRecipient(zeroRecipientTxParams) }, Error, 'Invalid recipient address') - }) - - it('should error when from is not a hex string', function () { - - // where from is undefined - const txParams = {} - assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`) - - // where from is array - txParams.from = [] - assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`) - - // where from is a object - txParams.from = {} - assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`) - - // where from is a invalid address - txParams.from = 'im going to fail' - assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address`) - - // should run - txParams.from ='0x1678a085c290ebd122dc42cba69373b5953b831d' - txGasUtil.validateFrom(txParams) - }) - }) diff --git a/ui/app/actions.js b/ui/app/actions.js index ad4270cef..0748a5bea 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -347,7 +347,7 @@ function transitionBackward () { } function confirmSeedWords () { - return (dispatch) => { + return dispatch => { dispatch(actions.showLoadingIndication()) log.debug(`background.clearSeedWordCache`) return new Promise((resolve, reject) => { @@ -355,7 +355,7 @@ function confirmSeedWords () { dispatch(actions.hideLoadingIndication()) if (err) { dispatch(actions.displayWarning(err.message)) - reject(err) + return reject(err) } log.info('Seed word cache cleared. ' + account) @@ -571,35 +571,47 @@ function signMsg (msgData) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - log.debug(`actions calling background.signMessage`) - background.signMessage(msgData, (err, newState) => { - log.debug('signMessage called back') - dispatch(actions.updateMetamaskState(newState)) - dispatch(actions.hideLoadingIndication()) + return new Promise((resolve, reject) => { + log.debug(`actions calling background.signMessage`) + background.signMessage(msgData, (err, newState) => { + log.debug('signMessage called back') + dispatch(actions.updateMetamaskState(newState)) + dispatch(actions.hideLoadingIndication()) - if (err) log.error(err) - if (err) return dispatch(actions.displayWarning(err.message)) + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } - dispatch(actions.completedTx(msgData.metamaskId)) + dispatch(actions.completedTx(msgData.metamaskId)) + return resolve(msgData) + }) }) } } function signPersonalMsg (msgData) { log.debug('action - signPersonalMsg') - return (dispatch) => { + return dispatch => { dispatch(actions.showLoadingIndication()) - log.debug(`actions calling background.signPersonalMessage`) - background.signPersonalMessage(msgData, (err, newState) => { - log.debug('signPersonalMessage called back') - dispatch(actions.updateMetamaskState(newState)) - dispatch(actions.hideLoadingIndication()) + return new Promise((resolve, reject) => { + log.debug(`actions calling background.signPersonalMessage`) + background.signPersonalMessage(msgData, (err, newState) => { + log.debug('signPersonalMessage called back') + dispatch(actions.updateMetamaskState(newState)) + dispatch(actions.hideLoadingIndication()) - if (err) log.error(err) - if (err) return dispatch(actions.displayWarning(err.message)) + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } - dispatch(actions.completedTx(msgData.metamaskId)) + dispatch(actions.completedTx(msgData.metamaskId)) + return resolve(msgData) + }) }) } } @@ -609,16 +621,22 @@ function signTypedMsg (msgData) { return (dispatch) => { dispatch(actions.showLoadingIndication()) - log.debug(`actions calling background.signTypedMessage`) - background.signTypedMessage(msgData, (err, newState) => { - log.debug('signTypedMessage called back') - dispatch(actions.updateMetamaskState(newState)) - dispatch(actions.hideLoadingIndication()) + return new Promise((resolve, reject) => { + log.debug(`actions calling background.signTypedMessage`) + background.signTypedMessage(msgData, (err, newState) => { + log.debug('signTypedMessage called back') + dispatch(actions.updateMetamaskState(newState)) + dispatch(actions.hideLoadingIndication()) - if (err) log.error(err) - if (err) return dispatch(actions.displayWarning(err.message)) + if (err) { + log.error(err) + dispatch(actions.displayWarning(err.message)) + return reject(err) + } - dispatch(actions.completedTx(msgData.metamaskId)) + dispatch(actions.completedTx(msgData.metamaskId)) + return resolve(msgData) + }) }) } } @@ -798,17 +816,24 @@ function updateTransaction (txData) { function updateAndApproveTx (txData) { log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) return (dispatch) => { - log.debug(`actions calling background.updateAndApproveTx.`) - background.updateAndApproveTransaction(txData, (err) => { - dispatch(actions.hideLoadingIndication()) - dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) - dispatch(actions.clearSend()) - if (err) { - dispatch(actions.txError(err)) - dispatch(actions.goHome()) - return log.error(err.message) - } - dispatch(actions.completedTx(txData.id)) + log.debug(`actions calling background.updateAndApproveTx`) + + return new Promise((resolve, reject) => { + background.updateAndApproveTransaction(txData, err => { + dispatch(actions.hideLoadingIndication()) + dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) + dispatch(actions.clearSend()) + + if (err) { + dispatch(actions.txError(err)) + dispatch(actions.goHome()) + log.error(err.message) + reject(err) + } + + dispatch(actions.completedTx(txData.id)) + resolve(txData) + }) }) } } @@ -836,29 +861,77 @@ function txError (err) { } function cancelMsg (msgData) { - log.debug(`background.cancelMessage`) - background.cancelMessage(msgData.id) - return actions.completedTx(msgData.id) + return dispatch => { + dispatch(actions.showLoadingIndication()) + + return new Promise((resolve, reject) => { + log.debug(`background.cancelMessage`) + background.cancelMessage(msgData.id, (err, newState) => { + dispatch(actions.updateMetamaskState(newState)) + dispatch(actions.hideLoadingIndication()) + + if (err) { + return reject(err) + } + + dispatch(actions.completedTx(msgData.id)) + return resolve(msgData) + }) + }) + } } function cancelPersonalMsg (msgData) { - const id = msgData.id - background.cancelPersonalMessage(id) - return actions.completedTx(id) + return dispatch => { + dispatch(actions.showLoadingIndication()) + + return new Promise((resolve, reject) => { + const id = msgData.id + background.cancelPersonalMessage(id, (err, newState) => { + dispatch(actions.updateMetamaskState(newState)) + dispatch(actions.hideLoadingIndication()) + + if (err) { + return reject(err) + } + + dispatch(actions.completedTx(id)) + return resolve(msgData) + }) + }) + } } function cancelTypedMsg (msgData) { - const id = msgData.id - background.cancelTypedMessage(id) - return actions.completedTx(id) + return dispatch => { + dispatch(actions.showLoadingIndication()) + + return new Promise((resolve, reject) => { + const id = msgData.id + background.cancelTypedMessage(id, (err, newState) => { + dispatch(actions.updateMetamaskState(newState)) + dispatch(actions.hideLoadingIndication()) + + if (err) { + return reject(err) + } + + dispatch(actions.completedTx(id)) + return resolve(msgData) + }) + }) + } } function cancelTx (txData) { - return (dispatch) => { + return dispatch => { log.debug(`background.cancelTransaction`) - background.cancelTransaction(txData.id, () => { - dispatch(actions.clearSend()) - dispatch(actions.completedTx(txData.id)) + return new Promise((resolve, reject) => { + background.cancelTransaction(txData.id, () => { + dispatch(actions.clearSend()) + dispatch(actions.completedTx(txData.id)) + resolve(txData) + }) }) } } @@ -1249,12 +1322,13 @@ function markNoticeRead (notice) { dispatch(actions.displayWarning(err)) return reject(err) } + if (notice) { dispatch(actions.showNotice(notice)) - resolve() + resolve(true) } else { dispatch(actions.clearNotices()) - resolve() + resolve(false) } }) }) @@ -1773,7 +1847,7 @@ function forceUpdateMetamaskState (dispatch) { } dispatch(actions.updateMetamaskState(newState)) - resolve() + resolve(newState) }) }) } diff --git a/ui/app/app.js b/ui/app/app.js index 0b7a7a1e0..75c3febb0 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -1,62 +1,421 @@ -const inherits = require('util').inherits -const Component = require('react').Component +const { Component } = require('react') +const PropTypes = require('prop-types') const connect = require('react-redux').connect +const { Route, Switch, withRouter } = require('react-router-dom') +const { compose } = require('recompose') const h = require('react-hyperscript') -const PropTypes = require('prop-types') const actions = require('./actions') const classnames = require('classnames') -// mascara -const MascaraFirstTime = require('../../mascara/src/app/first-time').default -const MascaraBuyEtherScreen = require('../../mascara/src/app/first-time/buy-ether-screen').default // init -const OldUIInitializeMenuScreen = require('./first-time/init-menu') -const InitializeMenuScreen = MascaraFirstTime -const NewKeyChainScreen = require('./new-keychain') -const WelcomeScreen = require('./welcome-screen').default - +const InitializeScreen = require('../../mascara/src/app/first-time').default // accounts -const MainContainer = require('./main-container') const SendTransactionScreen2 = require('./components/send/send-v2-container') const ConfirmTxScreen = require('./conf-tx') -// notice -const NoticeScreen = require('./components/notice') -const generateLostAccountsNotice = require('../lib/lost-accounts-notice') // slideout menu const WalletView = require('./components/wallet-view') // other views -const Settings = require('./settings') -const AddTokenScreen = require('./add-token') -const Import = require('./accounts/import') -const NewAccount = require('./accounts/new-account') +const Home = require('./components/pages/home') +const Authenticated = require('./components/pages/authenticated') +const Initialized = require('./components/pages/initialized') +const Settings = require('./components/pages/settings') +const UnlockPage = require('./components/pages/unlock') +const RestoreVaultPage = require('./components/pages/keychains/restore-vault') +const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation') +const AddTokenPage = require('./components/pages/add-token') +const CreateAccountPage = require('./components/pages/create-account') +const NoticeScreen = require('./components/pages/notice') + const Loading = require('./components/loading') const NetworkIndicator = require('./components/network') const Identicon = require('./components/identicon') -const BuyView = require('./components/buy-button-subview') -const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete') -const HDRestoreVaultScreen = require('./keychains/hd/restore-vault') -const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation') const ReactCSSTransitionGroup = require('react-addons-css-transition-group') const NetworkDropdown = require('./components/dropdowns/network-dropdown') const AccountMenu = require('./components/account-menu') -const QrView = require('./components/qr-code') // Global Modals const Modal = require('./components/modals/index').Modal -App.contextTypes = { - t: PropTypes.func, -} +// Routes +const { + DEFAULT_ROUTE, + UNLOCK_ROUTE, + SETTINGS_ROUTE, + REVEAL_SEED_ROUTE, + RESTORE_VAULT_ROUTE, + ADD_TOKEN_ROUTE, + NEW_ACCOUNT_ROUTE, + SEND_ROUTE, + CONFIRM_TRANSACTION_ROUTE, + INITIALIZE_ROUTE, + NOTICE_ROUTE, +} = require('./routes') + +class App extends Component { + componentWillMount () { + const { currentCurrency, setCurrentCurrencyToUSD } = this.props + + if (!currentCurrency) { + setCurrentCurrencyToUSD() + } + } + + renderRoutes () { + const exact = true + + return ( + h(Switch, [ + h(Route, { path: INITIALIZE_ROUTE, component: InitializeScreen }), + h(Initialized, { path: REVEAL_SEED_ROUTE, exact, component: RevealSeedConfirmation }), + h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }), + h(Initialized, { path: SETTINGS_ROUTE, component: Settings }), + h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }), + h(Initialized, { path: NOTICE_ROUTE, exact, component: NoticeScreen }), + h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }), + h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }), + h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }), + h(Authenticated, { path: NEW_ACCOUNT_ROUTE, component: CreateAccountPage }), + h(Authenticated, { path: DEFAULT_ROUTE, exact, component: Home }), + ]) + ) + } + + render () { + const { + isLoading, + loadingMessage, + network, + isMouseUser, + provider, + frequentRpcList, + currentView, + setMouseUserState, + } = this.props + const isLoadingNetwork = network === 'loading' && currentView.name !== 'config' + const loadMessage = loadingMessage || isLoadingNetwork ? + this.getConnectingLabel() : null + log.debug('Main ui render function') + + return ( + h('.flex-column.full-height', { + className: classnames({ 'mouse-user-styles': isMouseUser }), + style: { + overflowX: 'hidden', + position: 'relative', + alignItems: 'center', + }, + tabIndex: '0', + onClick: () => setMouseUserState(true), + onKeyDown: (e) => { + if (e.keyCode === 9) { + setMouseUserState(false) + } + }, + }, [ + + // global modal + h(Modal, {}, []), + + // app bar + this.renderAppBar(), + + // sidebar + this.renderSidebar(), -module.exports = connect(mapStateToProps, mapDispatchToProps)(App) + // network dropdown + h(NetworkDropdown, { + provider, + frequentRpcList, + }, []), + h(AccountMenu), -inherits(App, Component) -function App () { Component.call(this) } + (isLoading || isLoadingNetwork) && h(Loading, { + loadingMessage: loadMessage, + }), + + // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), + + // content + this.renderRoutes(), + ]) + ) + } + + renderGlobalModal () { + return h(Modal, { + ref: 'modalRef', + }, [ + // h(BuyOptions, {}, []), + ]) + } + + renderSidebar () { + return h('div', [ + h('style', ` + .sidebar-enter { + transition: transform 300ms ease-in-out; + transform: translateX(-100%); + } + .sidebar-enter.sidebar-enter-active { + transition: transform 300ms ease-in-out; + transform: translateX(0%); + } + .sidebar-leave { + transition: transform 200ms ease-out; + transform: translateX(0%); + } + .sidebar-leave.sidebar-leave-active { + transition: transform 200ms ease-out; + transform: translateX(-100%); + } + `), + + h(ReactCSSTransitionGroup, { + transitionName: 'sidebar', + transitionEnterTimeout: 300, + transitionLeaveTimeout: 200, + }, [ + // A second instance of Walletview is used for non-mobile viewports + this.props.sidebarOpen ? h(WalletView, { + responsiveDisplayClassname: '.sidebar', + style: {}, + }) : undefined, + + ]), + + // overlay + // TODO: add onClick for overlay to close sidebar + this.props.sidebarOpen ? h('div.sidebar-overlay', { + style: {}, + onClick: () => { + this.props.hideSidebar() + }, + }, []) : undefined, + ]) + } + + renderAppBar () { + const { + isUnlocked, + network, + provider, + networkDropdownOpen, + showNetworkDropdown, + hideNetworkDropdown, + isInitialized, + welcomeScreenSeen, + isPopup, + betaUI, + } = this.props + + if (window.METAMASK_UI_TYPE === 'notification') { + return null + } + + const props = this.props + const {isMascara, isOnboarding} = props + + // Do not render header if user is in mascara onboarding + if (isMascara && isOnboarding) { + return null + } + + // Do not render header if user is in mascara buy ether + if (isMascara && props.currentView.name === 'buyEth') { + return null + } + + return ( + + h('.full-width', { + style: {}, + }, [ + + (isInitialized || welcomeScreenSeen || isPopup || !betaUI) && h('.app-header.flex-row.flex-space-between', { + className: classnames({ + 'app-header--initialized': !isOnboarding, + }), + }, [ + h('div.app-header-contents', {}, [ + h('div.left-menu-wrapper', { + onClick: () => props.history.push(DEFAULT_ROUTE), + }, [ + // mini logo + h('img.metafox-icon', { + height: 42, + width: 42, + src: '/images/metamask-fox.svg', + }), + + // metamask name + h('.flex-row', [ + h('h1', this.context.t('appName')), + h('div.beta-label', this.context.t('beta')), + ]), + + ]), + + betaUI && isInitialized && h('div.header__right-actions', [ + h('div.network-component-wrapper', { + style: {}, + }, [ + // Network Indicator + h(NetworkIndicator, { + network, + provider, + disabled: this.props.location.pathname === CONFIRM_TRANSACTION_ROUTE, + onClick: (event) => { + event.preventDefault() + event.stopPropagation() + return networkDropdownOpen === false + ? showNetworkDropdown() + : hideNetworkDropdown() + }, + }), + + ]), + + isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [ + h(Identicon, { + address: this.props.selectedAddress, + diameter: 32, + }), + ]), + ]), + ]), + ]), + + !isInitialized && !isPopup && betaUI && h('.alpha-warning__container', {}, [ + h('h2', { + className: classnames({ + 'alpha-warning': welcomeScreenSeen, + 'alpha-warning-welcome-screen': !welcomeScreenSeen, + }), + }, 'Please be aware that this version is still under development'), + ]), + + ]) + ) + } + + renderLoadingIndicator ({ isLoading, isLoadingNetwork, loadMessage }) { + const { isMascara } = this.props + + return isMascara + ? null + : h(Loading, { + isLoading: isLoading || isLoadingNetwork, + loadingMessage: loadMessage, + }) + } + + toggleMetamaskActive () { + if (!this.props.isUnlocked) { + // currently inactive: redirect to password box + var passwordBox = document.querySelector('input[type=password]') + if (!passwordBox) return + passwordBox.focus() + } else { + // currently active: deactivate + this.props.dispatch(actions.lockMetamask(false)) + } + } + + getConnectingLabel = function () { + const { provider } = this.props + const providerName = provider.type + + let name + + if (providerName === 'mainnet') { + name = this.context.t('connectingToMainnet') + } else if (providerName === 'ropsten') { + name = this.context.t('connectingToRopsten') + } else if (providerName === 'kovan') { + name = this.context.t('connectingToRopsten') + } else if (providerName === 'rinkeby') { + name = this.context.t('connectingToRinkeby') + } else { + name = this.context.t('connectingToUnknown') + } + + return name + } + + getNetworkName () { + const { provider } = this.props + const providerName = provider.type + + let name + + if (providerName === 'mainnet') { + name = this.context.t('mainnet') + } else if (providerName === 'ropsten') { + name = this.context.t('ropsten') + } else if (providerName === 'kovan') { + name = this.context.t('kovan') + } else if (providerName === 'rinkeby') { + name = this.context.t('rinkeby') + } else { + name = this.context.t('unknownNetwork') + } + + return name + } +} + +App.propTypes = { + currentCurrency: PropTypes.string, + setCurrentCurrencyToUSD: PropTypes.func, + isLoading: PropTypes.bool, + loadingMessage: PropTypes.string, + network: PropTypes.string, + provider: PropTypes.object, + frequentRpcList: PropTypes.array, + currentView: PropTypes.object, + sidebarOpen: PropTypes.bool, + hideSidebar: PropTypes.func, + isMascara: PropTypes.bool, + isOnboarding: PropTypes.bool, + isUnlocked: PropTypes.bool, + networkDropdownOpen: PropTypes.bool, + showNetworkDropdown: PropTypes.func, + hideNetworkDropdown: PropTypes.func, + history: PropTypes.object, + location: PropTypes.object, + dispatch: PropTypes.func, + toggleAccountMenu: PropTypes.func, + selectedAddress: PropTypes.string, + noActiveNotices: PropTypes.bool, + lostAccounts: PropTypes.array, + isInitialized: PropTypes.bool, + forgottenPassword: PropTypes.bool, + activeAddress: PropTypes.string, + unapprovedTxs: PropTypes.object, + seedWords: PropTypes.string, + unapprovedMsgCount: PropTypes.number, + unapprovedPersonalMsgCount: PropTypes.number, + unapprovedTypedMessagesCount: PropTypes.number, + welcomeScreenSeen: PropTypes.bool, + isPopup: PropTypes.bool, + betaUI: PropTypes.bool, + isMouseUser: PropTypes.bool, + setMouseUserState: PropTypes.func, + t: PropTypes.func, +} function mapStateToProps (state) { + const { appState, metamask } = state + const { + networkDropdownOpen, + sidebarOpen, + isLoading, + loadingMessage, + } = appState + const { identities, accounts, @@ -65,17 +424,23 @@ function mapStateToProps (state) { isInitialized, noActiveNotices, seedWords, - } = state.metamask + unapprovedTxs, + lastUnreadNotice, + lostAccounts, + unapprovedMsgCount, + unapprovedPersonalMsgCount, + unapprovedTypedMessagesCount, + } = metamask const selected = address || Object.keys(accounts)[0] return { // state from plugin - networkDropdownOpen: state.appState.networkDropdownOpen, - sidebarOpen: state.appState.sidebarOpen, - isLoading: state.appState.isLoading, - loadingMessage: state.appState.loadingMessage, - noActiveNotices: state.metamask.noActiveNotices, - isInitialized: state.metamask.isInitialized, + networkDropdownOpen, + sidebarOpen, + isLoading, + loadingMessage, + noActiveNotices, + isInitialized, isUnlocked: state.metamask.isUnlocked, selectedAddress: state.metamask.selectedAddress, currentView: state.appState.currentView, @@ -85,14 +450,17 @@ function mapStateToProps (state) { isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized), isPopup: state.metamask.isPopup, seedWords: state.metamask.seedWords, - unapprovedTxs: state.metamask.unapprovedTxs, + unapprovedTxs, unapprovedMsgs: state.metamask.unapprovedMsgs, + unapprovedMsgCount, + unapprovedPersonalMsgCount, + unapprovedTypedMessagesCount, menuOpen: state.appState.menuOpen, network: state.metamask.network, provider: state.metamask.provider, - forgottenPassword: state.metamask.forgottenPassword, - lastUnreadNotice: state.metamask.lastUnreadNotice, - lostAccounts: state.metamask.lostAccounts, + forgottenPassword: state.appState.forgottenPassword, + lastUnreadNotice, + lostAccounts, frequentRpcList: state.metamask.frequentRpcList || [], currentCurrency: state.metamask.currentCurrency, isMouseUser: state.appState.isMouseUser, @@ -120,479 +488,11 @@ function mapDispatchToProps (dispatch, ownProps) { } } -App.prototype.componentWillMount = function () { - if (!this.props.currentCurrency) { - this.props.setCurrentCurrencyToUSD() - } -} - -App.prototype.render = function () { - var props = this.props - const { - isLoading, - loadingMessage, - network, - isMouseUser, - setMouseUserState, - } = props - const isLoadingNetwork = network === 'loading' && props.currentView.name !== 'config' - const loadMessage = loadingMessage || isLoadingNetwork ? - this.getConnectingLabel() : null - log.debug('Main ui render function') - - return ( - h('.flex-column.full-height', { - className: classnames({ 'mouse-user-styles': isMouseUser }), - style: { - overflowX: 'hidden', - position: 'relative', - alignItems: 'center', - }, - tabIndex: '0', - onClick: () => setMouseUserState(true), - onKeyDown: (e) => { - if (e.keyCode === 9) { - setMouseUserState(false) - } - }, - }, [ - - // global modal - h(Modal, {}, []), - - // app bar - this.renderAppBar(), - - // sidebar - this.renderSidebar(), - - // network dropdown - h(NetworkDropdown, { - provider: this.props.provider, - frequentRpcList: this.props.frequentRpcList, - }, []), - - h(AccountMenu), - - (isLoading || isLoadingNetwork) && h(Loading, { - loadingMessage: loadMessage, - }), - - // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), - - // content - this.renderPrimary(), - ]) - ) -} - -App.prototype.renderGlobalModal = function () { - return h(Modal, { - ref: 'modalRef', - }, [ - // h(BuyOptions, {}, []), - ]) -} - -App.prototype.renderSidebar = function () { - - return h('div', { - }, [ - h('style', ` - .sidebar-enter { - transition: transform 300ms ease-in-out; - transform: translateX(-100%); - } - .sidebar-enter.sidebar-enter-active { - transition: transform 300ms ease-in-out; - transform: translateX(0%); - } - .sidebar-leave { - transition: transform 200ms ease-out; - transform: translateX(0%); - } - .sidebar-leave.sidebar-leave-active { - transition: transform 200ms ease-out; - transform: translateX(-100%); - } - `), - - h(ReactCSSTransitionGroup, { - transitionName: 'sidebar', - transitionEnterTimeout: 300, - transitionLeaveTimeout: 200, - }, [ - // A second instance of Walletview is used for non-mobile viewports - this.props.sidebarOpen ? h(WalletView, { - responsiveDisplayClassname: '.sidebar', - style: {}, - }) : undefined, - - ]), - - // overlay - // TODO: add onClick for overlay to close sidebar - this.props.sidebarOpen ? h('div.sidebar-overlay', { - style: {}, - onClick: () => { - this.props.hideSidebar() - }, - }, []) : undefined, - ]) -} - -App.prototype.renderAppBar = function () { - const { - isUnlocked, - network, - provider, - networkDropdownOpen, - showNetworkDropdown, - hideNetworkDropdown, - currentView, - isInitialized, - betaUI, - isPopup, - welcomeScreenSeen, - } = this.props - - if (window.METAMASK_UI_TYPE === 'notification') { - return null - } - - const props = this.props - const {isMascara, isOnboarding} = props - - // Do not render header if user is in mascara onboarding - if (isMascara && isOnboarding) { - return null - } - - // Do not render header if user is in mascara buy ether - if (isMascara && props.currentView.name === 'buyEth') { - return null - } - - return ( - - h('.full-width', { - style: {}, - }, [ - - (isInitialized || welcomeScreenSeen || isPopup || !betaUI) && h('.app-header.flex-row.flex-space-between', { - className: classnames({ - 'app-header--initialized': !isOnboarding, - }), - }, [ - h('div.app-header-contents', {}, [ - h('div.left-menu-wrapper', { - onClick: () => { - props.dispatch(actions.backToAccountDetail(props.activeAddress)) - }, - }, [ - // mini logo - h('img.metafox-icon', { - height: 42, - width: 42, - src: './images/metamask-fox.svg', - }), - - // metamask name - h('.flex-row', [ - h('h1', this.context.t('appName')), - h('div.beta-label', this.context.t('beta')), - ]), - ]), - - betaUI && isInitialized && h('div.header__right-actions', [ - h('div.network-component-wrapper', { - style: {}, - }, [ - // Network Indicator - h(NetworkIndicator, { - network, - provider, - disabled: currentView.name === 'confTx', - onClick: (event) => { - event.preventDefault() - event.stopPropagation() - return networkDropdownOpen === false - ? showNetworkDropdown() - : hideNetworkDropdown() - }, - }), - - ]), - - isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [ - h(Identicon, { - address: this.props.selectedAddress, - diameter: 32, - }), - ]), - ]), - ]), - ]), - - !isInitialized && !isPopup && betaUI && h('.alpha-warning__container', {}, [ - h('h2', { - className: classnames({ - 'alpha-warning': welcomeScreenSeen, - 'alpha-warning-welcome-screen': !welcomeScreenSeen, - }), - }, 'Please be aware that this version is still under development'), - ]), - - ]) - ) -} - -App.prototype.renderLoadingIndicator = function ({ isLoading, isLoadingNetwork, loadMessage }) { - const { isMascara } = this.props - - return isMascara - ? null - : h(Loading, { - isLoading: isLoading || isLoadingNetwork, - loadingMessage: loadMessage, - }) -} - -App.prototype.renderBackButton = function (style, justArrow = false) { - var props = this.props - return ( - h('.flex-row', { - key: 'leftArrow', - style: style, - onClick: () => props.dispatch(actions.goBackToInitView()), - }, [ - h('i.fa.fa-arrow-left.cursor-pointer'), - justArrow ? null : h('div.cursor-pointer', { - style: { - marginLeft: '3px', - }, - onClick: () => props.dispatch(actions.goBackToInitView()), - }, 'BACK'), - ]) - ) -} - -App.prototype.renderPrimary = function () { - log.debug('rendering primary') - var props = this.props - const { - isMascara, - isOnboarding, - betaUI, - isRevealingSeedWords, - welcomeScreenSeen, - Qr, - isInitialized, - isUnlocked, - } = props - const isMascaraOnboarding = isMascara && isOnboarding - const isBetaUIOnboarding = betaUI && isOnboarding - - if (!welcomeScreenSeen && betaUI && !isInitialized && !isUnlocked) { - return h(WelcomeScreen) - } - - if (isMascaraOnboarding || isBetaUIOnboarding) { - return h(MascaraFirstTime) - } - - // notices - if (!props.noActiveNotices && !betaUI) { - log.debug('rendering notice screen for unread notices.') - return h(NoticeScreen, { - notice: props.lastUnreadNotice, - key: 'NoticeScreen', - onConfirm: () => props.dispatch(actions.markNoticeRead(props.lastUnreadNotice)), - }) - } else if (props.lostAccounts && props.lostAccounts.length > 0) { - log.debug('rendering notice screen for lost accounts view.') - return h(NoticeScreen, { - notice: generateLostAccountsNotice(props.lostAccounts), - key: 'LostAccountsNotice', - onConfirm: () => props.dispatch(actions.markAccountsFound()), - }) - } - - if (props.isInitialized && props.forgottenPassword) { - log.debug('rendering restore vault screen') - return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) - } else if (!props.isInitialized && !props.isUnlocked && !isRevealingSeedWords) { - log.debug('rendering menu screen') - return !betaUI - ? h(OldUIInitializeMenuScreen, {key: 'menuScreenInit'}) - : h(InitializeMenuScreen, {key: 'menuScreenInit'}) - } - - // show unlock screen - if (!props.isUnlocked) { - return h(MainContainer, { - currentViewName: props.currentView.name, - isUnlocked: props.isUnlocked, - }) - } - - // show seed words screen - if (props.seedWords) { - log.debug('rendering seed words') - return h(HDCreateVaultComplete, {key: 'HDCreateVaultComplete'}) - } - - // show current view - switch (props.currentView.name) { - - case 'accountDetail': - log.debug('rendering main container') - return h(MainContainer, {key: 'account-detail'}) - - case 'sendTransaction': - log.debug('rendering send tx screen') - - // Going to leave this here until we are ready to delete SendTransactionScreen v1 - // const SendComponentToRender = checkFeatureToggle('send-v2') - // ? SendTransactionScreen2 - // : SendTransactionScreen - - return h(SendTransactionScreen2, {key: 'send-transaction'}) - - case 'sendToken': - log.debug('rendering send token screen') - - // Going to leave this here until we are ready to delete SendTransactionScreen v1 - // const SendTokenComponentToRender = checkFeatureToggle('send-v2') - // ? SendTransactionScreen2 - // : SendTokenScreen - - return h(SendTransactionScreen2, {key: 'sendToken'}) - - case 'newKeychain': - log.debug('rendering new keychain screen') - return h(NewKeyChainScreen, {key: 'new-keychain'}) - - case 'confTx': - log.debug('rendering confirm tx screen') - return h(ConfirmTxScreen, {key: 'confirm-tx'}) - - case 'add-token': - log.debug('rendering add-token screen from unlock screen.') - return h(AddTokenScreen, {key: 'add-token'}) - - case 'config': - log.debug('rendering config screen') - return h(Settings, {key: 'config'}) - - case 'import-menu': - log.debug('rendering import screen') - return h(Import, {key: 'import-menu'}) - - case 'new-account-page': - log.debug('rendering new account screen') - return h(NewAccount, {key: 'new-account'}) - - case 'reveal-seed-conf': - log.debug('rendering reveal seed confirmation screen') - return h(RevealSeedConfirmation, {key: 'reveal-seed-conf'}) - - case 'info': - log.debug('rendering info screen') - return h(Settings, {key: 'info', tab: 'info'}) - - case 'buyEth': - log.debug('rendering buy ether screen') - return h(BuyView, {key: 'buyEthView'}) - - case 'onboardingBuyEth': - log.debug('rendering onboarding buy ether screen') - return h(MascaraBuyEtherScreen, {key: 'buyEthView'}) - - case 'qr': - log.debug('rendering show qr screen') - return h('div', { - style: { - position: 'absolute', - height: '100%', - top: '0px', - left: '0px', - }, - }, [ - h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', { - onClick: () => props.dispatch(actions.backToAccountDetail(props.activeAddress)), - style: { - marginLeft: '10px', - marginTop: '50px', - }, - }), - h('div', { - style: { - position: 'absolute', - left: '44px', - width: '285px', - }, - }, [ - h(QrView, {key: 'qr', Qr}), - ]), - ]) - - default: - log.debug('rendering default, account detail screen') - return h(MainContainer, {key: 'account-detail'}) - } -} - -App.prototype.toggleMetamaskActive = function () { - if (!this.props.isUnlocked) { - // currently inactive: redirect to password box - var passwordBox = document.querySelector('input[type=password]') - if (!passwordBox) return - passwordBox.focus() - } else { - // currently active: deactivate - this.props.dispatch(actions.lockMetamask(false)) - } -} - -App.prototype.getConnectingLabel = function () { - const { provider } = this.props - const providerName = provider.type - - let name - - if (providerName === 'mainnet') { - name = this.context.t('connectingToMainnet') - } else if (providerName === 'ropsten') { - name = this.context.t('connectingToRopsten') - } else if (providerName === 'kovan') { - name = this.context.t('connectingToRopsten') - } else if (providerName === 'rinkeby') { - name = this.context.t('connectingToRinkeby') - } else { - name = this.context.t('connectingToUnknown') - } - - return name +App.contextTypes = { + t: PropTypes.func, } -App.prototype.getNetworkName = function () { - const { provider } = this.props - const providerName = provider.type - - let name - - if (providerName === 'mainnet') { - name = this.context.t('mainnet') - } else if (providerName === 'ropsten') { - name = this.context.t('ropsten') - } else if (providerName === 'kovan') { - name = this.context.t('kovan') - } else if (providerName === 'rinkeby') { - name = this.context.t('rinkeby') - } else { - name = this.context.t('unknownNetwork') - } - - return name -} +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(App) diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index 21de358d6..7638995ea 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -1,20 +1,31 @@ const inherits = require('util').inherits const Component = require('react').Component -const PropTypes = require('prop-types') const connect = require('react-redux').connect +const { compose } = require('recompose') +const { withRouter } = require('react-router-dom') +const PropTypes = require('prop-types') const h = require('react-hyperscript') const actions = require('../../actions') const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu') const Identicon = require('../identicon') const { formatBalance } = require('../../util') +const { + SETTINGS_ROUTE, + INFO_ROUTE, + NEW_ACCOUNT_ROUTE, + IMPORT_ACCOUNT_ROUTE, + DEFAULT_ROUTE, +} = require('../../routes') + +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(AccountMenu) AccountMenu.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountMenu) - - inherits(AccountMenu, Component) function AccountMenu () { Component.call(this) } @@ -25,7 +36,6 @@ function mapStateToProps (state) { keyrings: state.metamask.keyrings, identities: state.metamask.identities, accounts: state.metamask.accounts, - } } @@ -48,11 +58,6 @@ function mapDispatchToProps (dispatch) { dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, - showNewAccountPage: (formToSelect) => { - dispatch(actions.showNewAccountPage(formToSelect)) - dispatch(actions.hideSidebar()) - dispatch(actions.toggleAccountMenu()) - }, showInfoPage: () => { dispatch(actions.showInfoPage()) dispatch(actions.hideSidebar()) @@ -65,10 +70,8 @@ AccountMenu.prototype.render = function () { const { isAccountMenuOpen, toggleAccountMenu, - showNewAccountPage, lockMetamask, - showConfigPage, - showInfoPage, + history, } = this.props return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [ @@ -78,30 +81,45 @@ AccountMenu.prototype.render = function () { }, [ this.context.t('myAccounts'), h('button.account-menu__logout-button', { - onClick: lockMetamask, + onClick: () => { + lockMetamask() + history.push(DEFAULT_ROUTE) + }, }, this.context.t('logout')), ]), h(Divider), h('div.account-menu__accounts', this.renderAccounts()), h(Divider), h(Item, { - onClick: () => showNewAccountPage('CREATE'), + onClick: () => { + toggleAccountMenu() + history.push(NEW_ACCOUNT_ROUTE) + }, icon: h('img.account-menu__item-icon', { src: 'images/plus-btn-white.svg' }), text: this.context.t('createAccount'), }), h(Item, { - onClick: () => showNewAccountPage('IMPORT'), + onClick: () => { + toggleAccountMenu() + history.push(IMPORT_ACCOUNT_ROUTE) + }, icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }), text: this.context.t('importAccount'), }), h(Divider), h(Item, { - onClick: showInfoPage, + onClick: () => { + toggleAccountMenu() + history.push(INFO_ROUTE) + }, icon: h('img', { src: 'images/mm-info-icon.svg' }), text: this.context.t('infoHelp'), }), h(Item, { - onClick: showConfigPage, + onClick: () => { + toggleAccountMenu() + history.push(SETTINGS_ROUTE) + }, icon: h('img.account-menu__item-icon', { src: 'images/settings.svg' }), text: this.context.t('settings'), }), diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js index 1f3946817..feb0a7037 100644 --- a/ui/app/components/ens-input.js +++ b/ui/app/components/ens-input.js @@ -32,10 +32,10 @@ EnsInput.prototype.render = function () { const network = this.props.network const networkHasEnsSupport = getNetworkEnsSupport(network) - if (!networkHasEnsSupport) return - props.onChange(recipient) + if (!networkHasEnsSupport) return + if (recipient.match(ensRE) === null) { return this.setState({ loadingEns: false, diff --git a/ui/app/add-token.js b/ui/app/components/pages/add-token.js index ebdd220aa..566e42450 100644 --- a/ui/app/add-token.js +++ b/ui/app/components/pages/add-token.js @@ -7,8 +7,8 @@ const connect = require('react-redux').connect const R = require('ramda') const Fuse = require('fuse.js') const contractMap = require('eth-contract-metadata') -const TokenBalance = require('./components/token-balance') -const Identicon = require('./components/identicon') +const TokenBalance = require('../../components/token-balance') +const Identicon = require('../../components/identicon') const contractList = Object.entries(contractMap) .map(([ _, tokenData]) => tokenData) .filter(tokenData => Boolean(tokenData.erc20)) @@ -24,9 +24,10 @@ const fuse = new Fuse(contractList, { { name: 'symbol', weight: 0.5 }, ], }) -const actions = require('./actions') +const actions = require('../../actions') const ethUtil = require('ethereumjs-util') -const { tokenInfoGetter } = require('./token-util') +const { tokenInfoGetter } = require('../../token-util') +const { DEFAULT_ROUTE } = require('../../routes') const emptyAddr = '0x0000000000000000000000000000000000000000' @@ -47,7 +48,6 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - goHome: () => dispatch(actions.goHome()), addTokens: tokens => dispatch(actions.addTokens(tokens)), } } @@ -56,6 +56,7 @@ inherits(AddTokenScreen, Component) function AddTokenScreen () { this.state = { isShowingConfirmation: false, + isShowingInfoBox: true, customAddress: '', customSymbol: '', customDecimals: '', @@ -295,7 +296,7 @@ AddTokenScreen.prototype.renderConfirmation = function () { selectedTokens, } = this.state - const { addTokens, goHome } = this.props + const { addTokens, history } = this.props const customToken = { address, @@ -310,9 +311,6 @@ AddTokenScreen.prototype.renderConfirmation = function () { return ( h('div.add-token', [ h('div.add-token__wrapper', [ - h('div.add-token__title-container.add-token__confirmation-title', [ - h('div.add-token__description', this.context.t('likeToAddTokens')), - ]), h('div.add-token__content-container.add-token__confirmation-content', [ h('div.add-token__description.add-token__confirmation-description', this.context.t('balances')), h('div.add-token__confirmation-token-list', @@ -335,7 +333,7 @@ AddTokenScreen.prototype.renderConfirmation = function () { onClick: () => this.setState({ isShowingConfirmation: false }), }, this.context.t('back')), h('button.btn-primary--lg', { - onClick: () => addTokens(tokens).then(goHome), + onClick: () => addTokens(tokens).then(() => history.push(DEFAULT_ROUTE)), }, this.context.t('addTokens')), ]), ]) @@ -347,18 +345,23 @@ AddTokenScreen.prototype.displayTab = function (selectedTab) { } AddTokenScreen.prototype.renderTabs = function () { - const { displayedTab, errors } = this.state + const { isShowingInfoBox, displayedTab, errors } = this.state return displayedTab === 'CUSTOM_TOKEN' ? this.renderCustomForm() : h('div', [ h('div.add-token__wrapper', [ h('div.add-token__content-container', [ - h('div.add-token__info-box', [ - h('div.add-token__info-box__close'), + isShowingInfoBox && h('div.add-token__info-box', [ + h('div.add-token__info-box__close', { + onClick: () => this.setState({ isShowingInfoBox: false }), + }), h('div.add-token__info-box__title', this.context.t('whatsThis')), h('div.add-token__info-box__copy', this.context.t('keepTrackTokens')), - h('div.add-token__info-box__copy--blue', this.context.t('learnMore')), + h('a.add-token__info-box__copy--blue', { + href: 'http://metamask.helpscoutdocs.com/article/16-managing-erc20-tokens', + target: '_blank', + }, this.context.t('learnMore')), ]), h('div.add-token__input-container', [ h('input.add-token__input', { @@ -379,23 +382,24 @@ AddTokenScreen.prototype.render = function () { isShowingConfirmation, displayedTab, } = this.state - const { goHome } = this.props + const { history } = this.props return h('div.add-token', [ h('div.add-token__header', [ h('div.add-token__header__cancel', { - onClick: () => goHome(), + onClick: () => history.push(DEFAULT_ROUTE), }, [ h('i.fa.fa-angle-left.fa-lg'), h('span', this.context.t('cancel')), ]), h('div.add-token__header__title', this.context.t('addTokens')), + isShowingConfirmation && h('div.add-token__header__subtitle', this.context.t('likeToAddTokens')), !isShowingConfirmation && h('div.add-token__header__tabs', [ h('div.add-token__header__tabs__tab', { className: classnames('add-token__header__tabs__tab', { 'add-token__header__tabs__selected': displayedTab === 'SEARCH', - 'add-token__header__tabs__unselected cursor-pointer': displayedTab !== 'SEARCH', + 'add-token__header__tabs__unselected': displayedTab !== 'SEARCH', }), onClick: () => this.displayTab('SEARCH'), }, this.context.t('search')), @@ -403,21 +407,21 @@ AddTokenScreen.prototype.render = function () { h('div.add-token__header__tabs__tab', { className: classnames('add-token__header__tabs__tab', { 'add-token__header__tabs__selected': displayedTab === 'CUSTOM_TOKEN', - 'add-token__header__tabs__unselected cursor-pointer': displayedTab !== 'CUSTOM_TOKEN', + 'add-token__header__tabs__unselected': displayedTab !== 'CUSTOM_TOKEN', }), onClick: () => this.displayTab('CUSTOM_TOKEN'), }, this.context.t('customToken')), ]), ]), -// + isShowingConfirmation ? this.renderConfirmation() : this.renderTabs(), !isShowingConfirmation && h('div.add-token__buttons', [ h('button.btn-secondary--lg.add-token__cancel-button', { - onClick: goHome, + onClick: () => history.push(DEFAULT_ROUTE), }, this.context.t('cancel')), h('button.btn-primary--lg.add-token__confirm-button', { onClick: this.onNext, diff --git a/ui/app/components/pages/authenticated.js b/ui/app/components/pages/authenticated.js new file mode 100644 index 000000000..1f6b0be49 --- /dev/null +++ b/ui/app/components/pages/authenticated.js @@ -0,0 +1,34 @@ +const { connect } = require('react-redux') +const PropTypes = require('prop-types') +const { Redirect } = require('react-router-dom') +const h = require('react-hyperscript') +const MetamaskRoute = require('./metamask-route') +const { UNLOCK_ROUTE, INITIALIZE_ROUTE } = require('../../routes') + +const Authenticated = props => { + const { isUnlocked, isInitialized } = props + + switch (true) { + case isUnlocked && isInitialized: + return h(MetamaskRoute, { ...props }) + case !isInitialized: + return h(Redirect, { to: { pathname: INITIALIZE_ROUTE } }) + default: + return h(Redirect, { to: { pathname: UNLOCK_ROUTE } }) + } +} + +Authenticated.propTypes = { + isUnlocked: PropTypes.bool, + isInitialized: PropTypes.bool, +} + +const mapStateToProps = state => { + const { metamask: { isUnlocked, isInitialized } } = state + return { + isUnlocked, + isInitialized, + } +} + +module.exports = connect(mapStateToProps)(Authenticated) diff --git a/ui/app/accounts/import/index.js b/ui/app/components/pages/create-account/import-account/index.js index 52d3dcde9..52d3dcde9 100644 --- a/ui/app/accounts/import/index.js +++ b/ui/app/components/pages/create-account/import-account/index.js diff --git a/ui/app/accounts/import/json.js b/ui/app/components/pages/create-account/import-account/json.js index e53c1c9ca..946907a47 100644 --- a/ui/app/accounts/import/json.js +++ b/ui/app/components/pages/create-account/import-account/json.js @@ -1,11 +1,12 @@ const Component = require('react').Component const PropTypes = require('prop-types') const h = require('react-hyperscript') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const connect = require('react-redux').connect -const actions = require('../../actions') +const actions = require('../../../../actions') const FileInput = require('react-simple-file-input').default - - +const { DEFAULT_ROUTE } = require('../../../../routes') const HELP_LINK = 'https://support.metamask.io/kb/article/7-importing-accounts' class JsonImportSubview extends Component { @@ -51,7 +52,7 @@ class JsonImportSubview extends Component { h('div.new-account-create-form__buttons', {}, [ h('button.btn-secondary.new-account-create-form__button', { - onClick: () => this.props.goHome(), + onClick: () => this.props.history.push(DEFAULT_ROUTE), }, [ this.context.t('cancel'), ]), @@ -112,6 +113,7 @@ JsonImportSubview.propTypes = { goHome: PropTypes.func, displayWarning: PropTypes.func, importNewJsonAccount: PropTypes.func, + history: PropTypes.object, t: PropTypes.func, } @@ -133,5 +135,7 @@ JsonImportSubview.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(JsonImportSubview) - +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(JsonImportSubview) diff --git a/ui/app/accounts/import/private-key.js b/ui/app/components/pages/create-account/import-account/private-key.js index 006131bdc..c77612ea4 100644 --- a/ui/app/accounts/import/private-key.js +++ b/ui/app/components/pages/create-account/import-account/private-key.js @@ -1,15 +1,21 @@ const inherits = require('util').inherits const Component = require('react').Component const h = require('react-hyperscript') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const PropTypes = require('prop-types') const connect = require('react-redux').connect -const actions = require('../../actions') +const actions = require('../../../../actions') +const { DEFAULT_ROUTE } = require('../../../../routes') PrivateKeyImportView.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(PrivateKeyImportView) +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(PrivateKeyImportView) function mapStateToProps (state) { @@ -20,9 +26,8 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - goHome: () => dispatch(actions.goHome()), importNewAccount: (strategy, [ privateKey ]) => { - dispatch(actions.importNewAccount(strategy, [ privateKey ])) + return dispatch(actions.importNewAccount(strategy, [ privateKey ])) }, displayWarning: () => dispatch(actions.displayWarning(null)), } @@ -30,11 +35,12 @@ function mapDispatchToProps (dispatch) { inherits(PrivateKeyImportView, Component) function PrivateKeyImportView () { + this.createKeyringOnEnter = this.createKeyringOnEnter.bind(this) Component.call(this) } PrivateKeyImportView.prototype.render = function () { - const { error, goHome } = this.props + const { error } = this.props return ( h('div.new-account-import-form__private-key', [ @@ -46,7 +52,7 @@ PrivateKeyImportView.prototype.render = function () { h('input.new-account-import-form__input-password', { type: 'password', id: 'private-key-box', - onKeyPress: () => this.createKeyringOnEnter(), + onKeyPress: e => this.createKeyringOnEnter(e), }), ]), @@ -54,7 +60,7 @@ PrivateKeyImportView.prototype.render = function () { h('div.new-account-import-form__buttons', {}, [ h('button.btn-secondary--lg.new-account-create-form__button', { - onClick: () => goHome(), + onClick: () => this.props.history.push(DEFAULT_ROUTE), }, [ this.context.t('cancel'), ]), @@ -82,6 +88,8 @@ PrivateKeyImportView.prototype.createKeyringOnEnter = function (event) { PrivateKeyImportView.prototype.createNewKeychain = function () { const input = document.getElementById('private-key-box') const privateKey = input.value + const { importNewAccount, history } = this.props - this.props.importNewAccount('Private Key', [ privateKey ]) + importNewAccount('Private Key', [ privateKey ]) + .then(() => history.push(DEFAULT_ROUTE)) } diff --git a/ui/app/accounts/import/seed.js b/ui/app/components/pages/create-account/import-account/seed.js index d98909baa..d98909baa 100644 --- a/ui/app/accounts/import/seed.js +++ b/ui/app/components/pages/create-account/import-account/seed.js diff --git a/ui/app/components/pages/create-account/index.js b/ui/app/components/pages/create-account/index.js new file mode 100644 index 000000000..0962477d8 --- /dev/null +++ b/ui/app/components/pages/create-account/index.js @@ -0,0 +1,81 @@ +const Component = require('react').Component +const { Switch, Route, matchPath } = require('react-router-dom') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const connect = require('react-redux').connect +const actions = require('../../../actions') +const { getCurrentViewContext } = require('../../../selectors') +const classnames = require('classnames') +const NewAccountCreateForm = require('./new-account') +const NewAccountImportForm = require('./import-account') +const { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE } = require('../../../routes') + +class CreateAccountPage extends Component { + renderTabs () { + const { history, location } = this.props + + return h('div.new-account__tabs', [ + h('div.new-account__tabs__tab', { + className: classnames('new-account__tabs__tab', { + 'new-account__tabs__selected': matchPath(location.pathname, { + path: NEW_ACCOUNT_ROUTE, exact: true, + }), + }), + onClick: () => history.push(NEW_ACCOUNT_ROUTE), + }, 'Create'), + + h('div.new-account__tabs__tab', { + className: classnames('new-account__tabs__tab', { + 'new-account__tabs__selected': matchPath(location.pathname, { + path: IMPORT_ACCOUNT_ROUTE, exact: true, + }), + }), + onClick: () => history.push(IMPORT_ACCOUNT_ROUTE), + }, 'Import'), + ]) + } + + render () { + return h('div.new-account', {}, [ + h('div.new-account__header', [ + h('div.new-account__title', 'New Account'), + this.renderTabs(), + ]), + h('div.new-account__form', [ + h(Switch, [ + h(Route, { + exact: true, + path: NEW_ACCOUNT_ROUTE, + component: NewAccountCreateForm, + }), + h(Route, { + exact: true, + path: IMPORT_ACCOUNT_ROUTE, + component: NewAccountImportForm, + }), + ]), + ]), + ]) + } +} + +CreateAccountPage.propTypes = { + location: PropTypes.object, + history: PropTypes.object, +} + +const mapStateToProps = state => ({ + displayedForm: getCurrentViewContext(state), +}) + +const mapDispatchToProps = dispatch => ({ + displayForm: form => dispatch(actions.setNewAccountForm(form)), + showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), + showExportPrivateKeyModal: () => { + dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) + }, + hideModal: () => dispatch(actions.hideModal()), + saveAccountLabel: (address, label) => dispatch(actions.saveAccountLabel(address, label)), +}) + +module.exports = connect(mapStateToProps, mapDispatchToProps)(CreateAccountPage) diff --git a/ui/app/accounts/new-account/create-form.js b/ui/app/components/pages/create-account/new-account.js index 48c74192a..40fa584be 100644 --- a/ui/app/accounts/new-account/create-form.js +++ b/ui/app/components/pages/create-account/new-account.js @@ -2,7 +2,8 @@ const { Component } = require('react') const PropTypes = require('prop-types') const h = require('react-hyperscript') const connect = require('react-redux').connect -const actions = require('../../actions') +const actions = require('../../../actions') +const { DEFAULT_ROUTE } = require('../../../routes') class NewAccountCreateForm extends Component { constructor (props, context) { @@ -19,7 +20,7 @@ class NewAccountCreateForm extends Component { render () { const { newAccountName, defaultAccountName } = this.state - + const { history, createAccount } = this.props return h('div.new-account-create-form', [ @@ -38,13 +39,16 @@ class NewAccountCreateForm extends Component { h('div.new-account-create-form__buttons', {}, [ h('button.btn-secondary--lg.new-account-create-form__button', { - onClick: () => this.props.goHome(), + onClick: () => history.push(DEFAULT_ROUTE), }, [ this.context.t('cancel'), ]), h('button.btn-primary--lg.new-account-create-form__button', { - onClick: () => this.props.createAccount(newAccountName || defaultAccountName), + onClick: () => { + createAccount(newAccountName || defaultAccountName) + .then(() => history.push(DEFAULT_ROUTE)) + }, }, [ this.context.t('create'), ]), @@ -59,8 +63,8 @@ NewAccountCreateForm.propTypes = { hideModal: PropTypes.func, showImportPage: PropTypes.func, createAccount: PropTypes.func, - goHome: PropTypes.func, numberOfExistingAccounts: PropTypes.number, + history: PropTypes.object, t: PropTypes.func, } @@ -77,23 +81,17 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - toCoinbase: (address) => { - dispatch(actions.buyEth({ network: '1', address, amount: 0 })) - }, - hideModal: () => { - dispatch(actions.hideModal()) - }, - createAccount: (newAccountName) => { - dispatch(actions.addNewAccount()) - .then((newAccountAddress) => { + toCoinbase: address => dispatch(actions.buyEth({ network: '1', address, amount: 0 })), + hideModal: () => dispatch(actions.hideModal()), + createAccount: newAccountName => { + return dispatch(actions.addNewAccount()) + .then(newAccountAddress => { if (newAccountName) { dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName)) } - dispatch(actions.goHome()) }) }, showImportPage: () => dispatch(actions.showImportPage()), - goHome: () => dispatch(actions.goHome()), } } diff --git a/ui/app/components/pages/home.js b/ui/app/components/pages/home.js new file mode 100644 index 000000000..7857a2a99 --- /dev/null +++ b/ui/app/components/pages/home.js @@ -0,0 +1,332 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const connect = require('../../metamask-connect') +const { Redirect, withRouter } = require('react-router-dom') +const { compose } = require('recompose') +const h = require('react-hyperscript') +const actions = require('../../actions') + +// init +const NewKeyChainScreen = require('../../new-keychain') +// mascara +const MascaraBuyEtherScreen = require('../../../../mascara/src/app/first-time/buy-ether-screen').default + +// accounts +const MainContainer = require('../../main-container') + +// other views +const BuyView = require('../../components/buy-button-subview') +const QrView = require('../../components/qr-code') + +// Routes +const { + REVEAL_SEED_ROUTE, + RESTORE_VAULT_ROUTE, + CONFIRM_TRANSACTION_ROUTE, + NOTICE_ROUTE, +} = require('../../routes') + +class Home extends Component { + componentDidMount () { + const { + history, + unapprovedTxs = {}, + unapprovedMsgCount = 0, + unapprovedPersonalMsgCount = 0, + unapprovedTypedMessagesCount = 0, + } = this.props + + // unapprovedTxs and unapproved messages + if (Object.keys(unapprovedTxs).length || + unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) { + history.push(CONFIRM_TRANSACTION_ROUTE) + } + } + + render () { + log.debug('rendering primary') + const { + noActiveNotices, + lostAccounts, + forgottenPassword, + currentView, + activeAddress, + seedWords, + } = this.props + + // notices + if (!noActiveNotices || (lostAccounts && lostAccounts.length > 0)) { + return h(Redirect, { + to: { + pathname: NOTICE_ROUTE, + }, + }) + } + + // seed words + if (seedWords) { + log.debug('rendering seed words') + return h(Redirect, { + to: { + pathname: REVEAL_SEED_ROUTE, + }, + }) + } + + if (forgottenPassword) { + log.debug('rendering restore vault screen') + return h(Redirect, { + to: { + pathname: RESTORE_VAULT_ROUTE, + }, + }) + } + + // if (!props.noActiveNotices) { + // log.debug('rendering notice screen for unread notices.') + // return h(NoticeScreen, { + // notice: props.lastUnreadNotice, + // key: 'NoticeScreen', + // onConfirm: () => props.dispatch(actions.markNoticeRead(props.lastUnreadNotice)), + // }) + // } else if (props.lostAccounts && props.lostAccounts.length > 0) { + // log.debug('rendering notice screen for lost accounts view.') + // return h(NoticeScreen, { + // notice: generateLostAccountsNotice(props.lostAccounts), + // key: 'LostAccountsNotice', + // onConfirm: () => props.dispatch(actions.markAccountsFound()), + // }) + // } + + // if (props.seedWords) { + // log.debug('rendering seed words') + // return h(HDCreateVaultComplete, {key: 'HDCreateVaultComplete'}) + // } + + // show initialize screen + // if (!isInitialized || forgottenPassword) { + // // show current view + // log.debug('rendering an initialize screen') + // // switch (props.currentView.name) { + + // // case 'restoreVault': + // // log.debug('rendering restore vault screen') + // // return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'}) + + // // default: + // // log.debug('rendering menu screen') + // // return h(InitializeScreen, {key: 'menuScreenInit'}) + // // } + // } + + // // show unlock screen + // if (!props.isUnlocked) { + // return h(MainContainer, { + // currentViewName: props.currentView.name, + // isUnlocked: props.isUnlocked, + // }) + // } + + // show current view + switch (currentView.name) { + + case 'accountDetail': + log.debug('rendering main container') + return h(MainContainer, {key: 'account-detail'}) + + // case 'sendTransaction': + // log.debug('rendering send tx screen') + + // // Going to leave this here until we are ready to delete SendTransactionScreen v1 + // // const SendComponentToRender = checkFeatureToggle('send-v2') + // // ? SendTransactionScreen2 + // // : SendTransactionScreen + + // return h(SendTransactionScreen2, {key: 'send-transaction'}) + + // case 'sendToken': + // log.debug('rendering send token screen') + + // // Going to leave this here until we are ready to delete SendTransactionScreen v1 + // // const SendTokenComponentToRender = checkFeatureToggle('send-v2') + // // ? SendTransactionScreen2 + // // : SendTokenScreen + + // return h(SendTransactionScreen2, {key: 'sendToken'}) + + case 'newKeychain': + log.debug('rendering new keychain screen') + return h(NewKeyChainScreen, {key: 'new-keychain'}) + + // case 'confTx': + // log.debug('rendering confirm tx screen') + // return h(Redirect, { + // to: { + // pathname: CONFIRM_TRANSACTION_ROUTE, + // }, + // }) + // return h(ConfirmTxScreen, {key: 'confirm-tx'}) + + // case 'add-token': + // log.debug('rendering add-token screen from unlock screen.') + // return h(AddTokenScreen, {key: 'add-token'}) + + // case 'config': + // log.debug('rendering config screen') + // return h(Settings, {key: 'config'}) + + // case 'import-menu': + // log.debug('rendering import screen') + // return h(Import, {key: 'import-menu'}) + + // case 'reveal-seed-conf': + // log.debug('rendering reveal seed confirmation screen') + // return h(RevealSeedConfirmation, {key: 'reveal-seed-conf'}) + + // case 'info': + // log.debug('rendering info screen') + // return h(Settings, {key: 'info', tab: 'info'}) + + case 'buyEth': + log.debug('rendering buy ether screen') + return h(BuyView, {key: 'buyEthView'}) + + case 'onboardingBuyEth': + log.debug('rendering onboarding buy ether screen') + return h(MascaraBuyEtherScreen, {key: 'buyEthView'}) + + case 'qr': + log.debug('rendering show qr screen') + return h('div', { + style: { + position: 'absolute', + height: '100%', + top: '0px', + left: '0px', + }, + }, [ + h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', { + onClick: () => this.props.dispatch(actions.backToAccountDetail(activeAddress)), + style: { + marginLeft: '10px', + marginTop: '50px', + }, + }), + h('div', { + style: { + position: 'absolute', + left: '44px', + width: '285px', + }, + }, [ + h(QrView, {key: 'qr'}), + ]), + ]) + + default: + log.debug('rendering default, account detail screen') + return h(MainContainer, {key: 'account-detail'}) + } + } +} + +Home.propTypes = { + currentCurrency: PropTypes.string, + isLoading: PropTypes.bool, + loadingMessage: PropTypes.string, + network: PropTypes.string, + provider: PropTypes.object, + frequentRpcList: PropTypes.array, + currentView: PropTypes.object, + sidebarOpen: PropTypes.bool, + isMascara: PropTypes.bool, + isOnboarding: PropTypes.bool, + isUnlocked: PropTypes.bool, + networkDropdownOpen: PropTypes.bool, + history: PropTypes.object, + dispatch: PropTypes.func, + selectedAddress: PropTypes.string, + noActiveNotices: PropTypes.bool, + lostAccounts: PropTypes.array, + isInitialized: PropTypes.bool, + forgottenPassword: PropTypes.bool, + activeAddress: PropTypes.string, + unapprovedTxs: PropTypes.object, + seedWords: PropTypes.string, + unapprovedMsgCount: PropTypes.number, + unapprovedPersonalMsgCount: PropTypes.number, + unapprovedTypedMessagesCount: PropTypes.number, + welcomeScreenSeen: PropTypes.bool, + isPopup: PropTypes.bool, + isMouseUser: PropTypes.bool, + t: PropTypes.func, +} + +function mapStateToProps (state) { + const { appState, metamask } = state + const { + networkDropdownOpen, + sidebarOpen, + isLoading, + loadingMessage, + } = appState + + const { + accounts, + address, + isInitialized, + noActiveNotices, + seedWords, + unapprovedTxs, + lastUnreadNotice, + lostAccounts, + unapprovedMsgCount, + unapprovedPersonalMsgCount, + unapprovedTypedMessagesCount, + } = metamask + const selected = address || Object.keys(accounts)[0] + + return { + // state from plugin + networkDropdownOpen, + sidebarOpen, + isLoading, + loadingMessage, + noActiveNotices, + isInitialized, + isUnlocked: state.metamask.isUnlocked, + selectedAddress: state.metamask.selectedAddress, + currentView: state.appState.currentView, + activeAddress: state.appState.activeAddress, + transForward: state.appState.transForward, + isMascara: state.metamask.isMascara, + isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized), + isPopup: state.metamask.isPopup, + seedWords: state.metamask.seedWords, + unapprovedTxs, + unapprovedMsgs: state.metamask.unapprovedMsgs, + unapprovedMsgCount, + unapprovedPersonalMsgCount, + unapprovedTypedMessagesCount, + menuOpen: state.appState.menuOpen, + network: state.metamask.network, + provider: state.metamask.provider, + forgottenPassword: state.appState.forgottenPassword, + lastUnreadNotice, + lostAccounts, + frequentRpcList: state.metamask.frequentRpcList || [], + currentCurrency: state.metamask.currentCurrency, + isMouseUser: state.appState.isMouseUser, + isRevealingSeedWords: state.metamask.isRevealingSeedWords, + Qr: state.appState.Qr, + welcomeScreenSeen: state.metamask.welcomeScreenSeen, + + // state needed to get account dropdown temporarily rendering from app bar + selected, + } +} + +module.exports = compose( + withRouter, + connect(mapStateToProps) +)(Home) diff --git a/ui/app/components/pages/initialized.js b/ui/app/components/pages/initialized.js new file mode 100644 index 000000000..3adf67b28 --- /dev/null +++ b/ui/app/components/pages/initialized.js @@ -0,0 +1,25 @@ +const { connect } = require('react-redux') +const PropTypes = require('prop-types') +const { Redirect } = require('react-router-dom') +const h = require('react-hyperscript') +const { INITIALIZE_ROUTE } = require('../../routes') +const MetamaskRoute = require('./metamask-route') + +const Initialized = props => { + return props.isInitialized + ? h(MetamaskRoute, { ...props }) + : h(Redirect, { to: { pathname: INITIALIZE_ROUTE } }) +} + +Initialized.propTypes = { + isInitialized: PropTypes.bool, +} + +const mapStateToProps = state => { + const { metamask: { isInitialized } } = state + return { + isInitialized, + } +} + +module.exports = connect(mapStateToProps)(Initialized) diff --git a/ui/app/components/pages/keychains/restore-vault.js b/ui/app/components/pages/keychains/restore-vault.js new file mode 100644 index 000000000..d57894e00 --- /dev/null +++ b/ui/app/components/pages/keychains/restore-vault.js @@ -0,0 +1,177 @@ +const { withRouter } = require('react-router-dom') +const PropTypes = require('prop-types') +const { compose } = require('recompose') +const PersistentForm = require('../../../../lib/persistent-form') +const connect = require('../../../metamask-connect') +const h = require('react-hyperscript') +const { createNewVaultAndRestore, unMarkPasswordForgotten } = require('../../../actions') +const { DEFAULT_ROUTE } = require('../../../routes') + +class RestoreVaultPage extends PersistentForm { + constructor (props) { + super(props) + + this.state = { + error: null, + } + } + + createOnEnter (event) { + if (event.key === 'Enter') { + this.createNewVaultAndRestore() + } + } + + cancel () { + this.props.unMarkPasswordForgotten() + .then(this.props.history.push(DEFAULT_ROUTE)) + } + + createNewVaultAndRestore () { + this.setState({ error: null }) + + // check password + var passwordBox = document.getElementById('password-box') + var password = passwordBox.value + var passwordConfirmBox = document.getElementById('password-box-confirm') + var passwordConfirm = passwordConfirmBox.value + + if (password.length < 8) { + this.setState({ error: 'Password not long enough' }) + return + } + + if (password !== passwordConfirm) { + this.setState({ error: 'Passwords don\'t match' }) + return + } + + // check seed + var seedBox = document.querySelector('textarea.twelve-word-phrase') + var seed = seedBox.value.trim() + if (seed.split(' ').length !== 12) { + this.setState({ error: 'Seed phrases are 12 words long' }) + return + } + + // submit + this.props.createNewVaultAndRestore(password, seed) + .then(() => this.props.history.push(DEFAULT_ROUTE)) + .catch(({ message }) => { + this.setState({ error: message }) + log.error(message) + }) + } + + render () { + const { error } = this.state + this.persistentFormParentId = 'restore-vault-form' + + return ( + h('.initialize-screen.flex-column.flex-center.flex-grow', [ + + h('h3.flex-center.text-transform-uppercase', { + style: { + background: '#EBEBEB', + color: '#AEAEAE', + marginBottom: 24, + width: '100%', + fontSize: '20px', + padding: 6, + }, + }, [ + this.props.t('restoreVault'), + ]), + + // wallet seed entry + h('h3', 'Wallet Seed'), + h('textarea.twelve-word-phrase.letter-spacey', { + dataset: { + persistentFormId: 'wallet-seed', + }, + placeholder: this.props.t('secretPhrase'), + }), + + // password + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box', + placeholder: this.props.t('newPassword8Chars'), + dataset: { + persistentFormId: 'password', + }, + style: { + width: 260, + marginTop: 12, + }, + }), + + // confirm password + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box-confirm', + placeholder: this.props.t('confirmPassword'), + onKeyPress: this.createOnEnter.bind(this), + dataset: { + persistentFormId: 'password-confirmation', + }, + style: { + width: 260, + marginTop: 16, + }, + }), + + error && ( + h('span.error.in-progress-notification', error) + ), + + // submit + h('.flex-row.flex-space-between', { + style: { + marginTop: 30, + width: '50%', + }, + }, [ + + // cancel + h('button.primary', { + onClick: () => this.cancel(), + }, this.props.t('cancel')), + + // submit + h('button.primary', { + onClick: this.createNewVaultAndRestore.bind(this), + }, this.props.t('ok')), + + ]), + ]) + ) + } +} + +RestoreVaultPage.propTypes = { + history: PropTypes.object, +} + +const mapStateToProps = state => { + const { appState: { warning, forgottenPassword } } = state + + return { + warning, + forgottenPassword, + } +} + +const mapDispatchToProps = dispatch => { + return { + createNewVaultAndRestore: (password, seed) => { + return dispatch(createNewVaultAndRestore(password, seed)) + }, + unMarkPasswordForgotten: () => dispatch(unMarkPasswordForgotten()), + } +} + +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(RestoreVaultPage) diff --git a/ui/app/components/pages/keychains/reveal-seed.js b/ui/app/components/pages/keychains/reveal-seed.js new file mode 100644 index 000000000..247f3c8e2 --- /dev/null +++ b/ui/app/components/pages/keychains/reveal-seed.js @@ -0,0 +1,195 @@ +const { Component } = require('react') +const { connect } = require('react-redux') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const { exportAsFile } = require('../../../util') +const { requestRevealSeed, confirmSeedWords } = require('../../../actions') +const { DEFAULT_ROUTE } = require('../../../routes') + +class RevealSeedPage extends Component { + componentDidMount () { + const passwordBox = document.getElementById('password-box') + if (passwordBox) { + passwordBox.focus() + } + } + + checkConfirmation (event) { + if (event.key === 'Enter') { + event.preventDefault() + this.revealSeedWords() + } + } + + revealSeedWords () { + const password = document.getElementById('password-box').value + this.props.requestRevealSeed(password) + } + + renderSeed () { + const { seedWords, confirmSeedWords, history } = this.props + + return ( + h('.initialize-screen.flex-column.flex-center.flex-grow', [ + + h('h3.flex-center.text-transform-uppercase', { + style: { + background: '#EBEBEB', + color: '#AEAEAE', + marginTop: 36, + marginBottom: 8, + width: '100%', + fontSize: '20px', + padding: 6, + }, + }, [ + 'Vault Created', + ]), + + h('div', { + style: { + fontSize: '1em', + marginTop: '10px', + textAlign: 'center', + }, + }, [ + h('span.error', 'These 12 words are the only way to restore your MetaMask accounts.\nSave them somewhere safe and secret.'), + ]), + + h('textarea.twelve-word-phrase', { + readOnly: true, + value: seedWords, + }), + + h('button.primary', { + onClick: () => confirmSeedWords().then(() => history.push(DEFAULT_ROUTE)), + style: { + margin: '24px', + fontSize: '0.9em', + marginBottom: '10px', + }, + }, 'I\'ve copied it somewhere safe'), + + h('button.primary', { + onClick: () => exportAsFile(`MetaMask Seed Words`, seedWords), + style: { + margin: '10px', + fontSize: '0.9em', + }, + }, 'Save Seed Words As File'), + ]) + ) + } + + renderConfirmation () { + const { history, warning, inProgress } = this.props + + return ( + h('.initialize-screen.flex-column.flex-center.flex-grow', { + style: { maxWidth: '420px' }, + }, [ + + h('h3.flex-center.text-transform-uppercase', { + style: { + background: '#EBEBEB', + color: '#AEAEAE', + marginBottom: 24, + width: '100%', + fontSize: '20px', + padding: 6, + }, + }, [ + 'Reveal Seed Words', + ]), + + h('.div', { + style: { + display: 'flex', + flexDirection: 'column', + padding: '20px', + justifyContent: 'center', + }, + }, [ + + h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'), + + // confirmation + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box', + placeholder: 'Enter your password to confirm', + onKeyPress: this.checkConfirmation.bind(this), + style: { + width: 260, + marginTop: '12px', + }, + }), + + h('.flex-row.flex-start', { + style: { + marginTop: 30, + width: '50%', + }, + }, [ + // cancel + h('button.primary', { + onClick: () => history.push(DEFAULT_ROUTE), + }, 'CANCEL'), + + // submit + h('button.primary', { + style: { marginLeft: '10px' }, + onClick: this.revealSeedWords.bind(this), + }, 'OK'), + + ]), + + warning && ( + h('span.error', { + style: { + margin: '20px', + }, + }, warning.split('-')) + ), + + inProgress && ( + h('span.in-progress-notification', 'Generating Seed...') + ), + ]), + ]) + ) + } + + render () { + return this.props.seedWords + ? this.renderSeed() + : this.renderConfirmation() + } +} + +RevealSeedPage.propTypes = { + requestRevealSeed: PropTypes.func, + confirmSeedWords: PropTypes.func, + seedWords: PropTypes.string, + inProgress: PropTypes.bool, + history: PropTypes.object, + warning: PropTypes.string, +} + +const mapStateToProps = state => { + const { appState: { warning }, metamask: { seedWords } } = state + + return { + warning, + seedWords, + } +} + +const mapDispatchToProps = dispatch => { + return { + requestRevealSeed: password => dispatch(requestRevealSeed(password)), + confirmSeedWords: () => dispatch(confirmSeedWords()), + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(RevealSeedPage) diff --git a/ui/app/components/pages/metamask-route.js b/ui/app/components/pages/metamask-route.js new file mode 100644 index 000000000..23c5b5199 --- /dev/null +++ b/ui/app/components/pages/metamask-route.js @@ -0,0 +1,28 @@ +const { connect } = require('react-redux') +const PropTypes = require('prop-types') +const { Route } = require('react-router-dom') +const h = require('react-hyperscript') + +const MetamaskRoute = ({ component, mascaraComponent, isMascara, ...props }) => { + return ( + h(Route, { + ...props, + component: isMascara && mascaraComponent ? mascaraComponent : component, + }) + ) +} + +MetamaskRoute.propTypes = { + component: PropTypes.func, + mascaraComponent: PropTypes.func, + isMascara: PropTypes.bool, +} + +const mapStateToProps = state => { + const { metamask: { isMascara } } = state + return { + isMascara, + } +} + +module.exports = connect(mapStateToProps)(MetamaskRoute) diff --git a/ui/app/components/pages/notice.js b/ui/app/components/pages/notice.js new file mode 100644 index 000000000..2329a9147 --- /dev/null +++ b/ui/app/components/pages/notice.js @@ -0,0 +1,203 @@ +const { Component } = require('react') +const h = require('react-hyperscript') +const { connect } = require('react-redux') +const PropTypes = require('prop-types') +const ReactMarkdown = require('react-markdown') +const linker = require('extension-link-enabler') +const generateLostAccountsNotice = require('../../../lib/lost-accounts-notice') +const findDOMNode = require('react-dom').findDOMNode +const actions = require('../../actions') +const { DEFAULT_ROUTE } = require('../../routes') + +class Notice extends Component { + constructor (props) { + super(props) + + this.state = { + disclaimerDisabled: true, + } + } + + componentWillMount () { + if (!this.props.notice) { + this.props.history.push(DEFAULT_ROUTE) + } + } + + componentDidMount () { + // eslint-disable-next-line react/no-find-dom-node + var node = findDOMNode(this) + linker.setupListener(node) + if (document.getElementsByClassName('notice-box')[0].clientHeight < 310) { + this.setState({ disclaimerDisabled: false }) + } + } + + componentWillReceiveProps (nextProps) { + if (!nextProps.notice) { + this.props.history.push(DEFAULT_ROUTE) + } + } + + componentWillUnmount () { + // eslint-disable-next-line react/no-find-dom-node + var node = findDOMNode(this) + linker.teardownListener(node) + } + + handleAccept () { + this.setState({ disclaimerDisabled: true }) + this.props.onConfirm() + } + + render () { + const { notice = {} } = this.props + const { title, date, body } = notice + const { disclaimerDisabled } = this.state + + return ( + h('.flex-column.flex-center.flex-grow', { + style: { + width: '100%', + }, + }, [ + h('h3.flex-center.text-transform-uppercase.terms-header', { + style: { + background: '#EBEBEB', + color: '#AEAEAE', + width: '100%', + fontSize: '20px', + textAlign: 'center', + padding: 6, + }, + }, [ + title, + ]), + + h('h5.flex-center.text-transform-uppercase.terms-header', { + style: { + background: '#EBEBEB', + color: '#AEAEAE', + marginBottom: 24, + width: '100%', + fontSize: '20px', + textAlign: 'center', + padding: 6, + }, + }, [ + date, + ]), + + h('style', ` + + .markdown { + overflow-x: hidden; + } + + .markdown h1, .markdown h2, .markdown h3 { + margin: 10px 0; + font-weight: bold; + } + + .markdown strong { + font-weight: bold; + } + .markdown em { + font-style: italic; + } + + .markdown p { + margin: 10px 0; + } + + .markdown a { + color: #df6b0e; + } + + `), + + h('div.markdown', { + onScroll: (e) => { + var object = e.currentTarget + if (object.offsetHeight + object.scrollTop + 100 >= object.scrollHeight) { + this.setState({ disclaimerDisabled: false }) + } + }, + style: { + background: 'rgb(235, 235, 235)', + height: '310px', + padding: '6px', + width: '90%', + overflowY: 'scroll', + scroll: 'auto', + }, + }, [ + h(ReactMarkdown, { + className: 'notice-box', + source: body, + skipHtml: true, + }), + ]), + + h('button.primary', { + disabled: disclaimerDisabled, + onClick: () => this.handleAccept(), + style: { + marginTop: '18px', + }, + }, 'Accept'), + ]) + ) + } + +} + +const mapStateToProps = state => { + const { metamask } = state + const { noActiveNotices, lastUnreadNotice, lostAccounts } = metamask + + return { + noActiveNotices, + lastUnreadNotice, + lostAccounts, + } +} + +Notice.propTypes = { + notice: PropTypes.object, + onConfirm: PropTypes.func, + history: PropTypes.object, +} + +const mapDispatchToProps = dispatch => { + return { + markNoticeRead: lastUnreadNotice => dispatch(actions.markNoticeRead(lastUnreadNotice)), + markAccountsFound: () => dispatch(actions.markAccountsFound()), + } +} + +const mergeProps = (stateProps, dispatchProps, ownProps) => { + const { noActiveNotices, lastUnreadNotice, lostAccounts } = stateProps + const { markNoticeRead, markAccountsFound } = dispatchProps + + let notice + let onConfirm + + if (!noActiveNotices) { + notice = lastUnreadNotice + onConfirm = () => markNoticeRead(lastUnreadNotice) + } else if (lostAccounts && lostAccounts.length > 0) { + notice = generateLostAccountsNotice(lostAccounts) + onConfirm = () => markAccountsFound() + } + + return { + ...stateProps, + ...dispatchProps, + ...ownProps, + notice, + onConfirm, + } +} + +module.exports = connect(mapStateToProps, mapDispatchToProps, mergeProps)(Notice) diff --git a/ui/app/components/pages/settings/index.js b/ui/app/components/pages/settings/index.js new file mode 100644 index 000000000..384ae4b41 --- /dev/null +++ b/ui/app/components/pages/settings/index.js @@ -0,0 +1,59 @@ +const { Component } = require('react') +const { Switch, Route, matchPath } = require('react-router-dom') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const TabBar = require('../../tab-bar') +const Settings = require('./settings') +const Info = require('./info') +const { DEFAULT_ROUTE, SETTINGS_ROUTE, INFO_ROUTE } = require('../../../routes') + +class Config extends Component { + renderTabs () { + const { history, location } = this.props + + return h('div.settings__tabs', [ + h(TabBar, { + tabs: [ + { content: 'Settings', key: SETTINGS_ROUTE }, + { content: 'Info', key: INFO_ROUTE }, + ], + isActive: key => matchPath(location.pathname, { path: key, exact: true }), + onSelect: key => history.push(key), + }), + ]) + } + + render () { + const { history } = this.props + + return ( + h('.main-container.settings', {}, [ + h('.settings__header', [ + h('div.settings__close-button', { + onClick: () => history.push(DEFAULT_ROUTE), + }), + this.renderTabs(), + ]), + h(Switch, [ + h(Route, { + exact: true, + path: INFO_ROUTE, + component: Info, + }), + h(Route, { + exact: true, + path: SETTINGS_ROUTE, + component: Settings, + }), + ]), + ]) + ) + } +} + +Config.propTypes = { + location: PropTypes.object, + history: PropTypes.object, +} + +module.exports = Config diff --git a/ui/app/components/pages/settings/info.js b/ui/app/components/pages/settings/info.js new file mode 100644 index 000000000..eb9be66e6 --- /dev/null +++ b/ui/app/components/pages/settings/info.js @@ -0,0 +1,112 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') + +class Info extends Component { + renderLogo () { + return ( + h('div.settings__info-logo-wrapper', [ + h('img.settings__info-logo', { src: 'images/info-logo.png' }), + ]) + ) + } + + renderInfoLinks () { + return ( + h('div.settings__content-item.settings__content-item--without-height', [ + h('div.settings__info-link-header', this.context.t('links')), + h('div.settings__info-link-item', [ + h('a', { + href: 'https://metamask.io/privacy.html', + target: '_blank', + }, [ + h('span.settings__info-link', this.context.t('privacyMsg')), + ]), + ]), + h('div.settings__info-link-item', [ + h('a', { + href: 'https://metamask.io/terms.html', + target: '_blank', + }, [ + h('span.settings__info-link', this.context.t('terms')), + ]), + ]), + h('div.settings__info-link-item', [ + h('a', { + href: 'https://metamask.io/attributions.html', + target: '_blank', + }, [ + h('span.settings__info-link', this.context.t('attributions')), + ]), + ]), + h('hr.settings__info-separator'), + h('div.settings__info-link-item', [ + h('a', { + href: 'https://support.metamask.io', + target: '_blank', + }, [ + h('span.settings__info-link', this.context.t('supportCenter')), + ]), + ]), + h('div.settings__info-link-item', [ + h('a', { + href: 'https://metamask.io/', + target: '_blank', + }, [ + h('span.settings__info-link', this.context.t('visitWebSite')), + ]), + ]), + h('div.settings__info-link-item', [ + h('a', { + target: '_blank', + href: 'mailto:help@metamask.io?subject=Feedback', + }, [ + h('span.settings__info-link', this.context.t('emailUs')), + ]), + ]), + ]) + ) + } + + render () { + return ( + h('div.settings__content', [ + h('div.settings__content-row', [ + h('div.settings__content-item.settings__content-item--without-height', [ + this.renderLogo(), + h('div.settings__info-item', [ + h('div.settings__info-version-header', 'MetaMask Version'), + h('div.settings__info-version-number', '4.0.0'), + ]), + h('div.settings__info-item', [ + h( + 'div.settings__info-about', + this.context.t('builtInCalifornia') + ), + ]), + ]), + this.renderInfoLinks(), + ]), + ]) + ) + } +} + +Info.propTypes = { + tab: PropTypes.string, + metamask: PropTypes.object, + setCurrentCurrency: PropTypes.func, + setRpcTarget: PropTypes.func, + displayWarning: PropTypes.func, + revealSeedConfirmation: PropTypes.func, + warning: PropTypes.string, + location: PropTypes.object, + history: PropTypes.object, + t: PropTypes.func, +} + +Info.contextTypes = { + t: PropTypes.func, +} + +module.exports = Info diff --git a/ui/app/settings.js b/ui/app/components/pages/settings/settings.js index 3aa7b9c6b..05a7379fb 100644 --- a/ui/app/settings.js +++ b/ui/app/components/pages/settings/settings.js @@ -1,16 +1,18 @@ const { Component } = require('react') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const PropTypes = require('prop-types') const h = require('react-hyperscript') const connect = require('react-redux').connect -const actions = require('./actions') -const infuraCurrencies = require('./infura-conversion.json') +const actions = require('../../../actions') +const infuraCurrencies = require('../../../infura-conversion.json') const validUrl = require('valid-url') -const { exportAsFile } = require('./util') -const TabBar = require('./components/tab-bar') -const SimpleDropdown = require('./components/dropdowns/simple-dropdown') +const { exportAsFile } = require('../../../util') +const SimpleDropdown = require('../../dropdowns/simple-dropdown') const ToggleButton = require('react-toggle-button') -const locales = require('../../app/_locales/index.json') -const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums +const { REVEAL_SEED_ROUTE } = require('../../../routes') +const locales = require('../../../../../app/_locales/index.json') +const { OLD_UI_NETWORK_TYPE } = require('../../../../../app/scripts/config').enums const getInfuraCurrencyOptions = () => { const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { @@ -40,30 +42,11 @@ class Settings extends Component { constructor (props) { super(props) - const { tab } = props - const activeTab = tab === 'info' ? 'info' : 'settings' - this.state = { - activeTab, newRpc: '', } } - renderTabs () { - const { activeTab } = this.state - - return h('div.settings__tabs', [ - h(TabBar, { - tabs: [ - { content: this.context.t('settings'), key: 'settings' }, - { content: this.context.t('info'), key: 'info' }, - ], - defaultTab: activeTab, - tabSelected: key => this.setState({ activeTab: key }), - }), - ]) - } - renderBlockieOptIn () { const { metamask: { useBlockie }, setUseBlockie } = this.props @@ -253,7 +236,7 @@ class Settings extends Component { } renderSeedWords () { - const { revealSeedConfirmation } = this.props + const { history } = this.props return ( h('div.settings__content-row', [ @@ -261,9 +244,9 @@ class Settings extends Component { h('div.settings__content-item', [ h('div.settings__content-item-col', [ h('button.btn-primary--lg.settings__button--red', { - onClick (event) { + onClick: event => { event.preventDefault() - revealSeedConfirmation() + history.push(REVEAL_SEED_ROUTE) }, }, this.context.t('revealSeedWords')), ]), @@ -310,7 +293,7 @@ class Settings extends Component { ]) } - renderSettingsContent () { + render () { const { warning, isMascara } = this.props return ( @@ -328,120 +311,9 @@ class Settings extends Component { ]) ) } - - renderLogo () { - return ( - h('div.settings__info-logo-wrapper', [ - h('img.settings__info-logo', { src: 'images/info-logo.png' }), - ]) - ) - } - - renderInfoLinks () { - return ( - h('div.settings__content-item.settings__content-item--without-height', [ - h('div.settings__info-link-header', this.context.t('links')), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/privacy.html', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('privacyMsg')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/terms.html', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('terms')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/attributions.html', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('attributions')), - ]), - ]), - h('hr.settings__info-separator'), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://support.metamask.io', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('supportCenter')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - href: 'https://metamask.io/', - target: '_blank', - }, [ - h('span.settings__info-link', this.context.t('visitWebSite')), - ]), - ]), - h('div.settings__info-link-item', [ - h('a', { - target: '_blank', - href: 'mailto:help@metamask.io?subject=Feedback', - }, [ - h('span.settings__info-link', this.context.t('emailUs')), - ]), - ]), - ]) - ) - } - - renderInfoContent () { - const version = global.platform.getVersion() - - return ( - h('div.settings__content', [ - h('div.settings__content-row', [ - h('div.settings__content-item.settings__content-item--without-height', [ - this.renderLogo(), - h('div.settings__info-item', [ - h('div.settings__info-version-header', 'MetaMask Version'), - h('div.settings__info-version-number', `${version}`), - ]), - h('div.settings__info-item', [ - h( - 'div.settings__info-about', - this.context.t('builtInCalifornia') - ), - ]), - ]), - this.renderInfoLinks(), - ]), - ]) - ) - } - - render () { - const { goHome } = this.props - const { activeTab } = this.state - - return ( - h('.main-container.settings', {}, [ - h('.settings__header', [ - h('div.settings__close-button', { - onClick: goHome, - }), - this.renderTabs(), - ]), - - activeTab === 'settings' - ? this.renderSettingsContent() - : this.renderInfoContent(), - ]) - ) - } } Settings.propTypes = { - tab: PropTypes.string, metamask: PropTypes.object, setUseBlockie: PropTypes.func, setCurrentCurrency: PropTypes.func, @@ -451,7 +323,7 @@ Settings.propTypes = { setFeatureFlagToBeta: PropTypes.func, showResetAccountConfirmationModal: PropTypes.func, warning: PropTypes.string, - goHome: PropTypes.func, + history: PropTypes.object, isMascara: PropTypes.bool, updateCurrentLocale: PropTypes.func, currentLocale: PropTypes.string, @@ -469,7 +341,6 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - goHome: () => dispatch(actions.goHome()), setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)), setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)), displayWarning: warning => dispatch(actions.displayWarning(warning)), @@ -490,5 +361,7 @@ Settings.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(Settings) - +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(Settings) diff --git a/ui/app/components/pages/unlock.js b/ui/app/components/pages/unlock.js new file mode 100644 index 000000000..b3320da21 --- /dev/null +++ b/ui/app/components/pages/unlock.js @@ -0,0 +1,193 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const connect = require('../../metamask-connect') +const h = require('react-hyperscript') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') +const { + tryUnlockMetamask, + forgotPassword, + markPasswordForgotten, + setNetworkEndpoints, + setFeatureFlag, +} = require('../../actions') +const environmentType = require('../../../../app/scripts/lib/environment-type') +const getCaretCoordinates = require('textarea-caret') +const EventEmitter = require('events').EventEmitter +const Mascot = require('../mascot') +const { OLD_UI_NETWORK_TYPE } = require('../../../../app/scripts/config').enums +const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../routes') + +class UnlockScreen extends Component { + constructor (props) { + super(props) + + this.state = { + error: null, + } + + this.animationEventEmitter = new EventEmitter() + } + + componentWillMount () { + const { isUnlocked, history } = this.props + + if (isUnlocked) { + history.push(DEFAULT_ROUTE) + } + } + + componentDidMount () { + const passwordBox = document.getElementById('password-box') + + if (passwordBox) { + passwordBox.focus() + } + } + + tryUnlockMetamask (password) { + const { tryUnlockMetamask, history } = this.props + tryUnlockMetamask(password) + .then(() => history.push(DEFAULT_ROUTE)) + .catch(({ message }) => this.setState({ error: message })) + } + + onSubmit (event) { + const input = document.getElementById('password-box') + const password = input.value + this.tryUnlockMetamask(password) + } + + onKeyPress (event) { + if (event.key === 'Enter') { + this.submitPassword(event) + } + } + + submitPassword (event) { + var element = event.target + var password = element.value + // reset input + element.value = '' + this.tryUnlockMetamask(password) + } + + inputChanged (event) { + // tell mascot to look at page action + var element = event.target + var boundingRect = element.getBoundingClientRect() + var coordinates = getCaretCoordinates(element, element.selectionEnd) + this.animationEventEmitter.emit('point', { + x: boundingRect.left + coordinates.left - element.scrollLeft, + y: boundingRect.top + coordinates.top - element.scrollTop, + }) + } + + render () { + const { error } = this.state + return ( + h('.unlock-screen', [ + + h(Mascot, { + animationEventEmitter: this.animationEventEmitter, + }), + + h('h1', { + style: { + fontSize: '1.4em', + textTransform: 'uppercase', + color: '#7F8082', + }, + }, this.props.t('appName')), + + h('input.large-input', { + type: 'password', + id: 'password-box', + placeholder: 'enter password', + style: { + background: 'white', + }, + onKeyPress: this.onKeyPress.bind(this), + onInput: this.inputChanged.bind(this), + }), + + h('.error', { + style: { + display: error ? 'block' : 'none', + padding: '0 20px', + textAlign: 'center', + }, + }, error), + + h('button.primary.cursor-pointer', { + onClick: this.onSubmit.bind(this), + style: { + margin: 10, + }, + }, this.props.t('login')), + + h('p.pointer', { + onClick: () => { + this.props.markPasswordForgotten() + this.props.history.push(RESTORE_VAULT_ROUTE) + + if (environmentType() === 'popup') { + global.platform.openExtensionInBrowser() + } + }, + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, this.props.t('restoreFromSeed')), + + h('p.pointer', { + onClick: () => { + this.props.useOldInterface() + .then(() => this.props.setNetworkEndpoints(OLD_UI_NETWORK_TYPE)) + }, + style: { + fontSize: '0.8em', + color: '#aeaeae', + textDecoration: 'underline', + marginTop: '32px', + }, + }, this.props.t('classicInterface')), + ]) + ) + } +} + +UnlockScreen.propTypes = { + forgotPassword: PropTypes.func, + tryUnlockMetamask: PropTypes.func, + markPasswordForgotten: PropTypes.func, + history: PropTypes.object, + isUnlocked: PropTypes.bool, + t: PropTypes.func, + useOldInterface: PropTypes.func, + setNetworkEndpoints: PropTypes.func, +} + +const mapStateToProps = state => { + const { metamask: { isUnlocked } } = state + return { + isUnlocked, + } +} + +const mapDispatchToProps = dispatch => { + return { + forgotPassword: () => dispatch(forgotPassword()), + tryUnlockMetamask: password => dispatch(tryUnlockMetamask(password)), + markPasswordForgotten: () => dispatch(markPasswordForgotten()), + useOldInterface: () => dispatch(setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')), + setNetworkEndpoints: type => dispatch(setNetworkEndpoints(type)), + } +} + +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(UnlockScreen) diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 2e4e0fbe5..16dbd273b 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -1,4 +1,6 @@ const Component = require('react').Component +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const PropTypes = require('prop-types') const connect = require('react-redux').connect const h = require('react-hyperscript') @@ -25,12 +27,16 @@ const currencyFormatter = require('currency-formatter') const currencies = require('currency-formatter/currencies') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') +const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes') ConfirmSendEther.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther) +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(ConfirmSendEther) function mapStateToProps (state) { @@ -74,7 +80,6 @@ function mapDispatchToProps (dispatch) { errors: { to: null, amount: null }, editingTransactionId: id, })) - dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), showCustomizeGasModal: (txMeta, sendGasLimit, sendGasPrice, sendGasTotal) => { @@ -239,6 +244,7 @@ ConfirmSendEther.prototype.getData = function () { const { identities } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} + const account = identities ? identities[txParams.from] || {} : {} const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH, gasFeeInHex } = this.getGasFee() const { FIAT: amountInFIAT, ETH: amountInETH } = this.getAmount() @@ -254,7 +260,7 @@ ConfirmSendEther.prototype.getData = function () { return { from: { address: txParams.from, - name: identities[txParams.from].name, + name: account.name, }, to: { address: txParams.to, @@ -281,9 +287,14 @@ ConfirmSendEther.prototype.convertToRenderableCurrency = function (value, curren : value } +ConfirmSendEther.prototype.editTransaction = function (txMeta) { + const { editTransaction, history } = this.props + editTransaction(txMeta) + history.push(SEND_ROUTE) +} + ConfirmSendEther.prototype.render = function () { const { - editTransaction, currentCurrency, clearSend, conversionRate, @@ -342,7 +353,7 @@ ConfirmSendEther.prototype.render = function () { h('.page-container__header', [ h('.page-container__header-row', [ h('span.page-container__back-button', { - onClick: () => editTransaction(txMeta), + onClick: () => this.editTransaction(txMeta), style: { visibility: !txMeta.lastGasPrice ? 'initial' : 'hidden', }, @@ -520,7 +531,9 @@ ConfirmSendEther.prototype.render = function () { }, this.context.t('cancel')), // Accept Button - h('button.btn-confirm.page-container__footer-button.allcaps', [this.context.t('confirm')]), + h('button.btn-confirm.page-container__footer-button.allcaps', { + onClick: event => this.onSubmit(event), + }, this.context.t('confirm')), ]), ]), ]) @@ -558,6 +571,7 @@ ConfirmSendEther.prototype.cancel = function (event, txMeta) { const { cancelTransaction } = this.props cancelTransaction(txMeta) + .then(() => this.props.history.push(DEFAULT_ROUTE)) } ConfirmSendEther.prototype.isBalanceSufficient = function (txMeta) { @@ -645,4 +659,4 @@ ConfirmSendEther.prototype.bnMultiplyByFraction = function (targetBN, numerator, const numBN = new BN(numerator) const denomBN = new BN(denominator) return targetBN.mul(numBN).div(denomBN) -}
\ No newline at end of file +} diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 65b9b9d07..3d59ab3fd 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -1,4 +1,6 @@ const Component = require('react').Component +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const PropTypes = require('prop-types') const connect = require('react-redux').connect const h = require('react-hyperscript') @@ -35,12 +37,16 @@ const { getSelectedAddress, getSelectedTokenContract, } = require('../../selectors') +const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes') ConfirmSendToken.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendToken) +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(ConfirmSendToken) function mapStateToProps (state, ownProps) { @@ -149,6 +155,12 @@ function ConfirmSendToken () { this.onSubmit = this.onSubmit.bind(this) } +ConfirmSendToken.prototype.editTransaction = function (txMeta) { + const { editTransaction, history } = this.props + editTransaction(txMeta) + history.push(SEND_ROUTE) +} + ConfirmSendToken.prototype.updateComponentSendErrors = function (prevProps) { const { balance: oldBalance, @@ -423,7 +435,6 @@ ConfirmSendToken.prototype.convertToRenderableCurrency = function (value, curren } ConfirmSendToken.prototype.render = function () { - const { editTransaction } = this.props const txMeta = this.gatherTxMeta() const { from: { @@ -450,7 +461,7 @@ ConfirmSendToken.prototype.render = function () { h('div.page-container', [ h('div.page-container__header', [ !txMeta.lastGasPrice && h('button.confirm-screen-back-button', { - onClick: () => editTransaction(txMeta), + onClick: () => this.editTransaction(txMeta), }, this.context.t('edit')), h('div.page-container__title', title), h('div.page-container__subtitle', subtitle), @@ -530,7 +541,9 @@ ConfirmSendToken.prototype.render = function () { }, this.context.t('cancel')), // Accept Button - h('button.btn-confirm.page-container__footer-button.allcaps', [this.context.t('confirm')]), + h('button.btn-confirm.page-container__footer-button.allcaps', { + onClick: event => this.onSubmit(event), + }, [this.context.t('confirm')]), ]), ]), ]), @@ -583,6 +596,7 @@ ConfirmSendToken.prototype.cancel = function (event, txMeta) { const { cancelTransaction } = this.props cancelTransaction(txMeta) + .then(() => this.props.history.push(DEFAULT_ROUTE)) } ConfirmSendToken.prototype.checkValidity = function () { diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 08c26a91f..aca1a5a0a 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -2,6 +2,8 @@ const connect = require('react-redux').connect const actions = require('../../actions') const abi = require('ethereumjs-abi') const SendEther = require('../../send-v2') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const { accountsWithSendEtherInfoSelector, @@ -16,7 +18,10 @@ const { getSelectedTokenContract, } = require('../../selectors') -module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther) +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(SendEther) function mapStateToProps (state) { const fromAccounts = accountsWithSendEtherInfoSelector(state) @@ -79,7 +84,6 @@ function mapDispatchToProps (dispatch) { updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)), updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), - goHome: () => dispatch(actions.goHome()), clearSend: () => dispatch(actions.clearSend()), setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)), } diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index 41415411e..b958a2d2d 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -6,6 +6,8 @@ const Identicon = require('./identicon') const connect = require('react-redux').connect const ethUtil = require('ethereumjs-util') const classnames = require('classnames') +const { compose } = require('recompose') +const { withRouter } = require('react-router-dom') const AccountDropdownMini = require('./dropdowns/account-dropdown-mini') @@ -20,6 +22,8 @@ const { conversionRateSelector, } = require('../selectors.js') +const { DEFAULT_ROUTE } = require('../routes') + function mapStateToProps (state) { return { balance: getSelectedAccount(state).balance, @@ -42,7 +46,10 @@ SignatureRequest.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(SignatureRequest) +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(SignatureRequest) inherits(SignatureRequest, Component) @@ -229,10 +236,14 @@ SignatureRequest.prototype.renderFooter = function () { return h('div.request-signature__footer', [ h('button.btn-secondary--lg.request-signature__footer__cancel-button', { - onClick: cancel, + onClick: event => { + cancel(event).then(() => this.props.history.push(DEFAULT_ROUTE)) + }, }, this.context.t('cancel')), h('button.btn-primary--lg', { - onClick: sign, + onClick: event => { + sign(event).then(() => this.props.history.push(DEFAULT_ROUTE)) + }, }, this.context.t('sign')), ]) } diff --git a/ui/app/components/tab-bar.js b/ui/app/components/tab-bar.js index a80640116..0016a09c1 100644 --- a/ui/app/components/tab-bar.js +++ b/ui/app/components/tab-bar.js @@ -4,31 +4,17 @@ const PropTypes = require('prop-types') const classnames = require('classnames') class TabBar extends Component { - constructor (props) { - super(props) - const { defaultTab, tabs } = props - - this.state = { - subview: defaultTab || tabs[0].key, - } - } - render () { - const { tabs = [], tabSelected } = this.props - const { subview } = this.state + const { tabs = [], onSelect, isActive } = this.props return ( h('.tab-bar', {}, [ - tabs.map((tab) => { - const { key, content } = tab + tabs.map(({ key, content }) => { return h('div', { className: classnames('tab-bar__tab pointer', { - 'tab-bar__tab--active': subview === key, + 'tab-bar__tab--active': isActive(key, content), }), - onClick: () => { - this.setState({ subview: key }) - tabSelected(key) - }, + onClick: () => onSelect(key), key, }, content) }), @@ -39,9 +25,9 @@ class TabBar extends Component { } TabBar.propTypes = { - defaultTab: PropTypes.string, + isActive: PropTypes.func.isRequired, tabs: PropTypes.array, - tabSelected: PropTypes.func, + onSelect: PropTypes.func, } module.exports = TabBar diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 740c4a4ab..554febcff 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -11,14 +11,19 @@ const { formatDate } = require('../util') const { showConfTxPage } = require('../actions') const classnames = require('classnames') const { tokenInfoGetter } = require('../token-util') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') +const { CONFIRM_TRANSACTION_ROUTE } = require('../routes') + +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(TxList) TxList.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList) - - function mapStateToProps (state) { return { txsToRender: selectors.transactionsSelector(state), @@ -96,7 +101,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa transactionNetworkId, transactionSubmittedTime, } = props - const { showConfTxPage } = this.props + const { history } = this.props const opts = { key: transactionId || transactionHash, @@ -116,7 +121,10 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa const isUnapproved = transactionStatus === 'unapproved' if (isUnapproved) { - opts.onClick = () => showConfTxPage({ id: transactionId }) + opts.onClick = () => { + this.props.showConfTxPage({ id: transactionId }) + history.push(CONFIRM_TRANSACTION_ROUTE) + } opts.transactionStatus = this.context.t('notStarted') } else if (transactionHash) { opts.onClick = () => this.view(transactionHash, transactionNetworkId) diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index ca24e813f..80aac35c4 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -4,20 +4,25 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const actions = require('../actions') const selectors = require('../selectors') +const { SEND_ROUTE } = require('../routes') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') const Identicon = require('./identicon') +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(TxView) + TxView.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) - - function mapStateToProps (state) { const sidebarOpen = state.appState.sidebarOpen const isMascara = state.appState.isMascara @@ -69,7 +74,7 @@ TxView.prototype.renderHeroBalance = function () { } TxView.prototype.renderButtons = function () { - const {selectedToken, showModal, showSendPage, showSendTokenPage } = this.props + const {selectedToken, showModal, history } = this.props return !selectedToken ? ( @@ -84,14 +89,14 @@ TxView.prototype.renderButtons = function () { style: { marginLeft: '0.8em', }, - onClick: showSendPage, + onClick: () => history.push(SEND_ROUTE), }, this.context.t('send')), ]) ) : ( h('div.flex-row.flex-center.hero-balance-buttons', [ h('button.btn-primary.hero-balance-button', { - onClick: showSendTokenPage, + onClick: () => history.push(SEND_ROUTE), }, this.context.t('send')), ]) ) diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index e6b94ad12..e3e1b8903 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -2,6 +2,8 @@ const Component = require('react').Component const PropTypes = require('prop-types') const connect = require('react-redux').connect const h = require('react-hyperscript') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const inherits = require('util').inherits const classnames = require('classnames') const Identicon = require('./identicon') @@ -12,14 +14,17 @@ const actions = require('../actions') const BalanceComponent = require('./balance-component') const TokenList = require('./token-list') const selectors = require('../selectors') +const { ADD_TOKEN_ROUTE } = require('../routes') + +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(WalletView) WalletView.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView) - - function mapStateToProps (state) { return { @@ -97,7 +102,7 @@ WalletView.prototype.render = function () { keyrings, showAccountDetailModal, hideSidebar, - showAddTokenPage, + history, } = this.props // temporary logs + fake extra wallets // console.log('walletview, selectedAccount:', selectedAccount) @@ -174,10 +179,7 @@ WalletView.prototype.render = function () { h(TokenList), h('button.btn-primary.wallet-view__add-token-button', { - onClick: () => { - showAddTokenPage() - hideSidebar() - }, + onClick: () => history.push(ADD_TOKEN_ROUTE), }, this.context.t('addToken')), ]) } diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index 1070436c3..fee7cd36f 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -2,6 +2,8 @@ const inherits = require('util').inherits const Component = require('react').Component const h = require('react-hyperscript') const connect = require('react-redux').connect +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const actions = require('./actions') const txHelper = require('../lib/tx-helper') @@ -11,19 +13,21 @@ const SignatureRequest = require('./components/signature-request') // const PendingPersonalMsg = require('./components/pending-personal-msg') // const PendingTypedMsg = require('./components/pending-typed-msg') const Loading = require('./components/loading') +const { DEFAULT_ROUTE } = require('./routes') -// const contentDivider = h('div', { -// style: { -// marginLeft: '16px', -// marginRight: '16px', -// height:'1px', -// background:'#E7E7E7', -// }, -// }) - -module.exports = connect(mapStateToProps)(ConfirmTxScreen) +module.exports = compose( + withRouter, + connect(mapStateToProps) +)(ConfirmTxScreen) function mapStateToProps (state) { + const { metamask } = state + const { + unapprovedMsgCount, + unapprovedPersonalMsgCount, + unapprovedTypedMessagesCount, + } = metamask + return { identities: state.metamask.identities, accounts: state.metamask.accounts, @@ -40,6 +44,10 @@ function mapStateToProps (state) { currentCurrency: state.metamask.currentCurrency, blockGasLimit: state.metamask.currentBlockGasLimit, computedBalances: state.metamask.computedBalances, + unapprovedMsgCount, + unapprovedPersonalMsgCount, + unapprovedTypedMessagesCount, + send: state.metamask.send, selectedAddressTxList: state.metamask.selectedAddressTxList, } } @@ -49,11 +57,35 @@ function ConfirmTxScreen () { Component.call(this) } +ConfirmTxScreen.prototype.getUnapprovedMessagesTotal = function () { + const { + unapprovedMsgCount = 0, + unapprovedPersonalMsgCount = 0, + unapprovedTypedMessagesCount = 0, + } = this.props + + return unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount +} + +ConfirmTxScreen.prototype.componentDidMount = function () { + const { + unapprovedTxs = {}, + network, + send, + } = this.props + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + + if (unconfTxList.length === 0 && !send.to && this.getUnapprovedMessagesTotal() === 0) { + this.props.history.push(DEFAULT_ROUTE) + } +} + ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) { const { - unapprovedTxs, + unapprovedTxs = {}, network, selectedAddressTxList, + send, } = this.props const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) @@ -61,8 +93,9 @@ ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) { const prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {} const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) - if (prevTx.status === 'dropped' && unconfTxList.length === 0) { - this.goHome({}) + if (unconfTxList.length === 0 && + (prevTx.status === 'dropped' || !send.to && this.getUnapprovedMessagesTotal() === 0)) { + this.props.history.push(DEFAULT_ROUTE) } } @@ -103,7 +136,6 @@ ConfirmTxScreen.prototype.render = function () { */ log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`) - if (unconfTxList.length === 0) return h(Loading) return currentTxView({ // Properties @@ -152,6 +184,7 @@ function currentTxView (opts) { // return h(PendingTypedMsg, opts) // } } + return h(Loading) } @@ -163,6 +196,7 @@ ConfirmTxScreen.prototype.buyEth = function (address, event) { ConfirmTxScreen.prototype.sendTransaction = function (txData, event) { this.stopPropagation(event) this.props.dispatch(actions.updateAndApproveTx(txData)) + .then(() => this.props.history.push(DEFAULT_ROUTE)) } ConfirmTxScreen.prototype.cancelTransaction = function (txData, event) { @@ -182,7 +216,7 @@ ConfirmTxScreen.prototype.signMessage = function (msgData, event) { var params = msgData.msgParams params.metamaskId = msgData.id this.stopPropagation(event) - this.props.dispatch(actions.signMsg(params)) + return this.props.dispatch(actions.signMsg(params)) } ConfirmTxScreen.prototype.stopPropagation = function (event) { @@ -196,7 +230,7 @@ ConfirmTxScreen.prototype.signPersonalMessage = function (msgData, event) { var params = msgData.msgParams params.metamaskId = msgData.id this.stopPropagation(event) - this.props.dispatch(actions.signPersonalMsg(params)) + return this.props.dispatch(actions.signPersonalMsg(params)) } ConfirmTxScreen.prototype.signTypedMessage = function (msgData, event) { @@ -204,25 +238,25 @@ ConfirmTxScreen.prototype.signTypedMessage = function (msgData, event) { var params = msgData.msgParams params.metamaskId = msgData.id this.stopPropagation(event) - this.props.dispatch(actions.signTypedMsg(params)) + return this.props.dispatch(actions.signTypedMsg(params)) } ConfirmTxScreen.prototype.cancelMessage = function (msgData, event) { log.info('canceling message') this.stopPropagation(event) - this.props.dispatch(actions.cancelMsg(msgData)) + return this.props.dispatch(actions.cancelMsg(msgData)) } ConfirmTxScreen.prototype.cancelPersonalMessage = function (msgData, event) { log.info('canceling personal message') this.stopPropagation(event) - this.props.dispatch(actions.cancelPersonalMsg(msgData)) + return this.props.dispatch(actions.cancelPersonalMsg(msgData)) } ConfirmTxScreen.prototype.cancelTypedMessage = function (msgData, event) { log.info('canceling typed message') this.stopPropagation(event) - this.props.dispatch(actions.cancelTypedMsg(msgData)) + return this.props.dispatch(actions.cancelTypedMsg(msgData)) } ConfirmTxScreen.prototype.goHome = function (event) { diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss index 445c819ff..c068028f8 100644 --- a/ui/app/css/index.scss +++ b/ui/app/css/index.scss @@ -6,9 +6,15 @@ */ @import './itcss/settings/index.scss'; + @import './itcss/tools/index.scss'; + @import './itcss/generic/index.scss'; + @import './itcss/base/index.scss'; + @import './itcss/objects/index.scss'; + @import './itcss/components/index.scss'; + @import './itcss/trumps/index.scss'; diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss index f5c1de67c..2fdda6f43 100644 --- a/ui/app/css/itcss/components/add-token.scss +++ b/ui/app/css/itcss/components/add-token.scss @@ -8,6 +8,7 @@ font-family: 'Roboto'; background: white; border-radius: 8px; + box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08); &__wrapper { background-color: $white; @@ -20,7 +21,7 @@ &__header { display: flex; flex-flow: column nowrap; - padding: 16px 16px 0px; + padding: 20px 20px 0px; border-bottom: 1px solid $geyser; flex: 0 0 auto; @@ -31,7 +32,8 @@ span { font-family: Roboto; - font-size: 16px; + font-size: 16px; + font-weight: 400; line-height: 21px; margin-left: 8px; } @@ -44,8 +46,13 @@ margin-top: 4px; } + &__subtitle { + font-weight: 400; + margin-top: 15px; + margin-bottom: 21px; + } + &__tabs { - margin-left: 22px; display: flex; &__tab { @@ -54,6 +61,7 @@ color: $dusty-gray; font-family: Roboto; font-size: 18px; + font-weight: 400; line-height: 24px; text-align: center; } @@ -65,6 +73,7 @@ &__unselected:hover { color: $black; border-bottom: none; + cursor: pointer; } &__selected { @@ -76,7 +85,7 @@ &__info-box { height: 96px; - margin: 20px 24px 0px; + margin: 20px 20px 0px; border-radius: 4px; background-color: $alabaster; position: relative; @@ -98,6 +107,7 @@ color: $mid-gray; font-family: Roboto; font-size: 14px; + font-weight: 400; margin-top: 15px; margin-bottom: 9px; } @@ -107,6 +117,7 @@ color: $mid-gray; font-family: Roboto; font-size: 12px; + font-weight: 400; line-height: 18px; } @@ -124,7 +135,8 @@ } &__confirmation-description { - margin: 12px 0; + font-weight: 400; + margin: 20px 0 40px 0; } &__content-container { @@ -151,7 +163,7 @@ &__input, &__add-custom-input { height: 54px; - padding: 21px 6px; + padding: 0px 20px; border: 1px solid $geyser; border-radius: 4px; margin: 22px 24px; @@ -232,6 +244,7 @@ &__add-custom-label { font-size: 16px; + font-weight: 400; line-height: 21px; margin-left: 22px; color: $scorpion; @@ -274,9 +287,11 @@ color: #5B5D67; font-family: Roboto; font-size: 18px; + font-weight: 400; line-height: 24px; margin-left: 24px; margin-top: 8px; + margin-bottom: 20px; } &__token-icons-container { @@ -317,6 +332,7 @@ } &__token-name { + font-weight: 400; font-size: 14px; line-height: 19px; } @@ -368,6 +384,7 @@ &__symbol { color: $scorpion; font-size: 16px; + font-weight: 400; line-height: 24px; } } diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index ffd43ecbf..959eb9d15 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -52,6 +52,8 @@ @import './editable-label.scss'; +@import './pages/index.scss'; + @import './new-account.scss'; @import './tooltip.scss'; diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss index aa7fed956..293579058 100644 --- a/ui/app/css/itcss/components/new-account.scss +++ b/ui/app/css/itcss/components/new-account.scss @@ -35,13 +35,14 @@ font-size: 18px; line-height: 24px; text-align: center; + cursor: pointer; } &__tab:first-of-type { margin-right: 20px; } - &__unselected:hover { + &__tab:hover { color: $black; border-bottom: none; } @@ -49,9 +50,9 @@ &__selected { color: $curious-blue; border-bottom: 3px solid $curious-blue; + cursor: initial; } } - } .new-account-import-disclaimer { diff --git a/ui/app/css/itcss/components/pages/index.scss b/ui/app/css/itcss/components/pages/index.scss new file mode 100644 index 000000000..82446fd7a --- /dev/null +++ b/ui/app/css/itcss/components/pages/index.scss @@ -0,0 +1 @@ +@import './unlock.scss'; diff --git a/ui/app/css/itcss/components/pages/unlock.scss b/ui/app/css/itcss/components/pages/unlock.scss new file mode 100644 index 000000000..5d438377b --- /dev/null +++ b/ui/app/css/itcss/components/pages/unlock.scss @@ -0,0 +1,9 @@ +.unlock-page { + box-shadow: none; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: rgb(247, 247, 247); + width: 100%; +} diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss index 388aea175..ace46bd8a 100644 --- a/ui/app/css/itcss/components/sections.scss +++ b/ui/app/css/itcss/components/sections.scss @@ -17,6 +17,12 @@ textarea.twelve-word-phrase { resize: none; } +.initialize-screen { + width: 100%; + z-index: $main-container-z-index; + background: #f7f7f7; +} + .initialize-screen hr { width: 60px; margin: 12px; diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index 4ab5f06c0..692b01c8c 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -1,6 +1,5 @@ -const inherits = require('util').inherits -const EventEmitter = require('events').EventEmitter -const Component = require('react').Component +const { EventEmitter } = require('events') +const { Component } = require('react') const PropTypes = require('prop-types') const connect = require('react-redux').connect const h = require('react-hyperscript') @@ -8,205 +7,219 @@ const Mascot = require('../components/mascot') const actions = require('../actions') const Tooltip = require('../components/tooltip') const getCaretCoordinates = require('textarea-caret') +const { RESTORE_VAULT_ROUTE, DEFAULT_ROUTE } = require('../routes') const environmentType = require('../../../app/scripts/lib/environment-type') const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums -let isSubmitting = false +class InitializeMenuScreen extends Component { + constructor (props) { + super(props) -InitializeMenuScreen.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps)(InitializeMenuScreen) - - -inherits(InitializeMenuScreen, Component) -function InitializeMenuScreen () { - Component.call(this) - this.animationEventEmitter = new EventEmitter() -} - -function mapStateToProps (state) { - return { - // state from plugin - currentView: state.appState.currentView, - warning: state.appState.warning, + this.animationEventEmitter = new EventEmitter() + this.state = { + warning: null, + } } -} - -InitializeMenuScreen.prototype.render = function () { - var state = this.props - - switch (state.currentView.name) { - - default: - return this.renderMenu(state) + componentWillMount () { + const { isInitialized, isUnlocked, history } = this.props + if (isInitialized || isUnlocked) { + history.push(DEFAULT_ROUTE) + } } -} -// InitializeMenuScreen.prototype.componentDidMount = function(){ -// document.getElementById('password-box').focus() -// } - -InitializeMenuScreen.prototype.renderMenu = function (state) { - return ( - - h('.initialize-screen.flex-column.flex-center.flex-grow', [ + componentDidMount () { + document.getElementById('password-box').focus() + } - h(Mascot, { - animationEventEmitter: this.animationEventEmitter, - }), + render () { + const { warning } = this.state - h('h1', { - style: { - fontSize: '1.3em', - textTransform: 'uppercase', - color: '#7F8082', - marginBottom: 10, - }, - }, this.context.t('appName')), + return ( + h('.initialize-screen.flex-column.flex-center', [ + h(Mascot, { + animationEventEmitter: this.animationEventEmitter, + }), - h('div', [ - h('h3', { + h('h1', { style: { - fontSize: '0.8em', + fontSize: '1.3em', + textTransform: 'uppercase', color: '#7F8082', - display: 'inline', + marginBottom: 10, }, - }, this.context.t('encryptNewDen')), + }, this.context.t('appName')), - h(Tooltip, { - title: this.context.t('denExplainer'), - }, [ - h('i.fa.fa-question-circle.pointer', { + h('div', [ + h('h3', { style: { - fontSize: '18px', - position: 'relative', - color: 'rgb(247, 134, 28)', - top: '2px', - marginLeft: '4px', + fontSize: '0.8em', + color: '#7F8082', + display: 'inline', }, - }), + }, this.context.t('encryptNewDen')), + + h(Tooltip, { + title: this.context.t('denExplainer'), + }, [ + h('i.fa.fa-question-circle.pointer', { + style: { + fontSize: '18px', + position: 'relative', + color: 'rgb(247, 134, 28)', + top: '2px', + marginLeft: '4px', + }, + }), + ]), ]), - ]), - - h('span.in-progress-notification', state.warning), - - // password - h('input.large-input.letter-spacey', { - type: 'password', - id: 'password-box', - placeholder: this.context.t('newPassword'), - onInput: this.inputChanged.bind(this), - style: { - width: 260, - marginTop: 12, - }, - }), - - // confirm password - h('input.large-input.letter-spacey', { - type: 'password', - id: 'password-box-confirm', - placeholder: this.context.t('confirmPassword'), - onKeyPress: this.createVaultOnEnter.bind(this), - onInput: this.inputChanged.bind(this), - style: { - width: 260, - marginTop: 16, - }, - }), - - - h('button.primary', { - onClick: this.createNewVaultAndKeychain.bind(this), - style: { - margin: 12, - }, - }, this.context.t('createDen')), - - h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: this.showRestoreVault.bind(this), + + h('span.error.in-progress-notification', warning), + + // password + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box', + placeholder: this.context.t('newPassword'), + onInput: this.inputChanged.bind(this), + style: { + width: 260, + marginTop: 12, + }, + }), + + // confirm password + h('input.large-input.letter-spacey', { + type: 'password', + id: 'password-box-confirm', + placeholder: this.context.t('confirmPassword'), + onKeyPress: this.createVaultOnEnter.bind(this), + onInput: this.inputChanged.bind(this), style: { - fontSize: '0.8em', - color: 'rgb(247, 134, 28)', - textDecoration: 'underline', + width: 260, + marginTop: 16, }, - }, this.context.t('importDen')), - ]), + }), + - h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: this.showOldUI.bind(this), + h('button.primary', { + onClick: this.createNewVaultAndKeychain.bind(this), style: { - fontSize: '0.8em', - color: '#aeaeae', - textDecoration: 'underline', - marginTop: '32px', + margin: 12, }, - }, 'Use classic interface'), - ]), + }, this.context.t('createDen')), - ]) - ) -} + h('.flex-row.flex-center.flex-grow', [ + h('p.pointer', { + onClick: () => this.showRestoreVault(), + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, this.context.t('importDen')), + ]), -InitializeMenuScreen.prototype.createVaultOnEnter = function (event) { - if (event.key === 'Enter') { - event.preventDefault() - this.createNewVaultAndKeychain() + h('.flex-row.flex-center.flex-grow', [ + h('p.pointer', { + onClick: this.showOldUI.bind(this), + style: { + fontSize: '0.8em', + color: '#aeaeae', + textDecoration: 'underline', + marginTop: '32px', + }, + }, 'Use classic interface'), + ]), + + ]) + ) } -} -InitializeMenuScreen.prototype.componentDidMount = function () { - document.getElementById('password-box').focus() -} + createVaultOnEnter (event) { + if (event.key === 'Enter') { + event.preventDefault() + this.createNewVaultAndKeychain() + } + } -InitializeMenuScreen.prototype.showRestoreVault = function () { - this.props.dispatch(actions.markPasswordForgotten()) - if (environmentType() === 'popup') { - global.platform.openExtensionInBrowser() + createNewVaultAndKeychain () { + const { history } = this.props + var passwordBox = document.getElementById('password-box') + var password = passwordBox.value + var passwordConfirmBox = document.getElementById('password-box-confirm') + var passwordConfirm = passwordConfirmBox.value + + this.setState({ warning: null }) + + if (password.length < 8) { + this.setState({ warning: this.context.t('passwordShort') }) + return + } + + if (password !== passwordConfirm) { + this.setState({ warning: this.context.t('passwordMismatch') }) + return + } + + this.props.createNewVaultAndKeychain(password) + .then(() => history.push(DEFAULT_ROUTE)) } -} -InitializeMenuScreen.prototype.showOldUI = function () { - this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) - .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) -} + inputChanged (event) { + // tell mascot to look at page action + var element = event.target + var boundingRect = element.getBoundingClientRect() + var coordinates = getCaretCoordinates(element, element.selectionEnd) + this.animationEventEmitter.emit('point', { + x: boundingRect.left + coordinates.left - element.scrollLeft, + y: boundingRect.top + coordinates.top - element.scrollTop, + }) + } -InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () { - var passwordBox = document.getElementById('password-box') - var password = passwordBox.value - var passwordConfirmBox = document.getElementById('password-box-confirm') - var passwordConfirm = passwordConfirmBox.value + showRestoreVault () { + this.props.markPasswordForgotten() + if (environmentType() === 'popup') { + global.platform.openExtensionInBrowser() + } - if (password.length < 8) { - this.warning = this.context.t('passwordShort') - this.props.dispatch(actions.displayWarning(this.warning)) - return + this.props.history.push(RESTORE_VAULT_ROUTE) } - if (password !== passwordConfirm) { - this.warning = this.context.t('passwordMismatch') - this.props.dispatch(actions.displayWarning(this.warning)) - return + + showOldUI () { + this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) + .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) } +} + +InitializeMenuScreen.propTypes = { + history: PropTypes.object, + isInitialized: PropTypes.bool, + isUnlocked: PropTypes.bool, + createNewVaultAndKeychain: PropTypes.func, + markPasswordForgotten: PropTypes.func, + dispatch: PropTypes.func, +} - if (!isSubmitting) { - isSubmitting = true - this.props.dispatch(actions.createNewVaultAndKeychain(password)) +InitializeMenuScreen.contextTypes = { + t: PropTypes.func, +} + +const mapStateToProps = state => { + const { metamask: { isInitialized, isUnlocked } } = state + + return { + isInitialized, + isUnlocked, } } -InitializeMenuScreen.prototype.inputChanged = function (event) { - // tell mascot to look at page action - var element = event.target - var boundingRect = element.getBoundingClientRect() - var coordinates = getCaretCoordinates(element, element.selectionEnd) - this.animationEventEmitter.emit('point', { - x: boundingRect.left + coordinates.left - element.scrollLeft, - y: boundingRect.top + coordinates.top - element.scrollTop, - }) +const mapDispatchToProps = dispatch => { + return { + createNewVaultAndKeychain: password => dispatch(actions.createNewVaultAndKeychain(password)), + markPasswordForgotten: () => dispatch(actions.markPasswordForgotten()), + } } + +module.exports = connect(mapStateToProps, mapDispatchToProps)(InitializeMenuScreen) diff --git a/ui/app/i18n-provider.js b/ui/app/i18n-provider.js index fe6d62c67..4ef618018 100644 --- a/ui/app/i18n-provider.js +++ b/ui/app/i18n-provider.js @@ -1,6 +1,8 @@ const { Component } = require('react') const connect = require('react-redux').connect const PropTypes = require('prop-types') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const t = require('../i18n-helper').getMessage class I18nProvider extends Component { @@ -32,5 +34,8 @@ const mapStateToProps = state => { } } -module.exports = connect(mapStateToProps)(I18nProvider) +module.exports = compose( + withRouter, + connect(mapStateToProps) +)(I18nProvider) diff --git a/ui/app/keychains/hd/recover-seed/confirmation.js b/ui/app/keychains/hd/recover-seed/confirmation.js index 02183f096..eb588415f 100644 --- a/ui/app/keychains/hd/recover-seed/confirmation.js +++ b/ui/app/keychains/hd/recover-seed/confirmation.js @@ -4,12 +4,21 @@ const PropTypes = require('prop-types') const connect = require('react-redux').connect const h = require('react-hyperscript') const actions = require('../../../actions') +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') +const { + DEFAULT_ROUTE, + INITIALIZE_BACKUP_PHRASE_ROUTE, +} = require('../../../routes') RevealSeedConfirmation.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps)(RevealSeedConfirmation) +module.exports = compose( + withRouter, + connect(mapStateToProps) +)(RevealSeedConfirmation) inherits(RevealSeedConfirmation, Component) @@ -109,6 +118,8 @@ RevealSeedConfirmation.prototype.componentDidMount = function () { RevealSeedConfirmation.prototype.goHome = function () { this.props.dispatch(actions.showConfigPage(false)) + this.props.dispatch(actions.confirmSeedWords()) + .then(() => this.props.history.push(DEFAULT_ROUTE)) } // create vault @@ -123,4 +134,5 @@ RevealSeedConfirmation.prototype.checkConfirmation = function (event) { RevealSeedConfirmation.prototype.revealSeedWords = function () { var password = document.getElementById('password-box').value this.props.dispatch(actions.requestRevealSeed(password)) + .then(() => this.props.history.push(INITIALIZE_BACKUP_PHRASE_ROUTE)) } diff --git a/ui/app/main-container.js b/ui/app/main-container.js index eed4bd164..6dd4ff151 100644 --- a/ui/app/main-container.js +++ b/ui/app/main-container.js @@ -2,8 +2,8 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const AccountAndTransactionDetails = require('./account-and-transaction-details') -const Settings = require('./settings') -const UnlockScreen = require('./unlock') +const Settings = require('./components/pages/settings') +const UnlockScreen = require('./components/pages/unlock') module.exports = MainContainer diff --git a/ui/app/root.js b/ui/app/root.js index 21d6d1829..09deae1b1 100644 --- a/ui/app/root.js +++ b/ui/app/root.js @@ -1,22 +1,23 @@ -const inherits = require('util').inherits -const Component = require('react').Component -const Provider = require('react-redux').Provider +const { Component } = require('react') +const PropTypes = require('prop-types') +const { Provider } = require('react-redux') const h = require('react-hyperscript') const SelectedApp = require('./select-app') -module.exports = Root - -inherits(Root, Component) -function Root () { Component.call(this) } - -Root.prototype.render = function () { - return ( +class Root extends Component { + render () { + const { store } = this.props - h(Provider, { - store: this.props.store, - }, [ - h(SelectedApp), - ]) + return ( + h(Provider, { store }, [ + h(SelectedApp), + ]) + ) + } +} - ) +Root.propTypes = { + store: PropTypes.object, } + +module.exports = Root diff --git a/ui/app/routes.js b/ui/app/routes.js new file mode 100644 index 000000000..4b3f8f4d8 --- /dev/null +++ b/ui/app/routes.js @@ -0,0 +1,49 @@ +const DEFAULT_ROUTE = '/' +const UNLOCK_ROUTE = '/unlock' +const SETTINGS_ROUTE = '/settings' +const INFO_ROUTE = '/settings/info' +const REVEAL_SEED_ROUTE = '/seed' +const CONFIRM_SEED_ROUTE = '/confirm-seed' +const RESTORE_VAULT_ROUTE = '/restore-vault' +const ADD_TOKEN_ROUTE = '/add-token' +const NEW_ACCOUNT_ROUTE = '/new-account' +const IMPORT_ACCOUNT_ROUTE = '/new-account/import' +const SEND_ROUTE = '/send' +const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction' +const SIGNATURE_REQUEST_ROUTE = '/confirm-transaction/signature-request' +const NOTICE_ROUTE = '/notice' +const WELCOME_ROUTE = '/welcome' +const INITIALIZE_ROUTE = '/initialize' +const INITIALIZE_CREATE_PASSWORD_ROUTE = '/initialize/create-password' +const INITIALIZE_IMPORT_ACCOUNT_ROUTE = '/initialize/import-account' +const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = '/initialize/import-with-seed-phrase' +const INITIALIZE_UNIQUE_IMAGE_ROUTE = '/initialize/unique-image' +const INITIALIZE_NOTICE_ROUTE = '/initialize/notice' +const INITIALIZE_BACKUP_PHRASE_ROUTE = '/initialize/backup-phrase' +const INITIALIZE_CONFIRM_SEED_ROUTE = '/initialize/confirm-phrase' + +module.exports = { + DEFAULT_ROUTE, + UNLOCK_ROUTE, + SETTINGS_ROUTE, + INFO_ROUTE, + REVEAL_SEED_ROUTE, + CONFIRM_SEED_ROUTE, + RESTORE_VAULT_ROUTE, + ADD_TOKEN_ROUTE, + NEW_ACCOUNT_ROUTE, + IMPORT_ACCOUNT_ROUTE, + SEND_ROUTE, + CONFIRM_TRANSACTION_ROUTE, + NOTICE_ROUTE, + SIGNATURE_REQUEST_ROUTE, + WELCOME_ROUTE, + INITIALIZE_ROUTE, + INITIALIZE_CREATE_PASSWORD_ROUTE, + INITIALIZE_IMPORT_ACCOUNT_ROUTE, + INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, + INITIALIZE_UNIQUE_IMAGE_ROUTE, + INITIALIZE_NOTICE_ROUTE, + INITIALIZE_BACKUP_PHRASE_ROUTE, + INITIALIZE_CONFIRM_SEED_ROUTE, +} diff --git a/ui/app/select-app.js b/ui/app/select-app.js index 101eb1cf6..d1565e2fb 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -2,6 +2,7 @@ const inherits = require('util').inherits const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') +const { HashRouter } = require('react-router-dom') const App = require('./app') const OldApp = require('../../old-ui/app/app') const { autoAddToBetaUI } = require('./selectors') @@ -63,7 +64,12 @@ SelectedApp.prototype.render = function () { // const Selected = betaUI || isMascara || firstTime ? App : OldApp const { betaUI, isMascara } = this.props - const Selected = betaUI || isMascara ? h(I18nProvider, [ h(App) ]) : h(OldApp) - return Selected + return betaUI || isMascara + ? h(HashRouter, { + hashType: 'noslash', + }, [ + h(I18nProvider, [ h(App) ]), + ]) + : h(OldApp) } diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 0f2997fb2..d0c28caa2 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -30,6 +30,7 @@ const { getGasTotal, } = require('./components/send/send-utils') const { isValidAddress } = require('./util') +const { CONFIRM_TRANSACTION_ROUTE, DEFAULT_ROUTE } = require('./routes') SendTransactionScreen.contextTypes = { t: PropTypes.func, @@ -182,7 +183,7 @@ SendTransactionScreen.prototype.componentDidUpdate = function (prevProps) { } SendTransactionScreen.prototype.renderHeader = function () { - const { selectedToken, clearSend, goHome } = this.props + const { selectedToken, clearSend, history } = this.props return h('div.page-container__header', [ @@ -193,7 +194,7 @@ SendTransactionScreen.prototype.renderHeader = function () { h('div.page-container__header-close', { onClick: () => { clearSend() - goHome() + history.push(DEFAULT_ROUTE) }, }), @@ -254,7 +255,6 @@ SendTransactionScreen.prototype.handleToChange = function (to, nickname = '') { const { updateSendTo, updateSendErrors, - from: {address: from}, } = this.props let toError = null @@ -262,8 +262,6 @@ SendTransactionScreen.prototype.handleToChange = function (to, nickname = '') { toError = this.context.t('required') } else if (!isValidAddress(to)) { toError = this.context.t('invalidAddressRecipient') - } else if (to === from) { - toError = this.context.t('fromToSame') } updateSendTo(to, nickname) @@ -498,12 +496,12 @@ SendTransactionScreen.prototype.renderForm = function () { SendTransactionScreen.prototype.renderFooter = function () { const { - goHome, clearSend, gasTotal, tokenBalance, selectedToken, errors: { amount: amountError, to: toError }, + history, } = this.props const missingTokenBalance = selectedToken && !tokenBalance @@ -513,7 +511,7 @@ SendTransactionScreen.prototype.renderFooter = function () { h('button.btn-secondary--lg.page-container__footer-button', { onClick: () => { clearSend() - goHome() + history.push(DEFAULT_ROUTE) }, }, this.context.t('cancel')), h('button.btn-primary--lg.page-container__footer-button', { @@ -579,12 +577,17 @@ SendTransactionScreen.prototype.getEditedTx = function () { data, }) } else { - const data = unapprovedTxs[editingTransactionId].txParams.data + const { data } = unapprovedTxs[editingTransactionId].txParams + Object.assign(editingTx.txParams, { value: ethUtil.addHexPrefix(amount), to: ethUtil.addHexPrefix(to), data, }) + + if (typeof editingTx.txParams.data === 'undefined') { + delete editingTx.txParams.data + } } return editingTx @@ -619,7 +622,6 @@ SendTransactionScreen.prototype.onSubmit = function (event) { if (editingTransactionId) { const editedTx = this.getEditedTx() - updateTx(editedTx) } else { @@ -643,4 +645,6 @@ SendTransactionScreen.prototype.onSubmit = function (event) { ? signTokenTx(selectedToken.address, to, amount, txParams) : signTx(txParams) } + + this.props.history.push(CONFIRM_TRANSACTION_ROUTE) } diff --git a/ui/app/util.js b/ui/app/util.js index 800ccb218..bbe2bb09e 100644 --- a/ui/app/util.js +++ b/ui/app/util.js @@ -271,6 +271,7 @@ function exportAsFile (filename, data) { window.navigator.msSaveBlob(blob, filename) } else { const elem = window.document.createElement('a') + elem.target = '_blank' elem.href = window.URL.createObjectURL(blob) elem.download = filename document.body.appendChild(elem) diff --git a/ui/app/welcome-screen.js b/ui/app/welcome-screen.js index cdbb6dba8..2fa244d9f 100644 --- a/ui/app/welcome-screen.js +++ b/ui/app/welcome-screen.js @@ -3,21 +3,35 @@ import h from 'react-hyperscript' import { Component } from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' import {closeWelcomeScreen} from './actions' import Mascot from './components/mascot' +import { INITIALIZE_CREATE_PASSWORD_ROUTE } from './routes' class WelcomeScreen extends Component { static propTypes = { closeWelcomeScreen: PropTypes.func.isRequired, + welcomeScreenSeen: PropTypes.bool, + history: PropTypes.object, } - constructor(props) { + constructor (props) { super(props) this.animationEventEmitter = new EventEmitter() } + componentWillMount () { + const { history, welcomeScreenSeen } = this.props + + if (welcomeScreenSeen) { + history.push(INITIALIZE_CREATE_PASSWORD_ROUTE) + } + } + initiateAccountCreation = () => { this.props.closeWelcomeScreen() + this.props.history.push(INITIALIZE_CREATE_PASSWORD_ROUTE) } render () { @@ -48,9 +62,18 @@ class WelcomeScreen extends Component { } } -export default connect( - null, - dispatch => ({ - closeWelcomeScreen: () => dispatch(closeWelcomeScreen()), - }) +const mapStateToProps = ({ metamask: { welcomeScreenSeen } }) => { + return { + welcomeScreenSeen, + } +} + +export default compose( + withRouter, + connect( + mapStateToProps, + dispatch => ({ + closeWelcomeScreen: () => dispatch(closeWelcomeScreen()), + }) + ) )(WelcomeScreen) diff --git a/ui/i18n-helper.js b/ui/i18n-helper.js index db2fd2dc4..3eee55ae9 100644 --- a/ui/i18n-helper.js +++ b/ui/i18n-helper.js @@ -25,18 +25,15 @@ const getMessage = (locale, key, substitutions) => { return phrase } -function fetchLocale (localeName) { - return new Promise((resolve, reject) => { - return fetch(`./_locales/${localeName}/messages.json`) - .then(response => response.json()) - .then( - locale => resolve(locale), - error => { - log.error(`failed to fetch ${localeName} locale because of ${error}`) - resolve({}) - } - ) - }) +async function fetchLocale (localeName) { + try { + const response = await fetch(`./_locales/${localeName}/messages.json`) + const locale = await response.json() + return locale + } catch (error) { + log.error(`failed to fetch ${localeName} locale because of ${error}`) + return {} + } } module.exports = { @@ -2,54 +2,77 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0-beta.31": - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz#473d021ecc573a2cce1c07d5b509d5215f46ba35" +"@babel/code-frame@7.0.0-beta.44", "@babel/code-frame@^7.0.0-beta.40": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" + "@babel/highlight" "7.0.0-beta.44" + +"@babel/generator@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" + dependencies: + "@babel/types" "7.0.0-beta.44" + jsesc "^2.5.1" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@babel/helper-function-name@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.44" + "@babel/template" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" -"@babel/helper-function-name@7.0.0-beta.31": - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz#afe63ad799209989348b1109b44feb66aa245f57" +"@babel/helper-get-function-arity@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.31" - "@babel/template" "7.0.0-beta.31" - "@babel/traverse" "7.0.0-beta.31" - "@babel/types" "7.0.0-beta.31" + "@babel/types" "7.0.0-beta.44" -"@babel/helper-get-function-arity@7.0.0-beta.31": - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz#1176d79252741218e0aec872ada07efb2b37a493" +"@babel/helper-split-export-declaration@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" dependencies: - "@babel/types" "7.0.0-beta.31" + "@babel/types" "7.0.0-beta.44" -"@babel/template@7.0.0-beta.31": - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.31.tgz#577bb29389f6c497c3e7d014617e7d6713f68bda" +"@babel/highlight@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" dependencies: - "@babel/code-frame" "7.0.0-beta.31" - "@babel/types" "7.0.0-beta.31" - babylon "7.0.0-beta.31" - lodash "^4.2.0" + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" -"@babel/traverse@7.0.0-beta.31": - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.31.tgz#db399499ad74aefda014f0c10321ab255134b1df" +"@babel/template@7.0.0-beta.44": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" dependencies: - "@babel/code-frame" "7.0.0-beta.31" - "@babel/helper-function-name" "7.0.0-beta.31" - "@babel/types" "7.0.0-beta.31" - babylon "7.0.0-beta.31" - debug "^3.0.1" - globals "^10.0.0" + "@babel/code-frame" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + lodash "^4.2.0" + +"@babel/traverse@^7.0.0-beta.40": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" + dependencies: + "@babel/code-frame" "7.0.0-beta.44" + "@babel/generator" "7.0.0-beta.44" + "@babel/helper-function-name" "7.0.0-beta.44" + "@babel/helper-split-export-declaration" "7.0.0-beta.44" + "@babel/types" "7.0.0-beta.44" + babylon "7.0.0-beta.44" + debug "^3.1.0" + globals "^11.1.0" invariant "^2.2.0" lodash "^4.2.0" -"@babel/types@7.0.0-beta.31": - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.31.tgz#42c9c86784f674c173fb21882ca9643334029de4" +"@babel/types@7.0.0-beta.44", "@babel/types@^7.0.0-beta.40": + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" dependencies: esutils "^2.0.2" lodash "^4.2.0" @@ -85,9 +108,15 @@ version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + "@types/node@*": - version "8.5.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.5.2.tgz#83b8103fa9a2c2e83d78f701a9aa7c9539739aa5" + version "9.6.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.2.tgz#e49ac1adb458835e95ca6487bc20f916b37aff23" JSONStream@^0.8.4: version "0.8.4" @@ -112,17 +141,18 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" abi-decoder@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.0.9.tgz#6bcfd86f7f63fbec8573d9778b3a4f92bb92e01f" + version "1.1.0" + resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.1.0.tgz#07f063e2a8f0ca1750fe4cd0dd112f6103ce3455" dependencies: babel-core "^6.23.1" babel-loader "^6.3.2" babel-plugin-add-module-exports "^0.2.1" babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-runtime "^6.23.0" babel-preset-es2015 "^6.22.0" chai "^3.5.0" web3 "^0.18.4" - webpack "^2.2.1" + webpack "^2.7.0" abstract-leveldown@~2.6.0: version "2.6.3" @@ -136,18 +166,11 @@ abstract-leveldown@~2.7.1: dependencies: xtend "~4.0.0" -accepts@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" - dependencies: - mime-types "~2.1.11" - negotiator "0.6.1" - -accepts@~1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" +accepts@~1.3.4, accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" dependencies: - mime-types "~2.1.16" + mime-types "~2.1.18" negotiator "0.6.1" accounting@^0.4.1: @@ -172,16 +195,16 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn-node@^1.3.0: +acorn-node@^1.2.0, acorn-node@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.3.0.tgz#5f86d73346743810ef1269b901dbcbded020861b" dependencies: acorn "^5.4.1" xtend "^4.0.1" -acorn@5.X, acorn@^5.0.0, acorn@^5.0.3, acorn@^5.2.1: - version "5.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" +acorn@5.X, acorn@^5.0.0, acorn@^5.0.3, acorn@^5.2.1, acorn@^5.3.0, acorn@^5.4.1, acorn@^5.5.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" acorn@^3.0.4: version "3.3.0" @@ -191,10 +214,6 @@ acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" -acorn@^5.3.0, acorn@^5.4.1: - version "5.5.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" - addressparser@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" @@ -203,10 +222,6 @@ aes-js@^0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d" -after@0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.1.tgz#ab5d4fb883f596816d3515f8f791c0af486dd627" - after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" @@ -232,6 +247,10 @@ ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" +ajv-keywords@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be" + ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" @@ -248,6 +267,15 @@ ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" +ajv@^6.0.1: + version "6.4.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.4.0.tgz#d3aff78e9277549771daf0164cff48482b754fc6" + dependencies: + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + uri-js "^3.0.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -271,18 +299,24 @@ amqplib@^0.5.2: safe-buffer "^5.0.1" ansi-colors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.0.1.tgz#e94c6c306005af8b482240241e2f3dea4b855ff3" + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" dependencies: ansi-wrap "^0.1.0" +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + dependencies: + ansi-wrap "0.1.0" + ansi-escapes@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" ansi-escapes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" ansi-gray@^0.1.1: version "0.1.1" @@ -290,6 +324,12 @@ ansi-gray@^0.1.1: dependencies: ansi-wrap "0.1.0" +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + dependencies: + ansi-wrap "0.1.0" + ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" @@ -310,12 +350,6 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" - dependencies: - color-convert "^1.9.0" - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -388,11 +422,18 @@ are-we-there-yet@~1.1.2: readable-stream "^2.0.6" argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -419,6 +460,10 @@ arr-map@^2.0.0, arr-map@^2.0.2: dependencies: make-iterator "^1.0.0" +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" @@ -509,10 +554,6 @@ array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" -arraybuffer.slice@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" - arraybuffer.slice@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" @@ -530,8 +571,8 @@ asmcrypto.js@0.22.0: resolved "https://registry.yarnpkg.com/asmcrypto.js/-/asmcrypto.js-0.22.0.tgz#38fc1440884d802c7bd37d1d23c2b26a5cd5d2d2" asn1.js@^4.0.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -556,8 +597,8 @@ assert@^1.1.1, assert@^1.4.0: util "0.10.3" assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" assign-symbols@^1.0.0: version "1.0.0" @@ -567,7 +608,7 @@ ast-types@0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" -ast-types@0.11.3: +ast-types@0.11.3, ast-types@0.x.x: version "0.11.3" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.3.tgz#c20757fe72ee71278ea0ff3d87e5c2ca30d9edf8" @@ -575,10 +616,6 @@ ast-types@0.9.6: version "0.9.6" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" -ast-types@0.x.x: - version "0.11.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.2.tgz#cc4e1d15a36b39979a1986fe1e91321cbfae7783" - astw@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/astw/-/astw-2.2.0.tgz#7bd41784d32493987aeb239b6b4e1c57a873b917" @@ -586,8 +623,8 @@ astw@^2.0.0: acorn "^4.0.3" async-done@^1.2.0, async-done@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.2.3.tgz#6c7abc7d61ca27fe6f1f2ba3206ea9ae60a43983" + version "1.2.4" + resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.2.4.tgz#17b0fcefb9a33cb9de63daa8904c0a65bd535fa0" dependencies: end-of-stream "^1.1.0" once "^1.3.2" @@ -604,7 +641,7 @@ async-eventemitter@^0.2.2: dependencies: async "^2.4.0" -async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: +"async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c": version "0.2.3" resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" dependencies: @@ -702,8 +739,8 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" atob@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" + version "2.1.0" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.0.tgz#ab2b150e51d7b122b9efc8d7340c06b6c41076bc" atob@~1.1.0: version "1.1.3" @@ -721,14 +758,14 @@ autoprefixer@^6.0.0: postcss-value-parser "^3.2.3" autoprefixer@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.1.0.tgz#374cf35be1c0e8fce97408d876f95f66f5cb4641" + version "8.2.0" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-8.2.0.tgz#1e49b611b31a5259b86b7a6b2b1b8faf091abe2a" dependencies: - browserslist "^3.1.1" - caniuse-lite "^1.0.30000810" + browserslist "^3.2.0" + caniuse-lite "^1.0.30000817" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^6.0.19" + postcss "^6.0.20" postcss-value-parser "^3.2.3" await-semaphore@^0.1.1: @@ -744,8 +781,8 @@ aws-sign2@~0.7.0: resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" aws4@^1.2.1, aws4@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" axios@^0.15.3: version "0.15.3" @@ -786,19 +823,19 @@ babel-core@^6.0.14, babel-core@^6.23.1, babel-core@^6.24.1, babel-core@^6.26.0: source-map "^0.5.6" babel-eslint@^8.0.0: - version "8.1.2" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.1.2.tgz#a39230b0c20ecbaa19a35d5633bf9b9ca2c8116f" + version "8.2.2" + resolved "http://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz#1102273354c6f0b29b4ea28a65f97d122296b68b" dependencies: - "@babel/code-frame" "7.0.0-beta.31" - "@babel/traverse" "7.0.0-beta.31" - "@babel/types" "7.0.0-beta.31" - babylon "7.0.0-beta.31" + "@babel/code-frame" "^7.0.0-beta.40" + "@babel/traverse" "^7.0.0-beta.40" + "@babel/types" "^7.0.0-beta.40" + babylon "^7.0.0-beta.40" eslint-scope "~3.7.1" eslint-visitor-keys "^1.0.0" babel-generator@^6.18.0, babel-generator@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -806,7 +843,7 @@ babel-generator@^6.18.0, babel-generator@^6.26.0: detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.17.4" - source-map "^0.5.6" + source-map "^0.5.7" trim-right "^1.0.1" babel-helper-bindify-decorators@^6.24.1: @@ -1360,7 +1397,7 @@ babel-preset-env@^1.3.2: invariant "^2.2.2" semver "^5.3.0" -babel-preset-es2015@^6.22.0, babel-preset-es2015@^6.24.0, babel-preset-es2015@^6.6.0, babel-preset-es2015@^6.9.0: +babel-preset-es2015@^6.22.0, babel-preset-es2015@^6.6.0, babel-preset-es2015@^6.9.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" dependencies: @@ -1504,18 +1541,14 @@ babelify@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-8.0.0.tgz#6f60f5f062bfe7695754ef2403b842014a580ed3" -babylon@7.0.0-beta.31: - version "7.0.0-beta.31" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.31.tgz#7ec10f81e0e456fd0f855ad60fa30c2ac454283f" +babylon@7.0.0-beta.44, babylon@^7.0.0-beta.30, babylon@^7.0.0-beta.40: + version "7.0.0-beta.44" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" babylon@^6.17.3, babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" -babylon@^7.0.0-beta.30: - version "7.0.0-beta.44" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" - bach@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" @@ -1565,12 +1598,8 @@ base64-arraybuffer@0.1.5: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" base64-js@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" - -base64id@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-0.1.0.tgz#02ce0fdeee0cef4f40080e1e73e834f0b1bfce3f" + version "1.2.3" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801" base64id@1.0.0: version "1.0.0" @@ -1660,8 +1689,8 @@ bindings@^1.2.1: resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" bip39@^2.2.0, bip39@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.4.0.tgz#a0b8adbf163f53495f00f05d9ede7c25369ccf13" + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" dependencies: create-hash "^1.1.0" pbkdf2 "^3.0.9" @@ -1682,10 +1711,11 @@ bitsyntax@~0.0.4: buffer-more-ints "0.0.2" bl@^1.2.0, bl@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" dependencies: - readable-stream "^2.0.5" + readable-stream "^2.3.5" + safe-buffer "^5.1.1" bl@~1.1.2: version "1.1.2" @@ -1711,7 +1741,7 @@ bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.3, bn.js@^4.11.7, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -1773,20 +1803,13 @@ boron@^0.2.3: dependencies: domkit "^0.0.1" -brace-expansion@^1.0.0: +brace-expansion@^1.0.0, brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - braces@^0.1.2: version "0.1.5" resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" @@ -1801,13 +1824,12 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -braces@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e" +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" - define-property "^1.0.0" extend-shallow "^2.0.1" fill-range "^4.0.0" isobject "^3.0.1" @@ -1817,30 +1839,13 @@ braces@^2.3.0: split-string "^3.0.2" to-regex "^3.0.1" -braces@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - kind-of "^6.0.2" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - brfs@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.4.3.tgz#db675d6f5e923e6df087fca5859c9090aaed3216" + version "1.5.0" + resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.5.0.tgz#a3822ed7a65723e056f89ff4b58e8abc63658f03" dependencies: quote-stream "^1.0.1" resolve "^1.1.5" - static-module "^1.1.0" + static-module "^2.2.0" through2 "^2.0.0" brorand@^1.0.1: @@ -1858,12 +1863,13 @@ browser-pack@^5.0.1: umd "^3.0.0" browser-pack@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.2.tgz#f86cd6cef4f5300c8e63e07a4d512f65fbff4531" + version "6.1.0" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" dependencies: JSONStream "^1.0.3" - combine-source-map "~0.7.1" + combine-source-map "~0.8.0" defined "^1.0.0" + safe-buffer "^5.1.1" through2 "^2.0.0" umd "^3.0.0" @@ -1883,9 +1889,9 @@ browser-resolve@^1.11.0, browser-resolve@^1.7.0: dependencies: resolve "1.1.7" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" browser-unpack@^1.2.0: version "1.2.0" @@ -1897,8 +1903,8 @@ browser-unpack@^1.2.0: minimist "^1.1.1" browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: - version "1.1.1" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1965,7 +1971,7 @@ browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: dependencies: pako "~1.0.5" -browserify@^14.0.0, browserify@^14.5.0: +browserify@^14.5.0: version "14.5.0" resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.5.0.tgz#0bbbce521acd6e4d1d54d8e9365008efb85a9cc5" dependencies: @@ -2017,7 +2023,7 @@ browserify@^14.0.0, browserify@^14.5.0: vm-browserify "~0.0.1" xtend "^4.0.0" -browserify@^16.1.1: +browserify@^16.1.0, browserify@^16.1.1: version "16.1.1" resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.1.1.tgz#7905ec07e0147c4d90f92001944050a6e1c2844e" dependencies: @@ -2078,18 +2084,18 @@ browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.7.6: electron-to-chromium "^1.2.7" browserslist@^2.1.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.10.0.tgz#bac5ee1cc69ca9d96403ffb8a3abdc5b6aed6346" + version "2.11.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" dependencies: - caniuse-lite "^1.0.30000780" - electron-to-chromium "^1.3.28" + caniuse-lite "^1.0.30000792" + electron-to-chromium "^1.3.30" -browserslist@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.1.2.tgz#893f29399d640ed35fe06bacd7eb1d78609a47e5" +browserslist@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.4.tgz#fb9ad70fd09875137ae943a31ab815ed76896031" dependencies: - caniuse-lite "^1.0.30000813" - electron-to-chromium "^1.3.36" + caniuse-lite "^1.0.30000821" + electron-to-chromium "^1.3.41" bs58@^2.0.1: version "2.0.1" @@ -2120,6 +2126,10 @@ buffer-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + buffer-more-ints@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz#26b3885d10fa13db7fc01aae3aab870199e0124c" @@ -2137,8 +2147,8 @@ buffer@^4.3.0: isarray "^1.0.0" buffer@^5.0.2: - version "5.0.8" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" + version "5.1.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.1.0.tgz#c913e43678c7cb7c8bd16afbcddb6c5505e8f9fe" dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -2255,16 +2265,12 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000784" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000784.tgz#1be95012d9489c7719074f81aee57dbdffe6361b" + version "1.0.30000824" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000824.tgz#bba3ff425296e04caa37fe426259206a7056551b" -caniuse-lite@^1.0.30000780: - version "1.0.30000784" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000784.tgz#129ced74e9a1280a441880b6cd2bce30ef59e6c0" - -caniuse-lite@^1.0.30000810, caniuse-lite@^1.0.30000813: - version "1.0.30000814" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000814.tgz#73eb6925ac2e54d495218f1ea0007da3940e488b" +caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000817, caniuse-lite@^1.0.30000821: + version "1.0.30000824" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000824.tgz#de3bc1ba0bff4937302f8cb2a8632a8cc1c07f9a" caseless@~0.11.0: version "0.11.0" @@ -2281,7 +2287,7 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -"chai@>=1.9.2 <4.0.0", chai@^3.5.0: +chai@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" dependencies: @@ -2289,7 +2295,7 @@ center-align@^0.1.1: deep-eql "^0.1.3" type-detect "^1.0.0" -chai@^4.1.0: +chai@^4.1.0, chai@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" dependencies: @@ -2324,15 +2330,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -chalk@^2.3.1, chalk@^2.3.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" dependencies: @@ -2410,7 +2408,7 @@ chokidar@1.6.1: optionalDependencies: fsevents "^1.0.0" -chokidar@^1.0.0, chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.7.0: +chokidar@^1.0.0, chokidar@^1.4.1: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -2425,9 +2423,9 @@ chokidar@^1.0.0, chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.7.0: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.2.tgz#4dc65139eeb2714977735b6a35d06e97b494dfd7" +chokidar@^2.0.0, chokidar@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176" dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -2441,7 +2439,7 @@ chokidar@^2.0.0: readdirp "^2.0.0" upath "^1.0.0" optionalDependencies: - fsevents "^1.0.0" + fsevents "^1.1.2" chromedriver@^2.34.1: version "2.37.0" @@ -2469,13 +2467,12 @@ circular-json@^0.5.1: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.1.tgz#b8942a09e535863dc21b04417a91971e1d9cd91f" class-utils@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.5.tgz#17e793103750f9627b2176ea34cfd1b565903c80" + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" dependencies: arr-union "^3.1.0" define-property "^0.2.5" isobject "^3.0.0" - lazy-cache "^2.0.2" static-extend "^0.1.1" classnames@^2.2.4, classnames@^2.2.5: @@ -2551,8 +2548,8 @@ clone-buffer@^1.0.0: resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" clone-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c" + version "1.0.1" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f" dependencies: is-regexp "^1.0.0" is-supported-regexp-flag "^1.0.0" @@ -2572,20 +2569,20 @@ clone-stats@^1.0.0: resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" clone@^1.0.0, clone@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" clone@^2.0.0, clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" cloneable-readable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117" + version "1.1.2" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" dependencies: inherits "^2.0.1" - process-nextick-args "^1.0.6" - through2 "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" co@^4.6.0: version "4.6.0" @@ -2681,8 +2678,8 @@ colors@1.0.3, colors@1.0.x: resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" colors@^1.1.0, colors@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + version "1.2.1" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.1.tgz#f4a3d302976aaf042356ba1ade3b1a2c62d9d794" combine-lists@^1.0.0: version "1.0.1" @@ -2690,6 +2687,15 @@ combine-lists@^1.0.0: dependencies: lodash "^4.5.0" +combine-source-map@^0.8.0, combine-source-map@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + combine-source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.6.1.tgz#9b4a09c316033d768e0f11e029fa2730e079ad96" @@ -2699,18 +2705,9 @@ combine-source-map@~0.6.1: lodash.memoize "~3.0.3" source-map "~0.4.2" -combine-source-map@~0.7.1: - version "0.7.2" - resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e" - dependencies: - convert-source-map "~1.1.0" - inline-source-map "~0.6.0" - lodash.memoize "~3.0.3" - source-map "~0.5.3" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" @@ -2724,13 +2721,9 @@ commander@2.9.0: dependencies: graceful-readlink ">= 1.0.0" -commander@^2.5.0, commander@^2.6.0, commander@^2.9.0, commander@~2.12.1: - version "2.12.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" - -commander@~2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" +commander@^2.5.0, commander@^2.6.0, commander@^2.9.0, commander@~2.15.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" commander@~2.14.1: version "2.14.1" @@ -2762,10 +2755,6 @@ component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" -component-emitter@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" - component-emitter@1.2.1, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -2774,19 +2763,19 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" -compressible@~2.0.11: - version "2.0.12" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" +compressible@~2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" dependencies: - mime-db ">= 1.30.0 < 2" + mime-db ">= 1.33.0 < 2" compression@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" + version "1.7.2" + resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" dependencies: accepts "~1.3.4" bytes "3.0.0" - compressible "~2.0.11" + compressible "~2.0.13" debug "2.6.9" on-headers "~1.0.1" safe-buffer "5.1.1" @@ -2796,7 +2785,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@1.6.0, concat-stream@^1.4.3, concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@~1.6.0: +concat-stream@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: @@ -2804,6 +2793,15 @@ concat-stream@1.6.0, concat-stream@^1.4.3, concat-stream@^1.4.6, concat-stream@^ readable-stream "^2.2.2" typedarray "^0.0.6" +concat-stream@^1.4.3, concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + concat-stream@~1.5.0, concat-stream@~1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" @@ -2820,11 +2818,11 @@ config-chain@~1.1.5: proto-list "~1.2.1" connect@^3.6.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.5.tgz#fb8dde7ba0763877d0ec9df9dac0b4b40e72c7da" + version "3.6.6" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" dependencies: debug "2.6.9" - finalhandler "1.0.6" + finalhandler "1.1.0" parseurl "~1.3.2" utils-merge "1.0.1" @@ -2852,15 +2850,11 @@ content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" -content-type-parser@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" - content-type@~1.0.1, content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" -convert-source-map@1.X, convert-source-map@^1.3.0, convert-source-map@^1.5.0: +convert-source-map@1.X, convert-source-map@^1.5.0, convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -2897,11 +2891,7 @@ core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" -core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" - -core-js@^2.4.1: +core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: version "2.5.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.5.tgz#b14dde936c640c0579a6b50cabcc132dd6127e3b" @@ -2963,8 +2953,8 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: sha.js "^2.4.8" create-react-class@^15.6.0: - version "15.6.2" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" + version "15.6.3" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" dependencies: fbjs "^0.8.9" loose-envify "^1.3.1" @@ -2999,7 +2989,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.5: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: @@ -3155,6 +3145,14 @@ data-uri-to-buffer@1: version "1.2.0" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz#77163ea9c20d8641b4707e8f18abdf9a78f34835" +data-urls@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.0.tgz#24802de4e81c298ea8a9388bb0d8e461c774684f" + dependencies: + abab "^1.0.4" + whatwg-mimetype "^2.0.0" + whatwg-url "^6.4.0" + date-fns@^1.27.2: version "1.29.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" @@ -3188,8 +3186,8 @@ debounce@^1.0.0: resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.1.0.tgz#6a1a4ee2a9dc4b7c24bb012558dbcdb05b37f408" debug-fabulous@1.X: - version "1.0.0" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.0.0.tgz#57f6648646097b1b0849dcda0017362c1ec00f8b" + version "1.1.0" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-1.1.0.tgz#af8a08632465224ef4174a9f06308c3c2a1ebc8e" dependencies: debug "3.X" memoizee "0.4.X" @@ -3205,24 +3203,18 @@ debug@2, debug@2.6.9, debug@^2.1.0, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, de dependencies: ms "2.0.0" -debug@2.2.0, debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -debug@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" - dependencies: - ms "0.7.2" - -debug@3.1.0, debug@3.X, debug@^3.0.1, debug@^3.1.0, debug@~3.1.0: +debug@3.1.0, debug@3.X, debug@^3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" +debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3277,9 +3269,9 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -deepmerge@~0.2.7: - version "0.2.10" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-0.2.10.tgz#8906bf9e525a4fbf1b203b2afcb4640249821219" +deepmerge@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.0.tgz#511a54fff405fc346f0240bb270a3e9533a31102" default-compare@^1.0.0: version "1.0.0" @@ -3372,10 +3364,14 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@1.1.1, depd@~1.1.0, depd@~1.1.1: +depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" +depd@~1.1.0, depd@~1.1.1, depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + deps-sort@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" @@ -3420,20 +3416,16 @@ detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" -detect-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-2.0.0.tgz#720ff51e4d97b76884f6bf57292348b13dfde939" - dependencies: - get-stdin "^3.0.0" - minimist "^1.1.0" - repeating "^1.1.0" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" dependencies: repeating "^2.0.0" +detect-indent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -3465,15 +3457,7 @@ di@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - -diff@^3.1.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" - -diff@^3.3.1, diff@^3.5.0: +diff@3.5.0, diff@^3.1.0, diff@^3.3.1, diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -3524,9 +3508,9 @@ dnode@^1.2.2: optionalDependencies: weak "^1.0.0" -doctrine@^2.0.0, doctrine@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.2.tgz#68f96ce8efc56cc42651f1faadb4f175273b0075" +doctrine@^2.0.2, doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" @@ -3571,14 +3555,14 @@ dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" -domain-browser@^1.1.1, domain-browser@~1.1.0: - version "1.1.7" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" - -domain-browser@^1.2.0: +domain-browser@^1.1.1, domain-browser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" +domain-browser@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" + domelementtype@1, domelementtype@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" @@ -3588,8 +3572,10 @@ domelementtype@~1.1.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.0.tgz#81fe5df81b3f057052cde3a9fa9bf536a85b9ab0" + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + dependencies: + webidl-conversions "^4.0.2" domhandler@2.3: version "2.3.0" @@ -3615,8 +3601,8 @@ domutils@1.5, domutils@1.5.1: domelementtype "1" domutils@^1.5.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff" + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" dependencies: dom-serializer "0" domelementtype "1" @@ -3639,7 +3625,7 @@ duplexer2@0.0.2, duplexer2@~0.0.2: dependencies: readable-stream "~1.1.9" -duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" dependencies: @@ -3653,9 +3639,9 @@ duplexer@^0.1.1, duplexer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" -duplexify@^3.1.2, duplexify@^3.4.2: - version "3.5.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd" +duplexify@^3.4.2, duplexify@^3.5.3: + version "3.5.4" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" @@ -3697,19 +3683,9 @@ ejs@^2.3.1: version "2.5.8" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.8.tgz#2ab6954619f225e6193b7ac5f7c39c48fefe4380" -electron-releases@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e" - -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.28: - version "1.3.30" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz#9666f532a64586651fc56a72513692e820d06a80" - dependencies: - electron-releases "^2.1.0" - -electron-to-chromium@^1.3.36: - version "1.3.37" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.37.tgz#4a92734e0044c8cf0b1553be57eae21a4c6e5fab" +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.41: + version "1.3.42" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz#95c33bf01d0cc405556aec899fe61fd4d76ea0f9" elegant-spinner@^1.0.1: version "1.0.1" @@ -3731,9 +3707,9 @@ emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" -encodeurl@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" +encodeurl@~1.0.1, encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" encoding@^0.1.11: version "0.1.12" @@ -3742,31 +3718,30 @@ encoding@^0.1.11: iconv-lite "~0.4.13" end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" dependencies: once "^1.4.0" -engine.io-client@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.0.tgz#7b730e4127414087596d9be3c88d2bc5fdb6cf5c" +engine.io-client@~3.1.0: + version "3.1.6" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.6.tgz#5bdeb130f8b94a50ac5cbeb72583e7a4a063ddfd" dependencies: component-emitter "1.2.1" component-inherit "0.0.3" - debug "2.3.3" - engine.io-parser "1.3.1" + debug "~3.1.0" + engine.io-parser "~2.1.1" has-cors "1.1.0" indexof "0.0.1" - parsejson "0.0.3" parseqs "0.0.5" parseuri "0.0.5" - ws "1.1.1" - xmlhttprequest-ssl "1.5.3" + ws "~3.3.1" + xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" -engine.io-client@~3.1.0: - version "3.1.5" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.1.5.tgz#85de17666560327ef1817978f6e3f8101ded2c47" +engine.io-client@~3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" dependencies: component-emitter "1.2.1" component-inherit "0.0.3" @@ -3780,17 +3755,6 @@ engine.io-client@~3.1.0: xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" -engine.io-parser@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.1.tgz#9554f1ae33107d6fbd170ca5466d2f833f6a07cf" - dependencies: - after "0.8.1" - arraybuffer.slice "0.0.6" - base64-arraybuffer "0.1.5" - blob "0.0.4" - has-binary "0.1.6" - wtf-8 "1.0.0" - engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.2.tgz#4c0f4cff79aaeecbbdcfdea66a823c6085409196" @@ -3801,17 +3765,6 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: blob "0.0.4" has-binary2 "~1.0.2" -engine.io@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.0.tgz#3eeb5f264cb75dbbec1baaea26d61f5a4eace2aa" - dependencies: - accepts "1.3.3" - base64id "0.1.0" - cookie "0.3.1" - debug "2.3.3" - engine.io-parser "1.3.1" - ws "1.1.1" - engine.io@~3.1.0: version "3.1.5" resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.1.5.tgz#0e7ef9d690eb0b35597f1d4ad02a26ca2dba3845" @@ -3825,6 +3778,17 @@ engine.io@~3.1.0: optionalDependencies: uws "~9.14.0" +engine.io@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.0.tgz#54332506f42f2edc71690d2f2a42349359f3bf7d" + dependencies: + accepts "~1.3.4" + base64id "1.0.0" + cookie "0.3.1" + debug "~3.1.0" + engine.io-parser "~2.1.0" + ws "~3.3.1" + enhanced-resolve@^3.3.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" @@ -3915,8 +3879,8 @@ enzyme@^3.3.0: rst-selector-parser "^2.2.3" errno@^0.1.3, errno@~0.1.1: - version "0.1.6" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" dependencies: prr "~1.0.1" @@ -3934,8 +3898,8 @@ error@^7.0.2: xtend "~4.0.0" es-abstract@^1.5.0, es-abstract@^1.6.1, es-abstract@^1.7.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" + version "1.11.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.11.0.tgz#cce87d518f0496893b1a30cd8461835535480681" dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -3952,13 +3916,14 @@ es-to-primitive@^1.1.1: is-symbol "^1.0.1" es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: - version "0.10.37" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.37.tgz#0ee741d148b80069ba27d020393756af257defc3" + version "0.10.42" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.42.tgz#8c07dd33af04d5dcd1310b5cef13bea63a89ba8d" dependencies: - es6-iterator "~2.0.1" + es6-iterator "~2.0.3" es6-symbol "~3.1.1" + next-tick "1" -es6-iterator@^2.0.1, es6-iterator@~2.0.1: +es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" dependencies: @@ -4025,7 +3990,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1 version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -escodegen@1.x.x: +escodegen@1.x.x, escodegen@^1.8.1, escodegen@^1.9.0, escodegen@~1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" dependencies: @@ -4036,36 +4001,6 @@ escodegen@1.x.x: optionalDependencies: source-map "~0.6.1" -escodegen@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852" - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.5.6" - -escodegen@~0.0.24: - version "0.0.28" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-0.0.28.tgz#0e4ff1715f328775d6cab51ac44a406cd7abffd3" - dependencies: - esprima "~1.0.2" - estraverse "~1.3.0" - optionalDependencies: - source-map ">= 0.1.2" - -escodegen@~1.3.2: - version "1.3.3" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.3.3.tgz#f024016f5a88e046fd12005055e939802e6c5f23" - dependencies: - esprima "~1.1.1" - estraverse "~1.5.0" - esutils "~1.0.0" - optionalDependencies: - source-map "~0.1.33" - escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" @@ -4092,12 +4027,12 @@ eslint-plugin-mocha@^5.0.0: ramda "^0.25.0" eslint-plugin-react@^7.4.0: - version "7.5.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz#52e56e8d80c810de158859ef07b880d2f56ee30b" + version "7.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz#f606c719dbd8a1a2b3d25c16299813878cca0160" dependencies: - doctrine "^2.0.0" + doctrine "^2.0.2" has "^1.0.1" - jsx-ast-utils "^2.0.0" + jsx-ast-utils "^2.0.1" prop-types "^15.6.0" eslint-scope@^3.7.1, eslint-scope@~3.7.1: @@ -4112,8 +4047,8 @@ eslint-visitor-keys@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" eslint@^4.0.0, eslint@^4.2.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.14.0.tgz#96609768d1dd23304faba2d94b7fefe5a5447a82" + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -4121,10 +4056,10 @@ eslint@^4.0.0, eslint@^4.2.0: concat-stream "^1.6.0" cross-spawn "^5.1.0" debug "^3.1.0" - doctrine "^2.0.2" + doctrine "^2.1.0" eslint-scope "^3.7.1" eslint-visitor-keys "^1.0.0" - espree "^3.5.2" + espree "^3.5.4" esquery "^1.0.0" esutils "^2.0.2" file-entry-cache "^2.0.0" @@ -4146,18 +4081,19 @@ eslint@^4.0.0, eslint@^4.2.0: path-is-inside "^1.0.2" pluralize "^7.0.0" progress "^2.0.0" + regexpp "^1.0.1" require-uncached "^1.0.3" semver "^5.3.0" strip-ansi "^4.0.0" strip-json-comments "~2.0.1" - table "^4.0.1" + table "4.0.2" text-table "~0.2.0" -espree@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: - acorn "^5.2.1" + acorn "^5.5.0" acorn-jsx "^3.0.0" esprima-fb@13001.1001.0-dev-harmony-fb: @@ -4172,47 +4108,26 @@ esprima@^4.0.0, esprima@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" -esprima@~1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" - -esprima@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.1.1.tgz#5b6f1547f4d102e670e140c509be6771d6aeb549" - esquery@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" dependencies: estraverse "^4.1.0" - object-assign "^4.0.1" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" -estraverse@~1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.3.2.tgz#37c2b893ef13d723f276d878d60d8535152a6c42" - -estraverse@~1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" - esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" -esutils@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" - etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -4235,18 +4150,7 @@ eth-block-tracker@^1.0.7: pify "^2.3.0" tape "^4.6.3" -eth-block-tracker@^2.1.2, eth-block-tracker@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.2.2.tgz#b3d72cd82ba5ee37471d22bac4f56387ee4137cf" - dependencies: - async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c - babelify "^7.3.0" - eth-query "^2.1.0" - ethjs-util "^0.1.3" - pify "^2.3.0" - tape "^4.6.3" - -eth-block-tracker@^2.3.0: +eth-block-tracker@^2.1.2, eth-block-tracker@^2.2.2, eth-block-tracker@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.0.tgz#4cb782c8ef8fde2f5dc894921ae1f5c1077c35a4" dependencies: @@ -4260,8 +4164,8 @@ eth-block-tracker@^2.3.0: tape "^4.6.3" eth-contract-metadata@^1.1.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.3.0.tgz#caf3cdc3d69995b6d7532c9d96fedbad46361ca8" + version "1.7.0" + resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.7.0.tgz#8d094043bf97019a2355b1e4d864ab33c9efe792" eth-ens-namehash@^1.0.2: version "1.0.2" @@ -4270,17 +4174,7 @@ eth-ens-namehash@^1.0.2: idna-uts46 "^1.0.1" js-sha3 "^0.5.7" -eth-hd-keyring@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-1.2.1.tgz#15ab3919b4153a8497e14673e8e8039e5965131c" - dependencies: - bip39 "^2.2.0" - eth-sig-util "^1.3.0" - ethereumjs-util "^5.1.1" - ethereumjs-wallet "^0.6.0" - events "^1.1.1" - -eth-hd-keyring@^1.2.2: +eth-hd-keyring@^1.2.1, eth-hd-keyring@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-1.2.2.tgz#ad5f479074436a93b439b0b95c79095c28791882" dependencies: @@ -4310,8 +4204,8 @@ eth-json-rpc-infura@^3.0.0: tape "^4.8.0" eth-json-rpc-middleware@^1.0.0, eth-json-rpc-middleware@^1.2.7, eth-json-rpc-middleware@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.5.0.tgz#16b1053386aa3803b125732aa6de07eadf068729" + version "1.5.2" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.5.2.tgz#14cb0af1e9910c24dd063beabbbb7142d39d9bb9" dependencies: async "^2.5.0" eth-query "^2.1.2" @@ -4321,6 +4215,7 @@ eth-json-rpc-middleware@^1.0.0, eth-json-rpc-middleware@^1.2.7, eth-json-rpc-mid ethereumjs-util "^5.1.2" ethereumjs-vm "^2.1.0" fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" json-rpc-error "^2.0.0" json-stable-stringify "^1.0.1" promise-to-callback "^1.0.0" @@ -4342,8 +4237,8 @@ eth-keyring-controller@^2.1.4: promise-filter "^1.1.0" eth-phishing-detect@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/eth-phishing-detect/-/eth-phishing-detect-1.1.12.tgz#3db7e88c754510c94e6736db85108b90e227fe41" + version "1.1.13" + resolved "https://registry.yarnpkg.com/eth-phishing-detect/-/eth-phishing-detect-1.1.13.tgz#ed718b933c8a69fef0cefa6604538824b472dbea" dependencies: fast-levenshtein "^2.0.6" @@ -4354,14 +4249,7 @@ eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: json-rpc-random-id "^1.0.0" xtend "^4.0.1" -eth-sig-util@^1.3.0, eth-sig-util@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.1.tgz#dfcde3cbd03c38d429ad8695938a2678ec56f1ae" - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-sig-util@^1.4.2: +eth-sig-util@^1.4.0, eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" dependencies: @@ -4390,10 +4278,11 @@ eth-token-tracker@^1.1.4: human-standard-token-abi "^1.0.2" eth-tx-summary@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.1.2.tgz#e38836fc9f8b56f14d75952f0f5e570f88fb2220" + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.1.tgz#0c2d5e4c57d2511614f85b9b583c32fa2924166c" dependencies: async "^2.1.2" + bn.js "^4.11.8" clone "^2.0.0" concat-stream "^1.5.1" end-of-stream "^1.1.0" @@ -4401,7 +4290,7 @@ eth-tx-summary@^3.1.2: ethereumjs-block "^1.4.1" ethereumjs-tx "^1.1.1" ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.0.2" + ethereumjs-vm "^2.3.4" through2 "^2.0.3" treeify "^1.0.1" web3-provider-engine "^13.3.2" @@ -4418,13 +4307,20 @@ ethereum-ens-network-map@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.0.tgz#43cd7669ce950a789e151001118d4d65f210eeb7" -ethereumjs-abi@^0.6.4, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": +ethereumjs-abi@^0.6.4: version "0.6.5" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#71f123b676f2b2d81bc20f343670d90045a3d3d8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" dependencies: bn.js "^4.10.0" ethereumjs-util "^4.3.0" +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.5" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf" + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^5.0.0" + ethereumjs-account@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.4.tgz#f8c30231bcb707f4514d8a052c1f9da103624d47" @@ -4433,8 +4329,8 @@ ethereumjs-account@^2.0.3: rlp "^2.0.0" ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0, ethereumjs-block@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.0.tgz#23d6a765b069500a9f35d1c093ab6b216cbbeb06" + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" dependencies: async "^2.0.1" ethereum-common "0.2.0" @@ -4443,13 +4339,13 @@ ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0, ether merkle-patricia-tree "^2.1.2" ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.0, ethereumjs-tx@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.3.tgz#ece051d3efdbe771ad2a518d61632ca2ab75ecbb" + version "1.3.4" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.4.tgz#c2304912f6c07af03237ad8675ac036e290dad48" dependencies: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" -ethereumjs-util@4.5.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: +ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" dependencies: @@ -4459,24 +4355,11 @@ ethereumjs-util@4.5.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumj rlp "^2.0.0" secp256k1 "^3.0.1" -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.2.tgz#25ba0215cbb4c2f0b108a6f96af2a2e62e45921f" +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz#2f02575852627d45622426f25ee4a0b5f377f27a" dependencies: - babel-preset-es2015 "^6.24.0" - babelify "^7.3.0" - bn.js "^4.8.0" - create-hash "^1.1.2" - ethjs-util "^0.1.3" - keccak "^1.0.2" - rlp "^2.0.0" - secp256k1 "^3.0.1" - -ethereumjs-util@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.3.tgz#0c1f6efb1da9c5b6720a65697859fc0be6672df0" - dependencies: - bn.js "^4.8.0" + bn.js "^4.11.0" create-hash "^1.1.2" ethjs-util "^0.1.3" keccak "^1.0.2" @@ -4494,16 +4377,16 @@ ethereumjs-util@^5.1.3: rlp "^2.0.0" secp256k1 "^3.0.1" -ethereumjs-vm@^2.0.0, ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.3.2.tgz#4f939e22b89e9b298f0c87a7e0f0d8949f485abd" +ethereumjs-vm@^2.0.0, ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz#f635d7cb047571a1840a6e9a74d29de4488f8ad6" dependencies: async "^2.1.2" async-eventemitter "^0.2.2" ethereum-common "0.2.0" ethereumjs-account "^2.0.3" ethereumjs-block "~1.7.0" - ethereumjs-util "4.5.0" + ethereumjs-util "^5.1.3" fake-merkle-patricia-tree "^1.0.1" functional-red-black-tree "^1.0.1" merkle-patricia-tree "^2.1.2" @@ -4685,7 +4568,7 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: event-stream@^3.1.7, event-stream@~3.3.0: version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" dependencies: duplexer "~0.1.1" from "~0" @@ -4718,11 +4601,11 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" +execa@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" dependencies: - cross-spawn "^5.0.1" + cross-spawn "^6.0.0" get-stream "^3.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" @@ -4730,9 +4613,9 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -4812,10 +4695,10 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: homedir-polyfill "^1.0.1" express@^4.10.7, express@^4.15.5: - version "4.16.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" + version "4.16.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" dependencies: - accepts "~1.3.4" + accepts "~1.3.5" array-flatten "1.1.1" body-parser "1.18.2" content-disposition "0.5.2" @@ -4823,29 +4706,35 @@ express@^4.10.7, express@^4.15.5: cookie "0.3.1" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.1" - encodeurl "~1.0.1" + depd "~1.1.2" + encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.1.0" + finalhandler "1.1.1" fresh "0.5.2" merge-descriptors "1.0.1" methods "~1.1.2" on-finished "~2.3.0" parseurl "~1.3.2" path-to-regexp "0.1.7" - proxy-addr "~2.0.2" + proxy-addr "~2.0.3" qs "6.5.1" range-parser "~1.2.0" safe-buffer "5.1.1" - send "0.16.1" - serve-static "1.13.1" + send "0.16.2" + serve-static "1.13.2" setprototypeof "1.1.0" - statuses "~1.3.1" - type-is "~1.6.15" + statuses "~1.4.0" + type-is "~1.6.16" utils-merge "1.0.1" vary "~1.1.2" +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + dependencies: + kind-of "^1.1.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4874,18 +4763,10 @@ extension-link-enabler@^1.0.0: extensionizer "^1.0.0" extensionizer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.0.tgz#01c209bbea6d9c0acba77129c3aa4a9a98fc3538" - -external-editor@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" + version "1.0.1" + resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.1.tgz#504544239a7610ba8404b15c1832091a37768d09" -external-editor@^2.1.0: +external-editor@^2.0.4, external-editor@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" dependencies: @@ -4899,19 +4780,6 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extglob@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.3.tgz#55e019d0c95bf873949c737b7e5172dba84ebb29" - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -4970,8 +4838,8 @@ fancy-log@^1.1.0, fancy-log@^1.3.2: time-stamp "^1.0.0" fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" fast-json-patch@^2.0.4: version "2.0.6" @@ -5072,9 +4940,9 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -finalhandler@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.6.tgz#007aea33d1a4d3e42017f624848ad58d212f814f" +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" dependencies: debug "2.6.9" encodeurl "~1.0.1" @@ -5084,16 +4952,16 @@ finalhandler@1.0.6: statuses "~1.3.1" unpipe "~1.0.0" -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" dependencies: debug "2.6.9" - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" on-finished "~2.3.0" parseurl "~1.3.2" - statuses "~1.3.1" + statuses "~1.4.0" unpipe "~1.0.0" find-cache-dir@^0.1.1: @@ -5200,9 +5068,9 @@ flow-parser@^0.*: version "0.69.0" resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.69.0.tgz#378b5128d6d0b554a8b2f16a4ca3e1ab9649f00e" -flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417" +flush-write-stream@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" dependencies: inherits "^2.0.1" readable-stream "^2.0.4" @@ -5267,14 +5135,14 @@ form-data@~2.1.1: mime-types "^2.1.12" form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: asynckit "^0.4.0" - combined-stream "^1.0.5" + combined-stream "1.0.6" mime-types "^2.1.12" -formatio@1.2.0, formatio@^1.2.0: +formatio@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" dependencies: @@ -5352,7 +5220,7 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -fsevents@^1.0.0: +fsevents@^1.0.0, fsevents@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" dependencies: @@ -5383,16 +5251,16 @@ ftp@~0.3.10: readable-stream "1.1.x" xregexp "2.0.0" -function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1, function-bind@~1.1.0: +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1, function-bind@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" function.prototype.name@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.0.3.tgz#0099ae5572e9dd6f03c97d023fd92bcc5e639eac" + version "1.1.0" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" dependencies: define-properties "^1.1.2" - function-bind "^1.1.0" + function-bind "^1.1.1" is-callable "^1.1.3" functional-red-black-tree@^1.0.1: @@ -5455,10 +5323,6 @@ get-own-enumerable-property-symbols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" -get-stdin@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-3.0.2.tgz#c1ced24b9039b38ded85bdf161e57713b6dd4abe" - get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -5570,12 +5434,12 @@ glob-stream@~3.1.9: through2 "^0.6.1" unique-stream "^1.0.0" -glob-watcher@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-4.0.0.tgz#9e63a8ff6e61e932de6cc2caece5071a6d737329" +glob-watcher@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.1.tgz#239aaa621b6bd843b288fdf6b155f50963c7d7ea" dependencies: async-done "^1.2.0" - chokidar "^1.4.3" + chokidar "^2.0.0" just-debounce "^1.0.0" object.defaults "^1.1.0" @@ -5666,13 +5530,9 @@ global@~4.3.0: min-document "^2.19.0" process "~0.5.1" -globals@^10.0.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-10.4.0.tgz#5c477388b128a9e4c5c5d01c7a2aca68c68b2da7" - -globals@^11.0.1: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.1.0.tgz#632644457f5f0e3ae711807183700ebf2e4633e4" +globals@^11.0.1, globals@^11.1.0: + version "11.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.4.0.tgz#b85c793349561c16076a3c13549238a27945f1bc" globals@^9.18.0: version "9.18.0" @@ -5712,8 +5572,8 @@ globule@^1.0.0: minimatch "~3.0.2" glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" + version "1.0.1" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" dependencies: sparkles "^1.0.0" @@ -5792,17 +5652,17 @@ gulp-autoprefixer@^5.0.0: vinyl-sourcemaps-apply "^0.2.0" gulp-babel@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-7.0.0.tgz#7b93c975159f7a0553e4263b4a55100ccc239b28" + version "7.0.1" + resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-7.0.1.tgz#b9c8e29fa376b36c57989db820fc1c1715bb47cb" dependencies: - gulp-util "^3.0.0" + plugin-error "^1.0.1" replace-ext "0.0.1" through2 "^2.0.0" vinyl-sourcemaps-apply "^0.2.0" gulp-cli@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.0.0.tgz#7f049ad298ed388cda9bd813b5d7062407d62cad" + version "2.0.1" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.0.1.tgz#7847e220cb3662f2be8a6d572bf14e17be5a994b" dependencies: ansi-colors "^1.0.1" archy "^1.0.0" @@ -5810,16 +5670,16 @@ gulp-cli@^2.0.0: color-support "^1.1.3" concat-stream "^1.6.0" copy-props "^2.0.1" - fancy-log "^1.1.0" + fancy-log "^1.3.2" gulplog "^1.0.0" - interpret "^1.0.0" + interpret "^1.1.0" isobject "^3.0.1" - liftoff "^2.3.0" + liftoff "^2.5.0" matchdep "^2.0.0" mute-stdout "^1.0.0" pretty-hrtime "^1.0.0" replace-homedir "^1.0.0" - semver-greatest-satisfied-range "^1.0.0" + semver-greatest-satisfied-range "^1.1.0" v8flags "^3.0.1" yargs "^7.1.0" @@ -5835,21 +5695,22 @@ gulp-debug@^3.2.0: tildify "^1.1.2" gulp-eslint@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-eslint/-/gulp-eslint-4.0.0.tgz#16d9ea4d696e7b7a9d65eeb1aa5bc4ba0a22c7f7" + version "4.0.2" + resolved "https://registry.yarnpkg.com/gulp-eslint/-/gulp-eslint-4.0.2.tgz#18a2a6768e4404cbf3e203239cb57474168fa606" dependencies: eslint "^4.0.0" - gulp-util "^3.0.8" + fancy-log "^1.3.2" + plugin-error "^1.0.0" gulp-json-editor@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/gulp-json-editor/-/gulp-json-editor-2.2.1.tgz#7c4dd7477e8d06dc5dc49c0b81e745cdb04f97bb" + version "2.3.0" + resolved "https://registry.yarnpkg.com/gulp-json-editor/-/gulp-json-editor-2.3.0.tgz#a9c8d7d4b23b2a810cf0ca4a93b5ad549608459d" dependencies: - deepmerge "~0.2.7" - detect-indent "^2.0.0" - gulp-util "~3.0.0" - js-beautify "~1.5.4" - through2 "~0.5.0" + deepmerge "^2.1.0" + detect-indent "^5.0.0" + js-beautify "^1.7.5" + plugin-error "^1.0.1" + through2 "^2.0.3" gulp-livereload@^3.8.1: version "3.8.1" @@ -5877,18 +5738,18 @@ gulp-replace@^0.6.1: replacestream "^4.0.0" gulp-sass@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-3.1.0.tgz#53dc4b68a1f5ddfe4424ab4c247655269a8b74b7" + version "3.2.1" + resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-3.2.1.tgz#2e3688a96fd8be1c0c01340750c191b2e79fab94" dependencies: gulp-util "^3.0" lodash.clonedeep "^4.3.2" - node-sass "^4.2.0" + node-sass "^4.8.3" through2 "^2.0.0" vinyl-sourcemaps-apply "^0.2.0" gulp-sourcemaps@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.2.tgz#4f41c72b35a7ea06b666d2e3f57917e2c0e71c4e" + version "2.6.4" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz#cbb2008450b1bcce6cd23bf98337be751bf6e30a" dependencies: "@gulp-sourcemaps/identity-map" "1.X" "@gulp-sourcemaps/map-sources" "1.X" @@ -5898,7 +5759,7 @@ gulp-sourcemaps@^2.6.0: debug-fabulous "1.X" detect-newline "2.X" graceful-fs "4.X" - source-map "0.X" + source-map "~0.6.0" strip-bom-string "1.X" through2 "2.X" @@ -5948,7 +5809,7 @@ gulp-uglify@^3.0.0: uglify-js "^3.0.5" vinyl-sourcemaps-apply "^0.2.0" -gulp-util@^3.0, gulp-util@^3.0.0, gulp-util@^3.0.2, gulp-util@^3.0.7, gulp-util@^3.0.8, gulp-util@~3.0.0: +gulp-util@^3.0, gulp-util@^3.0.2, gulp-util@^3.0.7: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -5987,19 +5848,20 @@ gulp-watch@^5.0.0: vinyl-file "^2.0.0" gulp-zip@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/gulp-zip/-/gulp-zip-4.0.0.tgz#1cefc08b4bf36df4b5b1e7c6b36ee55ebbe4a881" + version "4.1.0" + resolved "https://registry.yarnpkg.com/gulp-zip/-/gulp-zip-4.1.0.tgz#dab178bd99afa190923f1eb78abaf0db47817704" dependencies: get-stream "^3.0.0" - gulp-util "^3.0.0" + plugin-error "^0.1.2" through2 "^2.0.1" + vinyl "^2.1.0" yazl "^2.1.0" "gulp@github:gulpjs/gulp#4.0": - version "4.0.0-alpha.3" - resolved "https://codeload.github.com/gulpjs/gulp/tar.gz/71c094a51c7972d26f557899ddecab0210ef3776" + version "4.0.0" + resolved "https://codeload.github.com/gulpjs/gulp/tar.gz/55eb23a268dcc7340bb40808600fd4802848c06f" dependencies: - glob-watcher "^4.0.0" + glob-watcher "^5.0.0" gulp-cli "^2.0.0" undertaker "^1.0.0" vinyl-fs "^3.0.0" @@ -6069,18 +5931,6 @@ has-binary2@~1.0.2: dependencies: isarray "2.0.1" -has-binary@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.6.tgz#25326f39cfa4f616ad8787894e3af2cfbc7b6e10" - dependencies: - isarray "0.0.1" - -has-binary@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" - dependencies: - isarray "0.0.1" - has-color@~0.1.0: version "0.1.7" resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" @@ -6218,6 +6068,16 @@ hipchat-notifier@^1.1.0: lodash "^4.0.0" request "^2.0.0" +history@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b" + dependencies: + invariant "^2.2.1" + loose-envify "^1.2.0" + resolve-pathname "^2.2.0" + value-equal "^0.4.0" + warning "^3.0.0" + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -6231,12 +6091,12 @@ hoek@2.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" -hoist-non-react-statics@^2.2.1, hoist-non-react-statics@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" +hoist-non-react-statics@^2.3.0, hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" home-or-tmp@^2.0.0: version "2.0.0" @@ -6252,8 +6112,8 @@ homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + version "2.6.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" html-encoding-sniffer@^1.0.2: version "1.0.2" @@ -6316,7 +6176,7 @@ http-cache-semantics@3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" -http-errors@1.6.2, http-errors@~1.6.2: +http-errors@1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" dependencies: @@ -6332,9 +6192,18 @@ http-errors@~1.3.1: inherits "~2.0.1" statuses "1" +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + http-parser-js@>=0.4.0: - version "0.4.9" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1" + version "0.4.11" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.11.tgz#5b720849c650903c27e521633d94696ee95f3529" http-proxy-agent@1: version "1.0.0" @@ -6391,8 +6260,8 @@ https-proxy-agent@1: extend "3" https-proxy-agent@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz#7fbba856be8cd677986f42ebd3664f6317257887" + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" dependencies: agent-base "^4.1.0" debug "^3.1.0" @@ -6413,10 +6282,16 @@ iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" -iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.5, iconv-lite@~0.4.13: +iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@^0.4.17, iconv-lite@^0.4.5, iconv-lite@~0.4.13: + version "0.4.21" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.21.tgz#c47f8733d02171189ebc4a400f3218d348094798" + dependencies: + safer-buffer "^2.1.0" + idb-global@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/idb-global/-/idb-global-2.1.0.tgz#2a3e09d1ed9df3a836d59aeea99bf74047b8cc8d" @@ -6424,8 +6299,8 @@ idb-global@^2.1.0: obs-store "^2.4.1" identicon.js@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/identicon.js/-/identicon.js-2.3.1.tgz#0f16a0dd5e61e1a89699400cc192af4445506e5b" + version "2.3.2" + resolved "https://registry.yarnpkg.com/identicon.js/-/identicon.js-2.3.2.tgz#bfebb66c8047f386333ffa595fe2912345a0708d" idna-uts46@^1.0.1: version "1.1.0" @@ -6434,8 +6309,8 @@ idna-uts46@^1.0.1: punycode "^2.1.0" ieee754@^1.1.4: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + version "1.1.11" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.11.tgz#c16384ffe00f5b7835824e67b6f2bd44a5229455" iframe-stream@^3.0.0: version "3.0.0" @@ -6528,8 +6403,8 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" inject-css@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/inject-css/-/inject-css-0.1.1.tgz#ef3ffc78ec026c96e2355da0df32917e3526415c" + version "0.1.2" + resolved "https://registry.yarnpkg.com/inject-css/-/inject-css-0.1.2.tgz#94943e3944c409ba8a11f22e9de322ef0865e45a" inline-source-map@~0.5.0: version "0.5.0" @@ -6581,19 +6456,20 @@ inquirer@^5.1.0: through "^2.3.6" insert-module-globals@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.1.tgz#c03bf4e01cb086d5b5e5ace8ad0afe7889d638c3" + version "7.0.6" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.6.tgz#15a31d9d394e76d08838b9173016911d7fd4ea1b" dependencies: JSONStream "^1.0.3" - combine-source-map "~0.7.1" - concat-stream "~1.5.1" + combine-source-map "^0.8.0" + concat-stream "^1.6.1" is-buffer "^1.1.0" lexical-scope "^1.2.0" + path-is-absolute "^1.0.1" process "~0.11.0" through2 "^2.0.0" xtend "^4.0.0" -interpret@^1.0.0, interpret@^1.0.4: +interpret@^1.0.0, interpret@^1.0.4, interpret@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" @@ -6604,9 +6480,9 @@ into-stream@^3.1.0: from2 "^2.1.1" p-is-promise "^1.1.0" -invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" +invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: loose-envify "^1.0.0" @@ -6622,9 +6498,9 @@ ip@^1.1.2, ip@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" -ipaddr.js@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" +ipaddr.js@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b" irregular-plurals@^1.0.0: version "1.4.0" @@ -6806,12 +6682,17 @@ is-hexadecimal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + is-my-json-valid@^2.12.4: - version "2.17.1" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" + version "2.17.2" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" jsonpointer "^4.0.0" xtend "^4.0.0" @@ -6857,12 +6738,6 @@ is-observable@^0.2.0: dependencies: symbol-observable "^0.2.2" -is-odd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" - dependencies: - is-number "^3.0.0" - is-odd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" @@ -6874,8 +6749,8 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" dependencies: is-path-inside "^1.0.0" @@ -6928,8 +6803,8 @@ is-relative@^1.0.0: is-unc-path "^1.0.0" is-resolvable@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.1.tgz#acca1cd36dbe44b974b924321555a70ba03b1cf4" + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: version "1.1.0" @@ -6954,8 +6829,8 @@ is-subset@^0.1.1: resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" is-supported-regexp-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8" + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca" is-symbol@^1.0.1: version "1.0.1" @@ -6993,14 +6868,10 @@ is-windows@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" -is-windows@^1.0.0, is-windows@^1.0.2: +is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" -is-windows@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" - is-word-character@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" @@ -7017,6 +6888,10 @@ isarray@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" +isarray@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" + isbinaryfile@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" @@ -7046,50 +6921,50 @@ isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-lib-coverage@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" +istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" istanbul-lib-hook@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b" + version "1.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz#ae556fd5a41a6e8efa0b1002b1e416dfeaf9816c" dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e" +istanbul-lib-instrument@^1.10.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" babylon "^6.18.0" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.2.0" semver "^5.3.0" -istanbul-lib-report@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz#922be27c13b9511b979bd1587359f69798c1d425" +istanbul-lib-report@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz#e886cdf505c4ebbd8e099e4396a90d0a28e2acb5" dependencies: - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.2.0" mkdirp "^0.5.1" path-parse "^1.0.5" supports-color "^3.1.2" -istanbul-lib-source-maps@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz#750578602435f28a0c04ee6d7d9e0f2960e62c1c" +istanbul-lib-source-maps@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz#cc7ccad61629f4efff8e2f78adb8c522c9976ec7" dependencies: debug "^3.1.0" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.2.0" mkdirp "^0.5.1" rimraf "^2.6.1" source-map "^0.5.3" -istanbul-reports@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.3.tgz#3b9e1e8defb6d18b1d425da8e8b32c5a163f2d10" +istanbul-reports@^1.1.4: + version "1.3.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.3.0.tgz#2f322e81e1d9520767597dca3c20a0cce89a3554" dependencies: handlebars "^4.0.3" @@ -7124,14 +6999,15 @@ jazzicon@^1.2.0: raphael "^2.2.0" js-base64@^2.1.8, js-base64@^2.1.9: - version "2.4.0" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" + version "2.4.3" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582" -js-beautify@~1.5.4: - version "1.5.10" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.5.10.tgz#4d95371702699344a516ca26bf59f0a27bb75719" +js-beautify@^1.7.5: + version "1.7.5" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.7.5.tgz#69d9651ef60dbb649f65527b53674950138a7919" dependencies: config-chain "~1.1.5" + editorconfig "^0.13.2" mkdirp "~0.5.0" nopt "~3.0.1" @@ -7156,8 +7032,8 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.4.3, js-yaml@^3.6.1, js-yaml@^3.9.1: - version "3.10.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + version "3.11.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -7211,17 +7087,16 @@ jsdom-global@^3.0.2: resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9" jsdom@^11.2.0: - version "11.6.2" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.6.2.tgz#25d1ef332d48adf77fc5221fe2619967923f16bb" + version "11.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.7.0.tgz#8b45b657dae90d6d2d3a5f5d1126bb7102d0a172" dependencies: abab "^1.0.4" acorn "^5.3.0" acorn-globals "^4.1.0" array-equal "^1.0.0" - browser-process-hrtime "^0.1.2" - content-type-parser "^1.0.2" cssom ">= 0.3.2 < 0.4.0" cssstyle ">= 0.2.37 < 0.3.0" + data-urls "^1.0.0" domexception "^1.0.0" escodegen "^1.9.0" html-encoding-sniffer "^1.0.2" @@ -7237,6 +7112,7 @@ jsdom@^11.2.0: w3c-hr-time "^1.0.1" webidl-conversions "^4.0.2" whatwg-encoding "^1.0.3" + whatwg-mimetype "^2.1.0" whatwg-url "^6.4.0" ws "^4.0.0" xml-name-validator "^3.0.0" @@ -7245,6 +7121,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -7285,27 +7165,7 @@ json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" -json-rpc-engine@^3.0.1, json-rpc-engine@^3.1.0, json-rpc-engine@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.4.0.tgz#8a1647a7f2cc7018f4802f41ec8208d281f78bfc" - dependencies: - async "^2.0.1" - babel-preset-env "^1.3.2" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - -json-rpc-engine@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.6.0.tgz#0cc673dcb4b71103523fec81d1bba195a457f993" - dependencies: - async "^2.0.1" - babel-preset-env "^1.3.2" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - -json-rpc-engine@^3.6.1: +json-rpc-engine@^3.0.1, json-rpc-engine@^3.1.0, json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0, json-rpc-engine@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.6.1.tgz#f53084726dc6dedeead0e2c457eeb997135f1e25" dependencies: @@ -7363,10 +7223,6 @@ json-stringify-safe@5.0.x, json-stringify-safe@^5.0.1, json-stringify-safe@~5.0. version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -7419,7 +7275,7 @@ jstransform@^10.1.0: esprima-fb "13001.1001.0-dev-harmony-fb" source-map "0.1.31" -jsx-ast-utils@^2.0.0: +jsx-ast-utils@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" dependencies: @@ -7439,7 +7295,7 @@ just-debounce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" -just-extend@^1.1.26: +just-extend@^1.1.27: version "1.1.27" resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" @@ -7523,7 +7379,11 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: @@ -7554,11 +7414,11 @@ known-css-properties@^0.2.0: resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.2.0.tgz#899c94be368e55b42d7db8d5be7d73a4a4a41454" labeled-stream-splicer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59" + version "2.0.1" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926" dependencies: inherits "^2.0.1" - isarray "~0.0.1" + isarray "^2.0.4" stream-splicer "^2.0.0" last-run@^1.1.0: @@ -7572,12 +7432,6 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" -lazy-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - dependencies: - set-getter "^0.1.0" - lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -7608,8 +7462,8 @@ lead@^1.0.0: flush-write-stream "^1.0.2" left-pad@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee" + version "1.3.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" leftpad@0.0.0: version "0.0.0" @@ -7694,7 +7548,7 @@ lie@~3.1.0: dependencies: immediate "~3.0.5" -liftoff@^2.3.0: +liftoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" dependencies: @@ -7756,8 +7610,8 @@ listr@^0.13.0: strip-ansi "^3.0.1" livereload-js@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.2.2.tgz#6c87257e648ab475bc24ea257457edcc1f8d0bc2" + version "2.3.0" + resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.3.0.tgz#c3ab22e8aaf5bf3505d80d098cbad67726548c9a" load-json-file@^1.0.0: version "1.1.0" @@ -7810,9 +7664,9 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash-es@^4.2.0, lodash-es@^4.2.1: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" +lodash-es@^4.17.5, lodash-es@^4.2.1: + version "4.17.8" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.8.tgz#6fa8c8c5d337481df0bdf1c0d899d42473121e45" lodash._baseassign@^3.0.0: version "3.2.0" @@ -7964,8 +7818,8 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" lodash.mergewith@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" lodash.restparam@^3.0.0: version "3.6.1" @@ -8008,17 +7862,13 @@ lodash@3.7.x: version "3.7.0" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.7.0.tgz#3678bd8ab995057c07ade836ed2ef087da811d45" -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@~4.17.2, lodash@~4.17.4: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - -lodash@^4.17.2, lodash@^4.17.5: +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@~4.17.4: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" log-driver@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" log-symbols@^1.0.0, log-symbols@^1.0.2: version "1.0.2" @@ -8067,22 +7917,18 @@ loggly@^1.1.0: timespan "2.3.x" loglevel@^1.4.1, loglevel@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.0.tgz#ae0caa561111498c5ba13723d6fb631d24003934" - -lolex@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" + version "1.6.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" -lolex@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.1.tgz#3d2319894471ea0950ef64692ead2a5318cff362" +lolex@^2.2.0, lolex@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.2.tgz#85f9450425103bf9e7a60668ea25dc43274ca807" longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: @@ -8103,9 +7949,12 @@ lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" -lru-cache@2.2.x: - version "2.2.4" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" +lru-cache@4.1.x, lru-cache@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" lru-cache@^3.2.0: version "3.2.0" @@ -8113,13 +7962,6 @@ lru-cache@^3.2.0: dependencies: pseudomap "^1.0.1" -lru-cache@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@~2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5" @@ -8131,8 +7973,14 @@ lru-queue@0.1: es5-ext "~0.10.2" ltgt@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.0.tgz#b65ba5fcb349a29924c8e333f7c6a5562f2e4842" + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + dependencies: + vlq "^0.2.2" mailcomposer@4.0.1: version "4.0.1" @@ -8168,14 +8016,14 @@ make-error-cause@^1.1.1: make-error "^1.2.0" make-error@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.2.tgz#8762ffad2444dd8ff1f7c819629fa28e24fea1c4" + version "1.3.4" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" make-iterator@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.0.tgz#57bef5dc85d23923ba23767324d8e8f8f3d9694b" + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" dependencies: - kind-of "^3.1.0" + kind-of "^6.0.2" map-async@^0.1.1: version "0.1.1" @@ -8284,8 +8132,8 @@ memdown@^1.0.0: safe-buffer "~5.1.1" memoizee@0.4.X: - version "0.4.11" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.11.tgz#bde9817663c9e40fdb2a4ea1c367296087ae8c8f" + version "0.4.12" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.12.tgz#780e99a219c50c549be6d0fc61765080975c58fb" dependencies: d "1" es5-ext "^0.10.30" @@ -8326,6 +8174,12 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge-source-map@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + dependencies: + source-map "^0.5.6" + merge-source-map@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" @@ -8333,8 +8187,8 @@ merge-source-map@^1.0.2: source-map "^0.6.1" merkle-patricia-tree@^2.1.2: - version "2.3.0" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.0.tgz#84c606232ef343f1b96fc972e697708754f08573" + version "2.3.1" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz#7d4e7263a9c85c1679187cad4a6d71f48d524c71" dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -8362,8 +8216,8 @@ metamascara@^2.0.0: pump "^1.0.2" metamask-logo@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/metamask-logo/-/metamask-logo-2.1.3.tgz#175ce57ae50c7344b3b1dc32d2fd0b08e3978fd0" + version "2.1.4" + resolved "https://registry.yarnpkg.com/metamask-logo/-/metamask-logo-2.1.4.tgz#0612b2b0ffc7eeb6be480c310785426ad9599e3c" dependencies: gl-mat4 "1.1.4" gl-vec3 "1.0.3" @@ -8390,27 +8244,9 @@ micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.0.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.4.tgz#bb812e741a41f982c854e42b421a7eac458796f4" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.0" - define-property "^1.0.0" - extend-shallow "^2.0.1" - extglob "^2.0.2" - fragment-cache "^0.2.1" - kind-of "^6.0.0" - nanomatch "^1.2.5" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -micromatch@^3.1.4: - version "3.1.9" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.9.tgz#15dc93175ae39e52e93087847096effc73efcf89" +micromatch@^3.0.4, micromatch@^3.1.4, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -8424,7 +8260,7 @@ micromatch@^3.1.4: object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" - to-regex "^3.0.1" + to-regex "^3.0.2" miller-rabin@^4.0.0: version "4.0.1" @@ -8433,30 +8269,16 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -"mime-db@>= 1.30.0 < 2": - version "1.32.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" - -mime-db@~1.30.0: - version "1.30.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - -mime-db@~1.33.0: +"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" -mime-types@^2.1.11: +mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: version "2.1.18" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: - version "2.1.17" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - dependencies: - mime-db "~1.30.0" - mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" @@ -8470,8 +8292,8 @@ mime@~1.2.9: resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" mimic-response@^1.0.0: version "1.0.0" @@ -8531,8 +8353,8 @@ minimist@~0.0.1, minimist@~0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" mixin-deep@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.0.tgz#47a8732ba97799457c8c1eca28f95132d7e8150a" + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -8571,13 +8393,13 @@ mocha-sinon@^2.0.0: resolved "https://registry.yarnpkg.com/mocha-sinon/-/mocha-sinon-2.0.0.tgz#723a9310e7d737d7b77c7a66821237425b032d48" mocha@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.1.tgz#759b62c836b0732382a62b6b1fb245ec1bc943ac" + version "5.0.5" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.5.tgz#e228e3386b9387a4710007a641f127b00be44b52" dependencies: - browser-stdout "1.3.0" + browser-stdout "1.3.1" commander "2.11.0" debug "3.1.0" - diff "3.3.1" + diff "3.5.0" escape-string-regexp "1.0.5" glob "7.1.2" growl "1.10.3" @@ -8606,8 +8428,8 @@ module-deps@^4.0.8: xtend "^4.0.0" module-deps@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.0.0.tgz#4417b49a4f4d7af79b104186e5389ea99b1dc837" + version "6.0.2" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.0.2.tgz#660217d1602b863ac8d4d16951a3720dd9aa4c80" dependencies: JSONStream "^1.0.3" browser-resolve "^1.7.0" @@ -8629,10 +8451,6 @@ ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -8682,25 +8500,9 @@ mz@^2.6.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.2: - version "2.8.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" - -nanomatch@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.6.tgz#f27233e97c34a8706b7e781a4bc611c957a81625" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^1.0.0" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - is-odd "^1.0.0" - kind-of "^5.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" +nan@^2.0.5, nan@^2.0.8, nan@^2.10.0, nan@^2.2.1, nan@^2.3.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" nanomatch@^1.2.9: version "1.2.9" @@ -8728,12 +8530,13 @@ ncp@1.0.x: resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" nearley@^2.7.10: - version "2.11.0" - resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.11.0.tgz#5e626c79a6cd2f6ab9e7e5d5805e7668967757ae" + version "2.13.0" + resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.13.0.tgz#6e7b0f4e68bfc3e74c99eaef2eda39e513143439" dependencies: nomnom "~1.6.2" railroad-diagrams "^1.0.0" - randexp "^0.4.2" + randexp "0.4.6" + semver "^5.4.1" negotiator@0.6.1: version "0.6.1" @@ -8756,28 +8559,28 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" nise@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53" + version "1.3.2" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.3.2.tgz#fd6fd8dc040dfb3c0a45252feb6ff21832309b14" dependencies: - formatio "^1.2.0" - just-extend "^1.1.26" - lolex "^1.6.0" + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" path-to-regexp "^1.7.0" text-encoding "^0.6.4" nock@^9.0.14: - version "9.1.5" - resolved "https://registry.yarnpkg.com/nock/-/nock-9.1.5.tgz#9e4878e0e1c050bdd93ae1e326e89461ea15618b" + version "9.2.3" + resolved "https://registry.yarnpkg.com/nock/-/nock-9.2.3.tgz#39738087d6a0497d3a165fb352612b38a2f9b92f" dependencies: - chai ">=1.9.2 <4.0.0" - debug "^2.2.0" + chai "^4.1.2" + debug "^3.1.0" deep-equal "^1.0.0" json-stringify-safe "^5.0.1" - lodash "~4.17.2" + lodash "^4.17.5" mkdirp "^0.5.0" - propagate "0.4.0" + propagate "^1.0.0" qs "^6.5.1" - semver "^5.3.0" + semver "^5.5.0" node-dir@0.1.8: version "0.1.8" @@ -8837,13 +8640,13 @@ node-libs-browser@^2.0.0: vm-browserify "0.0.4" node-notifier@^5.0.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff" + version "5.2.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" dependencies: growly "^1.3.0" - semver "^5.3.0" - shellwords "^0.1.0" - which "^1.2.12" + semver "^5.4.1" + shellwords "^0.1.1" + which "^1.3.0" node-pre-gyp@^0.6.39: version "0.6.39" @@ -8861,9 +8664,9 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" -node-sass@^4.2.0, node-sass@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" +node-sass@^4.7.2, node-sass@^4.8.3: + version "4.8.3" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.8.3.tgz#d077cc20a08ac06f661ca44fb6f19cd2ed41debb" dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -8877,7 +8680,7 @@ node-sass@^4.2.0, node-sass@^4.7.2: lodash.mergewith "^4.6.0" meow "^3.7.0" mkdirp "^0.5.1" - nan "^2.3.2" + nan "^2.10.0" node-gyp "^3.3.1" npmlog "^4.0.0" request "~2.79.0" @@ -9043,29 +8846,29 @@ number-to-bn@1.7.0, number-to-bn@^1.7.0: strip-hex-prefix "1.0.0" nwmatcher@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.3.tgz#64348e3b3d80f035b40ac11563d278f8b72db89c" + version "1.4.4" + resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e" nyc@^11.0.3: - version "11.4.1" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.4.1.tgz#13fdf7e7ef22d027c61d174758f6978a68f4f5e5" + version "11.6.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.6.0.tgz#d9c7b51ffceb6bba099a4683a6adc1b331b98853" dependencies: archy "^1.0.0" arrify "^1.0.1" caching-transform "^1.0.0" - convert-source-map "^1.3.0" + convert-source-map "^1.5.1" debug-log "^1.0.1" default-require-extensions "^1.0.0" find-cache-dir "^0.1.1" find-up "^2.1.0" foreground-child "^1.5.3" glob "^7.0.6" - istanbul-lib-coverage "^1.1.1" + istanbul-lib-coverage "^1.1.2" istanbul-lib-hook "^1.1.0" - istanbul-lib-instrument "^1.9.1" - istanbul-lib-report "^1.1.2" - istanbul-lib-source-maps "^1.2.2" - istanbul-reports "^1.1.3" + istanbul-lib-instrument "^1.10.0" + istanbul-lib-report "^1.1.3" + istanbul-lib-source-maps "^1.2.3" + istanbul-reports "^1.1.4" md5-hex "^1.2.0" merge-source-map "^1.0.2" micromatch "^2.3.11" @@ -9074,8 +8877,8 @@ nyc@^11.0.3: rimraf "^2.5.4" signal-exit "^3.0.1" spawn-wrap "^1.4.2" - test-exclude "^4.1.1" - yargs "^10.0.3" + test-exclude "^4.2.0" + yargs "11.1.0" yargs-parser "^8.0.0" o-stream@^0.2.2: @@ -9098,10 +8901,6 @@ object-assign@3.0.0, object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - object-assign@4.X, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -9118,17 +8917,13 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.5.0: +object-inspect@^1.5.0, object-inspect@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.5.0.tgz#9d876c11e40f485c79215670281b767488f9bfe3" -object-inspect@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-0.4.0.tgz#f5157c116c1455b243b06ee97703392c5ad89fec" - -object-inspect@~1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.3.0.tgz#5b1eb8e6742e2ee83342a637034d844928ba2f6d" +object-inspect@~1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" object-is@^1.0.1: version "1.0.1" @@ -9291,10 +9086,6 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" - ora@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" @@ -9341,8 +9132,8 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" osenv@0, osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -9380,8 +9171,10 @@ p-lazy@^1.0.0: resolved "https://registry.yarnpkg.com/p-lazy/-/p-lazy-1.0.0.tgz#ec53c802f2ee3ac28f166cc82d0b2b02de27a835" p-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" + dependencies: + p-try "^1.0.0" p-locate@^2.0.0: version "2.0.0" @@ -9409,6 +9202,10 @@ p-timeout@^2.0.1: dependencies: p-finally "^1.0.0" +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + pac-proxy-agent@1: version "1.1.0" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz#34a385dfdf61d2f0ecace08858c745d3e791fd4d" @@ -9453,7 +9250,7 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" -parse-entities@^1.0.2: +parse-entities@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890" dependencies: @@ -9515,12 +9312,6 @@ parse5@^3.0.1: dependencies: "@types/node" "*" -parsejson@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" - dependencies: - better-assert "~1.0.0" - parseqs@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" @@ -9712,7 +9503,17 @@ plucker@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/plucker/-/plucker-0.0.0.tgz#2ffa24e03ab2cffa4e75adc1df70f25623c45d09" -plugin-error@^1.0.1: +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +plugin-error@^1.0.0, plugin-error@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" dependencies: @@ -9758,8 +9559,8 @@ polyfill-crypto.getrandomvalues@^1.0.0: mersenne-twister "^1.0.1" popper.js@^1.11.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.13.0.tgz#e1e7ff65cc43f7cf9cf16f1510a75e81f84f4565" + version "1.14.3" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" portfinder@~0.2.1: version "0.2.1" @@ -9843,21 +9644,13 @@ postcss@^5.0.0, postcss@^5.0.18, postcss@^5.0.20, postcss@^5.0.21, postcss@^5.0. source-map "^0.5.6" supports-color "^3.2.3" -postcss@^6.0.1: - version "6.0.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" +postcss@^6.0.1, postcss@^6.0.20: + version "6.0.21" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.21.tgz#8265662694eddf9e9a5960db6da33c39e4cd069d" dependencies: - chalk "^2.3.0" - source-map "^0.6.1" - supports-color "^4.4.0" - -postcss@^6.0.19: - version "6.0.19" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555" - dependencies: - chalk "^2.3.1" + chalk "^2.3.2" source-map "^0.6.1" - supports-color "^5.2.0" + supports-color "^5.3.0" prelude-ls@~1.1.2: version "1.1.2" @@ -9899,11 +9692,11 @@ private@^0.1.6, private@^0.1.7, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" -process-nextick-args@^1.0.6, process-nextick-args@^1.0.7, process-nextick-args@~1.0.6: +process-nextick-args@^1.0.7, process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -process-nextick-args@~2.0.0: +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" @@ -9955,28 +9748,28 @@ prompt@^1.0.0: utile "0.3.x" winston "2.1.x" -prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0: - version "15.6.0" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" +prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" dependencies: fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" -propagate@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-0.4.0.tgz#f3fcca0a6fe06736a7ba572966069617c130b481" +propagate@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-1.0.0.tgz#00c2daeedda20e87e3782b344adba1cddd6ad709" proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" -proxy-addr@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" +proxy-addr@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" dependencies: forwarded "~0.1.2" - ipaddr.js "1.5.2" + ipaddr.js "1.6.0" proxy-agent@~2.0.0: version "2.0.0" @@ -10019,13 +9812,20 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" -pump@^1.0.0, pump@^1.0.2: +pump@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" dependencies: end-of-stream "^1.1.0" once "^1.3.1" +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -10034,12 +9834,12 @@ pump@^3.0.0: once "^1.3.1" pumpify@^1.3.4, pumpify@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b" + version "1.4.0" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.4.0.tgz#80b7c5df7e24153d03f0e7ac8a05a5d068bd07fb" dependencies: - duplexify "^3.1.2" - inherits "^2.0.1" - pump "^1.0.0" + duplexify "^3.5.3" + inherits "^2.0.3" + pump "^2.0.0" punycode@1.3.2: version "1.3.2" @@ -10062,8 +9862,8 @@ q@~1.4.0: resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" qjobs@^1.1.4: - version "1.1.5" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73" + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" qrcode-npm@0.0.3: version "0.0.3" @@ -10121,7 +9921,7 @@ qunitjs@^2.4.1: resolve "1.3.2" walk-sync "0.3.1" -quote-stream@^1.0.1: +quote-stream@^1.0.1, quote-stream@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" dependencies: @@ -10129,13 +9929,6 @@ quote-stream@^1.0.1: minimist "^1.1.3" through2 "^2.0.0" -quote-stream@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-0.0.0.tgz#cde29e94c409b16e19dc7098b89b6658f9721d3b" - dependencies: - minimist "0.0.8" - through2 "~0.4.1" - raf@^3.1.0, raf@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" @@ -10154,7 +9947,7 @@ ramda@^0.25.0: version "0.25.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" -randexp@^0.4.2: +randexp@0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" dependencies: @@ -10169,14 +9962,14 @@ randomatic@^1.1.3: kind-of "^4.0.0" randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -10192,8 +9985,8 @@ raphael@^2.2.0: eve-raphael "0.5.0" raven-js@^3.24.0: - version "3.24.0" - resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.24.0.tgz#59464d8bc4b3812ae87a282e9bb98ecad5b4b047" + version "3.24.1" + resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.24.1.tgz#7327e08786248517eedd36205bf50f1047821ffa" raw-body@2, raw-body@2.3.2: version "2.3.2" @@ -10213,8 +10006,8 @@ raw-body@~2.1.5: unpipe "1.0.0" rc@^1.1.7: - version "1.2.2" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" + version "1.2.6" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" dependencies: deep-extend "~0.4.0" ini "~1.3.0" @@ -10247,23 +10040,23 @@ react-hyperscript@^2.4.0: react ">= 0.12.0 < 16.0.0" react-hyperscript@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-hyperscript/-/react-hyperscript-3.0.0.tgz#3c16010b33175de6bc01fd1ebad0a16a9a6dc9ab" + version "3.2.0" + resolved "https://registry.yarnpkg.com/react-hyperscript/-/react-hyperscript-3.2.0.tgz#24144ff6b1beb07af7154794a782a74b34920868" -react-input-autosize@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.1.2.tgz#a3dc11a5517c434db25229925541309de3f7a8f5" +react-input-autosize@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" dependencies: prop-types "^15.5.8" react-markdown@^3.0.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-3.1.3.tgz#5ac1f20cb5a3e8c47b6ae3c8522e813b08f58c34" + version "3.3.0" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-3.3.0.tgz#a87cdd822aa9302d6add9687961dd1a82a45d02e" dependencies: - prop-types "^15.6.0" - remark-parse "^4.0.0" + prop-types "^15.6.1" + remark-parse "^5.0.0" unified "^6.1.5" - unist-util-visit "^1.1.3" + unist-util-visit "^1.3.0" xtend "^4.0.1" react-motion@^0.5.2: @@ -10275,27 +10068,50 @@ react-motion@^0.5.2: raf "^3.1.0" react-redux@^5.0.5: - version "5.0.6" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946" + version "5.0.7" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" dependencies: - hoist-non-react-statics "^2.2.1" + hoist-non-react-statics "^2.5.0" invariant "^2.0.0" - lodash "^4.2.0" - lodash-es "^4.2.0" + lodash "^4.17.5" + lodash-es "^4.17.5" loose-envify "^1.1.0" - prop-types "^15.5.10" + prop-types "^15.6.0" + +react-router-dom@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d" + dependencies: + history "^4.7.2" + invariant "^2.2.2" + loose-envify "^1.3.1" + prop-types "^15.5.4" + react-router "^4.2.0" + warning "^3.0.0" + +react-router@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.2.0.tgz#61f7b3e3770daeb24062dae3eedef1b054155986" + dependencies: + history "^4.7.2" + hoist-non-react-statics "^2.3.0" + invariant "^2.2.2" + loose-envify "^1.3.1" + path-to-regexp "^1.7.0" + prop-types "^15.5.4" + warning "^3.0.0" react-select@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.1.0.tgz#626a2de839fdea2ade74dd1b143a9bde34be6c82" + version "1.2.1" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.2.1.tgz#a2fe58a569eb14dcaa6543816260b97e538120d1" dependencies: classnames "^2.2.4" prop-types "^15.5.8" - react-input-autosize "^2.1.0" + react-input-autosize "^2.1.2" react-simple-file-input@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/react-simple-file-input/-/react-simple-file-input-2.0.1.tgz#15ad4ffc78feb1b882649ad6b01c033ef27571e6" + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-simple-file-input/-/react-simple-file-input-2.1.0.tgz#d0742be5acd781bf746e6f792b0bc724cd5c09f2" dependencies: prop-types "^15.5.7" @@ -10307,8 +10123,8 @@ react-test-renderer@^15.6.2: object-assign "^4.1.0" react-testutils-additions@^15.2.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/react-testutils-additions/-/react-testutils-additions-15.3.0.tgz#0ee96a5998f54e2bda2cf0a3430a345df04b7f64" + version "15.3.1" + resolved "https://registry.yarnpkg.com/react-testutils-additions/-/react-testutils-additions-15.3.1.tgz#265a804a90935330c5c5fc90aafb43c0a6780cf4" dependencies: object-assign "3.0.0" sizzle "2.3.3" @@ -10348,11 +10164,10 @@ react-transition-group@^1.2.0: warning "^3.0.0" react-transition-group@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.2.1.tgz#e9fb677b79e6455fd391b03823afe84849df4a10" + version "2.3.0" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.3.0.tgz#8dd1af58f6af284b19fd057f512e74f20438ad31" dependencies: chain-function "^1.0.0" - classnames "^2.2.5" dom-helpers "^3.2.0" loose-envify "^1.3.1" prop-types "^15.5.8" @@ -10452,16 +10267,16 @@ readable-stream@1.1.x, "readable-stream@1.x >=1.1.9", "readable-stream@>=1.1.13- isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@2, readable-stream@^2.3.0: - version "2.3.5" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" +readable-stream@2, readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@~2.3.3: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" isarray "~1.0.0" process-nextick-args "~2.0.0" safe-buffer "~5.1.1" - string_decoder "~1.0.3" + string_decoder "~1.1.1" util-deprecate "~1.0.1" "readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.15, readable-stream@~1.0.17, readable-stream@~1.0.27-1: @@ -10473,18 +10288,6 @@ readable-stream@2, readable-stream@^2.3.0: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9, readable-stream@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - readable-stream@~2.0.0, readable-stream@~2.0.5, readable-stream@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -10626,11 +10429,16 @@ regex-cache@^0.4.2: dependencies: is-equal-shallow "^0.1.3" -regex-not@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" dependencies: - extend-shallow "^2.0.1" + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" regexpu-core@^2.0.0: version "2.0.0" @@ -10650,9 +10458,9 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -remark-parse@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-4.0.0.tgz#99f1f049afac80382366e2e0d0bd55429dd45d8b" +remark-parse@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" dependencies: collapse-white-space "^1.0.2" is-alphabetical "^1.0.0" @@ -10660,7 +10468,7 @@ remark-parse@^4.0.0: is-whitespace-character "^1.0.0" is-word-character "^1.0.0" markdown-escapes "^1.0.0" - parse-entities "^1.0.2" + parse-entities "^1.1.0" repeat-string "^1.5.4" state-toggle "^1.0.0" trim "0.0.1" @@ -10701,12 +10509,6 @@ repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" -repeating@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" - dependencies: - is-finite "^1.0.0" - repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" @@ -10765,8 +10567,8 @@ request-promise@^4.2.1: tough-cookie ">=2.3.3" request@2, request@^2.0.0, request@^2.67.0, request@^2.74.0, request@^2.79.0, request@^2.83.0: - version "2.83.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + version "2.85.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -10939,6 +10741,10 @@ resolve-options@^1.1.0: dependencies: value-or-function "^3.0.0" +resolve-pathname@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" + resolve-url@^0.2.1, resolve-url@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -10958,14 +10764,14 @@ resolve@^0.6.1: resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + version "1.7.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.0.tgz#2bdf5374811207285df0df652b78f118ab8f3c5e" dependencies: path-parse "^1.0.5" -resolve@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" +resolve@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" dependencies: path-parse "^1.0.5" @@ -11048,8 +10854,8 @@ run-async@^2.0.0, run-async@^2.2.0: is-promise "^2.1.0" rustbn.js@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.1.1.tgz#088b8c29d5f6d7d9f56ffb545f5d110e4a6801eb" + version "0.1.2" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.1.2.tgz#979fa0f9562216dd667c9d2cd179ae5d13830eff" rx-lite-aggregates@^4.0.8: version "4.0.8" @@ -11071,7 +10877,17 @@ safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.x: +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +samsam@1.3.0, samsam@1.x: version "1.3.0" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" @@ -11137,8 +10953,8 @@ scss-tokenizer@^0.2.3: source-map "^0.4.2" secp256k1@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.4.0.tgz#1c905b256fa4ae5b9cc170e672dd59b4c5de46a4" + version "3.5.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.0.tgz#677d3b8a8e04e1a5fa381a1ae437c54207b738d0" dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -11162,17 +10978,13 @@ semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" -semver-greatest-satisfied-range@^1.0.0: +semver-greatest-satisfied-range@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" dependencies: sver-compat "^1.5.0" -"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - -semver@^5.5.0: +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -11184,14 +10996,18 @@ semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -send@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" dependencies: debug "2.6.9" - depd "~1.1.1" + depd "~1.1.2" destroy "~1.0.4" - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" @@ -11200,27 +11016,21 @@ send@0.16.1: ms "2.0.0" on-finished "~2.3.0" range-parser "~1.2.0" - statuses "~1.3.1" + statuses "~1.4.0" -serve-static@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" dependencies: - encodeurl "~1.0.1" + encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.2" - send "0.16.1" + send "0.16.2" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" -set-getter@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - dependencies: - to-object-path "^0.3.0" - set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -11256,8 +11066,8 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: - version "2.4.9" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d" + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -11319,7 +11129,7 @@ shelljs@^0.8.0: interpret "^1.0.0" rechoir "^0.6.2" -shellwords@^0.1.0: +shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" @@ -11397,8 +11207,8 @@ snapdragon-util@^3.0.1: kind-of "^3.2.0" snapdragon@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" dependencies: base "^0.11.1" debug "^2.2.0" @@ -11407,7 +11217,7 @@ snapdragon@^0.8.1: map-cache "^0.2.2" source-map "^0.5.6" source-map-resolve "^0.5.0" - use "^2.0.0" + use "^3.1.0" sntp@1.x.x: version "1.0.9" @@ -11421,60 +11231,47 @@ sntp@2.x.x: dependencies: hoek "4.x.x" -socket.io-adapter@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" - dependencies: - debug "2.3.3" - socket.io-parser "2.3.1" - socket.io-adapter@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" -socket.io-client@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.6.0.tgz#5b668f4f771304dfeed179064708386fa6717853" +socket.io-client@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.4.tgz#0918a552406dc5e540b380dcd97afc4a64332f8e" dependencies: backo2 "1.0.2" + base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" - debug "2.3.3" - engine.io-client "1.8.0" - has-binary "0.1.7" + debug "~2.6.4" + engine.io-client "~3.1.0" + has-cors "1.1.0" indexof "0.0.1" object-component "0.0.3" + parseqs "0.0.5" parseuri "0.0.5" - socket.io-parser "2.3.1" + socket.io-parser "~3.1.1" to-array "0.1.4" -socket.io-client@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.0.4.tgz#0918a552406dc5e540b380dcd97afc4a64332f8e" +socket.io-client@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.0.tgz#0d0b21d460dc4ed36e57085136f2be0137ff20ff" dependencies: backo2 "1.0.2" base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" - debug "~2.6.4" - engine.io-client "~3.1.0" + debug "~3.1.0" + engine.io-client "~3.2.0" + has-binary2 "~1.0.2" has-cors "1.1.0" indexof "0.0.1" object-component "0.0.3" parseqs "0.0.5" parseuri "0.0.5" - socket.io-parser "~3.1.1" + socket.io-parser "~3.2.0" to-array "0.1.4" -socket.io-parser@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" - dependencies: - component-emitter "1.1.2" - debug "2.2.0" - isarray "0.0.1" - json3 "3.3.2" - socket.io-parser@~3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.1.3.tgz#ed2da5ee79f10955036e3da413bfd7f1e4d86c8e" @@ -11484,17 +11281,13 @@ socket.io-parser@~3.1.1: has-binary2 "~1.0.2" isarray "2.0.1" -socket.io@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.6.0.tgz#3e40d932637e6bd923981b25caf7c53e83b6e2e1" +socket.io-parser@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" dependencies: - debug "2.3.3" - engine.io "1.8.0" - has-binary "0.1.7" - object-assign "4.1.0" - socket.io-adapter "0.5.0" - socket.io-client "1.6.0" - socket.io-parser "2.3.1" + component-emitter "1.2.1" + debug "~3.1.0" + isarray "2.0.1" socket.io@2.0.4: version "2.0.4" @@ -11506,6 +11299,17 @@ socket.io@2.0.4: socket.io-client "2.0.4" socket.io-parser "~3.1.1" +socket.io@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.0.tgz#de77161795b6303e7aefc982ea04acb0cec17395" + dependencies: + debug "~3.1.0" + engine.io "~3.2.0" + has-binary2 "~1.0.2" + socket.io-adapter "~1.1.0" + socket.io-client "2.1.0" + socket.io-parser "~3.2.0" + socks-proxy-agent@2: version "2.1.1" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz#86ebb07193258637870e13b7bd99f26c663df3d3" @@ -11529,8 +11333,8 @@ socks@~1.1.5: smart-buffer "^1.0.13" solc@^0.4.2: - version "0.4.19" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.19.tgz#1af1c4c292a0365a6977d4cbe3fbee7139b4b561" + version "0.4.21" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.21.tgz#6a7ecd505bfa0fc268330d5de6b9ae65c8c68264" dependencies: fs-extra "^0.30.0" memorystream "^0.3.1" @@ -11593,11 +11397,7 @@ source-map@0.1.31: dependencies: amdefine ">=0.0.4" -source-map@0.X, "source-map@>= 0.1.2", source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - -source-map@^0.1.38, source-map@~0.1.33: +source-map@^0.1.38: version "0.1.43" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" dependencies: @@ -11609,10 +11409,14 @@ source-map@^0.4.2, source-map@^0.4.4, source-map@~0.4.0, source-map@~0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + sparkles@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" @@ -11632,19 +11436,27 @@ spawn-wrap@^1.4.2: signal-exit "^3.0.2" which "^1.3.0" -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" dependencies: - spdx-license-ids "^1.0.2" + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" specificity@^0.3.0: version "0.3.2" @@ -11673,8 +11485,8 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + version "1.14.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -11694,11 +11506,11 @@ state-toggle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" -static-eval@~0.2.0: - version "0.2.4" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-0.2.4.tgz#b7d34d838937b969f9641ca07d48f8ede263ea7b" +static-eval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.0.tgz#0e821f8926847def7b4b50cda5d55c04a9b13864" dependencies: - escodegen "~0.0.24" + escodegen "^1.8.1" static-extend@^0.1.1: version "0.1.2" @@ -11707,30 +11519,37 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -static-module@^1.1.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/static-module/-/static-module-1.5.0.tgz#27da9883c41a8cd09236f842f0c1ebc6edf63d86" +static-module@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.3.tgz#72cf34b2ccb77d261f702da1dfda5df7853db14a" dependencies: concat-stream "~1.6.0" - duplexer2 "~0.0.2" - escodegen "~1.3.2" + convert-source-map "^1.5.1" + duplexer2 "~0.1.4" + escodegen "~1.9.0" falafel "^2.1.0" - has "^1.0.0" - object-inspect "~0.4.0" - quote-stream "~0.0.0" - readable-stream "~1.0.27-1" + has "^1.0.1" + magic-string "^0.22.4" + merge-source-map "1.0.4" + object-inspect "~1.4.0" + quote-stream "~1.0.2" + readable-stream "~2.3.3" shallow-copy "~0.0.1" - static-eval "~0.2.0" - through2 "~0.4.1" + static-eval "^2.0.0" + through2 "~2.0.3" -statuses@1, "statuses@>= 1.3.1 < 2": - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" +statuses@1, "statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + stdin@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/stdin/-/stdin-0.0.1.tgz#d3041981aaec3dfdbc77a1b38d6372e38f5fb71e" @@ -11777,12 +11596,12 @@ stream-exhaust@^1.0.1: resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" stream-http@^2.0.0, stream-http@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" + version "2.8.1" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.1.tgz#d0441be1a457a73a733a8a7b53570bebd9ef66a4" dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" - readable-stream "^2.2.6" + readable-stream "^2.3.3" to-arraybuffer "^1.0.0" xtend "^4.0.0" @@ -11860,9 +11679,9 @@ string.prototype.trim@~1.1.2: es-abstract "^1.5.0" function-bind "^1.0.2" -string_decoder@^1.0.0, string_decoder@~1.0.0, string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" dependencies: safe-buffer "~5.1.0" @@ -11870,6 +11689,12 @@ string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +string_decoder@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + stringify-object@^3.0.0: version "3.2.2" resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.2.tgz#9853052e5a88fb605a44cd27445aa257ad7ffbcd" @@ -12085,13 +11910,13 @@ supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3: dependencies: has-flag "^1.0.0" -supports-color@^4.0.0, supports-color@^4.4.0: +supports-color@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" dependencies: has-flag "^2.0.0" -supports-color@^5.2.0, supports-color@^5.3.0: +supports-color@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" dependencies: @@ -12137,8 +11962,8 @@ symbol-observable@^0.2.2: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" symbol-observable@^1.0.3, symbol-observable@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32" + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" symbol-tree@^3.2.2: version "3.2.2" @@ -12151,12 +11976,12 @@ synesthesia@^1.0.1: css-color-names "0.0.3" syntax-error@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.3.0.tgz#1ed9266c4d40be75dc55bf9bb1cb77062bb96ca1" + version "1.4.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" dependencies: - acorn "^4.0.3" + acorn-node "^1.2.0" -table@^4.0.1: +table@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: @@ -12167,6 +11992,17 @@ table@^4.0.1: slice-ansi "1.0.0" string-width "^2.1.1" +table@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" + dependencies: + ajv "^6.0.1" + ajv-keywords "^3.0.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + tap-parser@^5.1.0: version "5.4.0" resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-5.4.0.tgz#6907e89725d7b7fa6ae41ee2c464c3db43188aec" @@ -12185,19 +12021,19 @@ tapable@^1.0.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" tape@^4.4.0, tape@^4.5.1, tape@^4.6.0, tape@^4.6.2, tape@^4.6.3, tape@^4.8.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.8.0.tgz#f6a9fec41cc50a1de50fa33603ab580991f6068e" + version "4.9.0" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.0.tgz#855c08360395133709d34d3fbf9ef341eb73ca6a" dependencies: deep-equal "~1.0.1" defined "~1.0.0" for-each "~0.3.2" - function-bind "~1.1.0" + function-bind "~1.1.1" glob "~7.1.2" has "~1.0.1" inherits "~2.0.3" minimist "~1.2.0" - object-inspect "~1.3.0" - resolve "~1.4.0" + object-inspect "~1.5.0" + resolve "~1.5.0" resumer "~0.0.0" string.prototype.trim "~1.1.2" through "~2.3.8" @@ -12230,26 +12066,26 @@ temp@^0.8.1: os-tmpdir "^1.0.0" rimraf "~2.2.6" -test-exclude@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" +test-exclude@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" dependencies: arrify "^1.0.1" - micromatch "^2.3.11" + micromatch "^3.1.8" object-assign "^4.1.0" read-pkg-up "^1.0.1" require-main-filename "^1.0.1" testem@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/testem/-/testem-2.0.0.tgz#b05c96200c7ac98bae998d71c94c0c5345907d13" + version "2.2.1" + resolved "https://registry.yarnpkg.com/testem/-/testem-2.2.1.tgz#7bcda44eeb34287d918b3c8b9c6863d26a616557" dependencies: backbone "^1.1.2" bluebird "^3.4.6" charm "^1.0.0" commander "^2.6.0" consolidate "^0.14.0" - execa "^0.9.0" + execa "^0.10.0" express "^4.10.7" fireworm "^0.7.0" glob "^7.0.4" @@ -12266,7 +12102,7 @@ testem@^2.0.0: npmlog "^4.0.0" printf "^0.2.3" rimraf "^2.4.4" - socket.io "1.6.0" + socket.io "^2.1.0" spawn-args "^0.2.0" styled_string "0.0.1" tap-parser "^5.1.0" @@ -12281,8 +12117,8 @@ text-table@^0.2.0, text-table@~0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" textarea-caret@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/textarea-caret/-/textarea-caret-3.0.2.tgz#f360c48699aa1abf718680a43a31a850665c2caf" + version "3.1.0" + resolved "https://registry.yarnpkg.com/textarea-caret/-/textarea-caret-3.1.0.tgz#5d5a35bb035fd06b2ff0e25d5359e97f2655087f" textextensions@2: version "2.2.0" @@ -12311,7 +12147,7 @@ through2-filter@^2.0.0: through2 "~2.0.0" xtend "~4.0.0" -through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: +through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" dependencies: @@ -12346,13 +12182,6 @@ through2@~0.4.1: readable-stream "~1.0.17" xtend "~2.1.1" -through2@~0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" - dependencies: - readable-stream "~1.0.17" - xtend "~3.0.0" - through@2, "through@>=2.2.7 <3", through@X.X.X, through@^2.3.4, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -12386,14 +12215,14 @@ timers-browserify@^1.0.1: process "~0.11.0" timers-browserify@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" + version "2.0.6" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae" dependencies: setimmediate "^1.0.4" timers-ext@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.2.tgz#61cc47a76c1abd3195f14527f978d58ae94c5204" + version "0.1.5" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.5.tgz#77147dd4e76b660c2abb8785db96574cbbd12922" dependencies: es5-ext "~0.10.14" next-tick "1" @@ -12450,13 +12279,14 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" -to-regex@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" dependencies: - define-property "^0.2.5" - extend-shallow "^2.0.1" - regex-not "^1.0.0" + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" to-through@^2.0.0: version "2.0.0" @@ -12469,8 +12299,8 @@ toggle-selection@^1.0.3: resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1" @@ -12485,8 +12315,8 @@ traverse@~0.6.3: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" treeify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.0.1.tgz#69b3cd022022a168424e7cfa1ced44c939d3eb2f" + version "1.1.0" + resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" trim-newlines@^1.0.0: version "1.0.0" @@ -12529,11 +12359,11 @@ tsscmp@~1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" -tty-browserify@0.0.0, tty-browserify@~0.0.0: +tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" -tty-browserify@0.0.1: +tty-browserify@0.0.1, tty-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" @@ -12566,15 +12396,15 @@ type-detect@^1.0.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.5.tgz#d70e5bc81db6de2a381bcaca0c6e0cbdc7635de2" + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" -type-is@~1.6.10, type-is@~1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" +type-is@~1.6.10, type-is@~1.6.15, type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" dependencies: media-typer "0.3.0" - mime-types "~2.1.15" + mime-types "~2.1.18" typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" @@ -12584,14 +12414,7 @@ ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" -uglify-es@^3.0.15: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.3.tgz#095f5314d2a5d27e215390e50fa90751473dac2f" - dependencies: - commander "~2.12.1" - source-map "~0.6.1" - -uglify-es@^3.3.9: +uglify-es@^3.0.15, uglify-es@^3.3.9: version "3.3.10" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.10.tgz#8b0b7992cebe20edc26de1bf325cef797b8f3fa5" dependencies: @@ -12608,10 +12431,10 @@ uglify-js@^2.6, uglify-js@^2.8.27: uglify-to-browserify "~1.0.0" uglify-js@^3.0.5: - version "3.3.7" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.7.tgz#28463e7c7451f89061d2b235e30925bf5625e14d" + version "3.3.20" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.20.tgz#dc8bdee7d454c7d31dddc36f922d170bfcee3a0a" dependencies: - commander "~2.13.0" + commander "~2.15.0" source-map "~0.6.1" uglify-to-browserify@~1.0.0: @@ -12632,17 +12455,13 @@ uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" umd@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.1.tgz#8ae556e11011f63c2596708a8837259f01b3d60e" + version "3.0.3" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" unc-path-regex@^0.1.2: version "0.1.2" @@ -12739,7 +12558,7 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" -unist-util-visit@^1.1.0, unist-util-visit@^1.1.3: +unist-util-visit@^1.1.0, unist-util-visit@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.0.tgz#41ca7c82981fd1ce6c762aac397fc24e35711444" dependencies: @@ -12768,6 +12587,12 @@ upath@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d" +uri-js@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-3.0.2.tgz#f90b858507f81dea4dcfbb3c4c3dbfa2b557faaa" + dependencies: + punycode "^2.1.0" + urix@^0.1.0, urix@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -12795,19 +12620,17 @@ url@^0.11.0, url@~0.11.0: punycode "1.3.2" querystring "0.2.0" -use@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" +use@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" dependencies: - define-property "^0.2.5" - isobject "^3.0.0" - lazy-cache "^2.0.2" + kind-of "^6.0.2" useragent@^2.1.12: - version "2.2.1" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" + version "2.3.0" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" dependencies: - lru-cache "2.2.x" + lru-cache "4.1.x" tmp "0.0.x" utf8@^2.1.1: @@ -12844,8 +12667,8 @@ uuid@^2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" uuid@^3.0.0, uuid@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" uws@~9.14.0: version "9.14.0" @@ -12856,8 +12679,8 @@ v8-compile-cache@^1.1.2: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz#8d32e4f16974654657e676e0e467a348e89b0dc4" v8flags@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.0.1.tgz#dce8fc379c17d9f2c9e9ed78d89ce00052b1b76b" + version "3.0.2" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.0.2.tgz#ad6a78a20a6b23d03a8debc11211e3cc23149477" dependencies: homedir-polyfill "^1.0.1" @@ -12866,11 +12689,15 @@ valid-url@^1.0.9: resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +value-equal@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" value-or-function@^3.0.0: version "3.0.0" @@ -12930,10 +12757,9 @@ vinyl-file@^2.0.0: vinyl "^1.1.0" vinyl-fs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.1.tgz#74af5f6836a1cf414d35eeb3c10f2e65fc2a2c10" + version "3.0.2" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.2.tgz#1b86258844383f57581fcaac081fe09ef6d6d752" dependencies: - flush-write-stream "^1.0.0" fs-mkdirp-stream "^1.0.0" glob-stream "^6.1.0" graceful-fs "^4.0.0" @@ -12942,6 +12768,7 @@ vinyl-fs@^3.0.0: lead "^1.0.0" object.assign "^4.0.4" pumpify "^1.3.5" + readable-stream "^2.3.3" remove-bom-buffer "^3.0.0" remove-bom-stream "^1.2.0" resolve-options "^1.1.0" @@ -13003,6 +12830,10 @@ vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.1.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + vm-browserify@0.0.4, vm-browserify@~0.0.1: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -13037,11 +12868,11 @@ warning@^3.0.0: loose-envify "^1.0.0" watchify@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/watchify/-/watchify-3.9.0.tgz#f075fd2e8a86acde84cedba6e5c2a0bedd523d9e" + version "3.11.0" + resolved "https://registry.yarnpkg.com/watchify/-/watchify-3.11.0.tgz#03f1355c643955e7ab8dcbf399f624644221330f" dependencies: anymatch "^1.3.0" - browserify "^14.0.0" + browserify "^16.1.0" chokidar "^1.0.0" defined "^1.0.0" outpipe "^1.1.0" @@ -13049,12 +12880,12 @@ watchify@^3.9.0: xtend "^4.0.0" watchpack@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" + version "1.5.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.5.0.tgz#231e783af830a22f8966f65c4c4bacc814072eed" dependencies: - async "^2.1.2" - chokidar "^1.7.0" + chokidar "^2.0.2" graceful-fs "^4.1.2" + neo-async "^2.5.0" weak@^1.0.0: version "1.0.1" @@ -13063,31 +12894,7 @@ weak@^1.0.0: bindings "^1.2.1" nan "^2.0.5" -web3-provider-engine@^13.3.2: - version "13.4.0" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.4.0.tgz#78c2794ba926d0c5b94c6e8955abb994bb8e8854" - dependencies: - async "^2.5.0" - clone "^2.0.0" - eth-block-tracker "^2.2.2" - eth-sig-util "^1.3.0" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.1" - ethereumjs-vm "^2.0.2" - fetch-ponyfill "^4.0.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.67.0" - semaphore "^1.0.3" - solc "^0.4.2" - tape "^4.4.0" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-provider-engine@^13.8.0: +web3-provider-engine@^13.3.2, web3-provider-engine@^13.8.0: version "13.8.0" resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" dependencies: @@ -13128,8 +12935,8 @@ web3@^0.18.4: xmlhttprequest "*" web3@^0.20.1: - version "0.20.3" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.3.tgz#caa44373dc8815ac8767bddb6ba73073964caa8b" + version "0.20.6" + resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.6.tgz#3e97306ae024fb24e10a3d75c884302562215120" dependencies: bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" crypto-js "^3.1.4" @@ -13185,7 +12992,7 @@ webpack-sources@^1.0.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^2.2.1: +webpack@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.7.0.tgz#b2a1226804373ffd3d03ea9c6bd525067034f6b1" dependencies: @@ -13229,8 +13036,12 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: iconv-lite "0.4.19" whatwg-fetch@>=0.10.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + +whatwg-mimetype@^2.0.0, whatwg-mimetype@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" whatwg-url@^6.4.0: version "6.4.0" @@ -13333,13 +13144,6 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018" - dependencies: - options ">=0.0.5" - ultron "1.0.x" - ws@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" @@ -13355,10 +13159,6 @@ ws@~3.3.1: safe-buffer "~5.1.0" ultron "~1.1.0" -wtf-8@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" - x-is-function@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" @@ -13403,10 +13203,6 @@ xmldom@^0.1.19: version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" -xmlhttprequest-ssl@1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" - xmlhttprequest-ssl@~1.5.4: version "1.5.5" resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" @@ -13429,10 +13225,6 @@ xtend@~2.1.1, xtend@~2.1.2: dependencies: object-keys "~0.4.0" -xtend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" - y18n@^3.2.0, y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" @@ -13472,28 +13264,7 @@ yargs-parser@^9.0.2: dependencies: camelcase "^4.1.0" -yargs@^1.2.6: - version "1.3.3" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.3.3.tgz#054de8b61f22eefdb7207059eaef9d6b83fb931a" - -yargs@^10.0.3: - version "10.0.3" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.0.3.tgz#6542debd9080ad517ec5048fb454efe9e4d4aaae" - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^8.0.0" - -yargs@^11.0.0, yargs@^11.1.0: +yargs@11.1.0, yargs@^11.0.0, yargs@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" dependencies: @@ -13510,6 +13281,10 @@ yargs@^11.0.0, yargs@^11.1.0: y18n "^3.2.1" yargs-parser "^9.0.2" +yargs@^1.2.6: + version "1.3.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.3.3.tgz#054de8b61f22eefdb7207059eaef9d6b83fb931a" + yargs@^3.5.4: version "3.32.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" |