diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 3d2cd35bd096..017e38f9e162 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -11,6 +11,16 @@ "exposeDescription": { "message": "Expose accounts to the current website. Useful for legacy dapps." }, + "external": { + "message": "External" + }, + "externalAcc": { + "message": "External Account", + "description": "select this for entering external account without password" + }, + "externalAccountMsg": { + "message": "External accounts will not be associated with your originally created MetaMask account seedphrase. When you want to confirm a transaction with external account, Metamask will provide transaction details and expects a valid signature from external signer app." + }, "confirmExpose": { "message": "Are you sure you want to expose your accounts to the current website?" }, @@ -753,6 +763,15 @@ "invalidSeedPhrase": { "message": "Invalid seed phrase" }, + "invalidSignature": { + "message": "Invalid signature" + }, + "invalidSignatureLength": { + "message": "Length should be 130 chars." + }, + "invalidSignatureChar": { + "message": "Invalid character in signature." + }, "jsonFail": { "message": "Something went wrong. Please make sure your JSON file is properly formatted." }, @@ -1039,6 +1058,10 @@ "message": "Paste your private key string here:", "description": "For importing an account from a private key" }, + "pasteExternalAccount": { + "message": "Paste your external account address here:", + "description": "For importing an external account from account number" + }, "pasteSeed": { "message": "Paste your seed phrase here!" }, @@ -1097,6 +1120,9 @@ "recipientAddress": { "message": "Recipient Address" }, + "signature": { + "message": "Signature" + }, "refundAddress": { "message": "Your Refund Address" }, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 653868066374..27964a5c1b26 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -158,7 +158,10 @@ module.exports = class MetamaskController extends EventEmitter { }) // key mgmt - const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring] + const additionalKeyrings = [ + TrezorKeyring, + LedgerBridgeKeyring, + ] this.keyringController = new KeyringController({ keyringTypes: additionalKeyrings, initState: initState.KeyringController, @@ -407,6 +410,7 @@ module.exports = class MetamaskController extends EventEmitter { resetAccount: nodeify(this.resetAccount, this), removeAccount: nodeify(this.removeAccount, this), importAccountWithStrategy: nodeify(this.importAccountWithStrategy, this), + addExtAccount: nodeify(this.addExtAccount, this), // hardware wallets connectHardware: nodeify(this.connectHardware, this), @@ -451,6 +455,7 @@ module.exports = class MetamaskController extends EventEmitter { createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this), addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController), exportAccount: nodeify(keyringController.exportAccount, keyringController), + updateExternalSign: nodeify(keyringController.updateExternalSign, keyringController), // txController cancelTransaction: nodeify(txController.cancelTransaction, txController), @@ -944,6 +949,23 @@ module.exports = class MetamaskController extends EventEmitter { await this.preferencesController.setSelectedAddress(accounts[0]) } + /** + * Creates and external account and adds it to a newly created + * ExternalAccountKeyring. + * + * @param {string} address - A valid Ethereum address string. + */ + async addExtAccount (address) { + if (!ethUtil.isValidAddress(address)) throw new Error('Address is invalid.') + const keyring = await this.keyringController.addNewKeyring('External Account', [ address ]) + const accounts = await keyring.getAccounts() + // update accounts in preferences controller + const allAccounts = await this.keyringController.getAccounts() + this.preferencesController.setAddresses(allAccounts) + // set new account as selected + await this.preferencesController.setSelectedAddress(accounts[0]) + } + // --------------------------------------------------------------------------- // Identity Management (signature operations) diff --git a/package-lock.json b/package-lock.json index b10935026479..e29142b934e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -823,7 +823,7 @@ }, "autoprefixer": { "version": "7.2.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", + "resolved": "http://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", "dev": true, "requires": { @@ -1165,7 +1165,7 @@ }, "style-loader": { "version": "0.20.3", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz", + "resolved": "http://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz", "integrity": "sha512-2I7AVP73MvK33U7B9TKlYZAqdROyMXDYSMvHLX43qy3GCOaJNiV6i0v/sv9idWIaQ42Yn2dNv79Q5mKXbKhAZg==", "dev": true, "requires": { @@ -1310,7 +1310,7 @@ }, "@storybook/podda": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@storybook/podda/-/podda-1.2.3.tgz", + "resolved": "http://registry.npmjs.org/@storybook/podda/-/podda-1.2.3.tgz", "integrity": "sha512-g7dsdsn50AhlGZ8iIDKdF8bi7Am++iFOq+QN+hNKz3FvgLuf8Dz+mpC/BFl90eE9bEYxXqXKeMf87399Ec5Qhw==", "dev": true, "requires": { @@ -1674,7 +1674,7 @@ "dependencies": { "hoist-non-react-statics": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=", "dev": true } @@ -1694,7 +1694,7 @@ "dependencies": { "hoist-non-react-statics": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=", "dev": true } @@ -1920,7 +1920,7 @@ }, "acorn-jsx": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { @@ -1929,7 +1929,7 @@ "dependencies": { "acorn": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", "dev": true } @@ -2685,7 +2685,7 @@ }, "adjust-sourcemap-loader": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz", "integrity": "sha512-958oaHHVEXMvsY7v7cC5gEkNIcoaAVIhZ4mBReYVZJOTP9IgKmzLjIOhTtzpLMu+qriXvLsVjJ155EeInp45IQ==", "dev": true, "requires": { @@ -3648,7 +3648,7 @@ }, "babel-helper-is-nodes-equiv": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "resolved": "http://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", "dev": true }, @@ -3897,7 +3897,7 @@ }, "babel-plugin-react-docgen": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-1.9.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-1.9.0.tgz", "integrity": "sha512-8lQ73p4BL+xcgba03NTiHrddl2X8J6PDMQHPpz73sesrRBf6JtAscQPLIjFWQR/abLokdv81HdshpjYGppOXgA==", "dev": true, "requires": { @@ -3908,77 +3908,77 @@ }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", "dev": true }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", "dev": true }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", "dev": true }, "babel-plugin-syntax-decorators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", "dev": true }, "babel-plugin-syntax-do-expressions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", "dev": true }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", "dev": true }, "babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", "dev": true }, "babel-plugin-syntax-function-bind": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", "dev": true }, "babel-plugin-syntax-jsx": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", "dev": true }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, @@ -4796,7 +4796,7 @@ }, "base-x": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", "integrity": "sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w=" }, "base62": { @@ -5359,7 +5359,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "requires": { "bn.js": "^4.1.0", @@ -5443,7 +5443,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" @@ -5524,7 +5523,7 @@ }, "cacache": { "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "resolved": "http://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", "dev": true, "requires": { @@ -5620,7 +5619,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { @@ -5734,7 +5733,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -6176,7 +6175,7 @@ }, "color": { "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "resolved": "http://registry.npmjs.org/color/-/color-0.11.4.tgz", "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "requires": { "clone": "^1.0.2", @@ -6289,7 +6288,7 @@ }, "yargs": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", "dev": true } @@ -6834,7 +6833,7 @@ }, "css-in-js-utils": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz", "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==", "dev": true, "requires": { @@ -6852,7 +6851,7 @@ }, "css-loader": { "version": "0.28.11", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", + "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", "dev": true, "requires": { @@ -6938,7 +6937,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -6968,7 +6967,7 @@ }, "css-select": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dev": true, "requires": { @@ -7020,7 +7019,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -7060,7 +7059,7 @@ }, "cssnano": { "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "resolved": "http://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "dev": true, "requires": { @@ -7234,7 +7233,7 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "requires": { "es5-ext": "^0.10.9" @@ -7748,7 +7747,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -8386,7 +8385,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -8438,7 +8437,7 @@ }, "yargs": { "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "dev": true, "requires": { @@ -8499,7 +8498,7 @@ "dependencies": { "domelementtype": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", "dev": true } @@ -8562,7 +8561,7 @@ }, "dotenv": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", + "resolved": "http://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==", "dev": true }, @@ -8587,7 +8586,7 @@ }, "duplexer": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" }, "duplexer2": { @@ -8607,7 +8606,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -9077,7 +9076,7 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "requires": { "es6-promise": "^4.0.3" @@ -9342,7 +9341,7 @@ }, "ansi-escapes": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, @@ -9449,7 +9448,7 @@ }, "progress": { "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, @@ -9491,7 +9490,7 @@ }, "slice-ansi": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true }, @@ -9697,7 +9696,7 @@ }, "eth-json-rpc-middleware": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", + "resolved": "http://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", "requires": { "async": "^2.5.0", @@ -9781,6 +9780,33 @@ } } }, + "eth-external-account-keyring": { + "version": "github:r001/eth-external-account-keyring#807da82ce472594bbb5c33125a85d89c729ebc7a", + "from": "github:r001/eth-external-account-keyring#v1.0.0", + "requires": { + "eth-sig-util": "^2.0.2", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "^5.1.1", + "events": "^1.1.1", + "xtend": "^4.0.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + } + } + }, "eth-hd-keyring": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/eth-hd-keyring/-/eth-hd-keyring-1.2.2.tgz", @@ -9973,7 +9999,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -9982,7 +10008,7 @@ }, "eth-json-rpc-middleware": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", + "resolved": "http://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", "requires": { "async": "^2.5.0", @@ -10147,16 +10173,15 @@ } }, "eth-keyring-controller": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-3.3.1.tgz", - "integrity": "sha512-Knz3alRHjgJ+/4LUBxXLApXeuoMsehaLOvVHpalSTkU//YPXBjvaITlc6653n+g1vvJ4sD2VbMNfFmYYyFHEtw==", + "version": "github:r001/KeyringController#9a2bdcd030b0fed5fa28b9eac3949c35698cf00f", + "from": "github:r001/KeyringController#9a2bdcd030b0fed5fa28b9eac3949c35698cf00f", "requires": { "bip39": "^2.4.0", "bluebird": "^3.5.0", "browser-passworder": "^2.0.3", - "eth-hd-keyring": "^1.2.2", + "eth-hd-keyring": "^2.0.0", "eth-sig-util": "^1.4.0", - "eth-simple-keyring": "^1.3.0", + "eth-simple-keyring": "^2.0.0", "ethereumjs-util": "^5.1.2", "loglevel": "^1.5.0", "obs-store": "^2.4.1", @@ -10165,13 +10190,42 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", "object-assign": "^4.0.0" } }, + "eth-hd-keyring": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eth-hd-keyring/-/eth-hd-keyring-2.0.0.tgz", + "integrity": "sha512-lTeANNPNj/j08sWU7LUQZTsx9NUJaUsiOdVxeP0UI5kke7L+Sd7zJWBmCShudEVG8PkqKLE1KJo08o430sl6rw==", + "requires": { + "bip39": "^2.2.0", + "eth-sig-util": "^2.0.1", + "ethereumjs-abi": "^0.6.5", + "ethereumjs-util": "^5.1.1", + "ethereumjs-wallet": "^0.6.0", + "events": "^1.1.1", + "xtend": "^4.0.1" + }, + "dependencies": { + "eth-sig-util": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.1.0.tgz", + "integrity": "sha512-JRKmq1zytYoOuAj8llYiGlRGSlWrQ0jGGh9+YPhELfmMP1PD/dkwq2kzMoB8pRF6sEgZojQfSasswto3xsKFvw==", + "requires": { + "buffer": "^5.2.1", + "elliptic": "^6.4.0", + "ethereumjs-abi": "0.6.5", + "ethereumjs-util": "^5.1.1", + "tweetnacl": "^1.0.0", + "tweetnacl-util": "^0.15.0" + } + } + } + }, "eth-sig-util": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", @@ -10183,7 +10237,7 @@ "dependencies": { "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", + "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { "bn.js": "^4.10.0", "ethereumjs-util": "^5.0.0" @@ -10224,6 +10278,11 @@ "through2": "^2.0.3", "xtend": "^4.0.1" } + }, + "tweetnacl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz", + "integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins=" } } }, @@ -10456,11 +10515,12 @@ } }, "eth-simple-keyring": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eth-simple-keyring/-/eth-simple-keyring-1.3.1.tgz", - "integrity": "sha512-oOASghMej6WO+bjFF+/8bT2DU7D9QKgD81BbS+/qd26z25ueATcgwPNP2LrkoWUbe39OVVM4P5A4fTEEZpGAHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eth-simple-keyring/-/eth-simple-keyring-2.0.0.tgz", + "integrity": "sha512-4dMbkIy2k1qotDTjWINvXG+7tBmofp0YUhlXgcG0+I3w684V46+MAHEkBtD2Y09iEeIB07RDXrezKP9WxOpynA==", "requires": { - "eth-sig-util": "^1.4.2", + "eth-sig-util": "^2.0.1", + "ethereumjs-abi": "^0.6.5", "ethereumjs-util": "^5.1.1", "ethereumjs-wallet": "^0.6.0", "events": "^1.1.1", @@ -10526,7 +10586,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -10658,7 +10718,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -10955,7 +11015,7 @@ "dependencies": { "ethereumjs-util": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", "requires": { "bn.js": "^4.8.0", @@ -11085,7 +11145,7 @@ "dependencies": { "ethereumjs-util": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", "requires": { "bn.js": "^4.8.0", @@ -11098,9 +11158,8 @@ } }, "ethereumjs-wallet": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz", - "integrity": "sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s=", + "version": "github:r001/ethereumjs-wallet#4e35d91bd8b563f06c926b045f60371077e15d82", + "from": "github:r001/ethereumjs-wallet#4e35d91bd8b563f06c926b045f60371077e15d82", "requires": { "aes-js": "^0.2.3", "bs58check": "^1.0.8", @@ -11508,7 +11567,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -11989,7 +12048,7 @@ "dependencies": { "core-js": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" } } @@ -12051,7 +12110,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { @@ -12550,7 +12609,7 @@ "dependencies": { "async": { "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", "dev": true }, @@ -12918,7 +12977,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -13807,7 +13866,7 @@ }, "babelify": { "version": "7.3.0", - "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "dev": true, "requires": { @@ -14880,7 +14939,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -15177,7 +15236,7 @@ }, "ethereumjs-block": { "version": "1.2.2", - "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.2.2.tgz", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.2.2.tgz", "integrity": "sha1-LsdTSlkCG47JuDww5JaQxuuu3aE=", "dev": true, "requires": { @@ -15190,13 +15249,13 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "ethereumjs-util": { "version": "4.5.0", - "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", "dev": true, "requires": { @@ -15275,7 +15334,7 @@ }, "ethereumjs-block": { "version": "1.7.1", - "resolved": "http://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", "dev": true, "requires": { @@ -16722,7 +16781,7 @@ }, "node-fetch": { "version": "2.1.2", - "resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", "dev": true }, @@ -17635,7 +17694,7 @@ "dependencies": { "fs-extra": { "version": "0.30.0", - "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true, "requires": { @@ -18625,7 +18684,7 @@ }, "whatwg-fetch": { "version": "2.0.4", - "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", "dev": true }, @@ -18754,7 +18813,7 @@ }, "yargs-parser": { "version": "2.4.1", - "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "dev": true, "requires": { @@ -18820,7 +18879,7 @@ "dependencies": { "bluebird": { "version": "3.4.6", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz", "integrity": "sha1-AdqNgh2HgT0ViWfnQ9X+bGLPjA8=", "dev": true }, @@ -18891,7 +18950,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -18957,7 +19016,7 @@ }, "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -18996,7 +19055,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -19072,13 +19131,13 @@ "dependencies": { "minimist": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", "dev": true }, "yargs": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", "dev": true, "requires": { @@ -19596,7 +19655,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -20386,7 +20445,7 @@ }, "gulp-stylelint": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/gulp-stylelint/-/gulp-stylelint-7.0.0.tgz", + "resolved": "http://registry.npmjs.org/gulp-stylelint/-/gulp-stylelint-7.0.0.tgz", "integrity": "sha512-0PI+tNTzaJz5+qO3i9Jyd04ZPSb+NCN7bZ2GaIArvbQpuyJha9p3lpWxPG+XJtrVT42bIiyLeYKPnLe7uW4dQQ==", "dev": true, "requires": { @@ -21267,7 +21326,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true } @@ -21491,7 +21550,7 @@ }, "htmlescape": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true }, @@ -21589,7 +21648,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -21749,7 +21808,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -22228,7 +22287,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "requires": { "builtin-modules": "^1.0.0" @@ -22415,7 +22474,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -23044,13 +23103,13 @@ }, "entities": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/entities/-/entities-1.0.0.tgz", "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", "dev": true }, "htmlparser2": { "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", "dev": true, "requires": { @@ -23069,7 +23128,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -23275,7 +23334,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -23330,12 +23389,12 @@ }, "json5": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "requires": { "graceful-fs": "^4.1.6" @@ -23355,7 +23414,7 @@ "dependencies": { "JSONStream": { "version": "0.8.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "resolved": "http://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", "dev": true, "requires": { @@ -23377,7 +23436,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -23591,19 +23650,19 @@ "dependencies": { "core-js": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", "dev": true }, "es6-promise": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", "dev": true }, "readable-stream": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { @@ -24116,7 +24175,7 @@ }, "kew": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "resolved": "http://registry.npmjs.org/kew/-/kew-0.7.0.tgz", "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", "dev": true }, @@ -24233,7 +24292,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -24291,7 +24350,7 @@ }, "level-iterator-stream": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "resolved": "http://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", "requires": { "inherits": "^2.0.1", @@ -24307,7 +24366,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -24344,7 +24403,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "requires": { "core-util-is": "~1.0.0", @@ -24437,7 +24496,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -24449,7 +24508,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -24941,7 +25000,7 @@ }, "magic-string": { "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "resolved": "http://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", "dev": true, "requires": { @@ -25060,7 +25119,7 @@ }, "marked": { "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "dev": true }, @@ -25443,7 +25502,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { @@ -25510,7 +25569,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { @@ -25565,7 +25624,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "ethereumjs-util": { @@ -25612,7 +25671,7 @@ }, "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -25730,7 +25789,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pump": { @@ -25980,7 +26039,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -26345,7 +26404,7 @@ "dependencies": { "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -26380,7 +26439,7 @@ }, "ncp": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=", "dev": true }, @@ -26431,7 +26490,7 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, @@ -26565,7 +26624,7 @@ "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } @@ -26603,7 +26662,7 @@ "dependencies": { "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "requires": { "base64-js": "^1.0.2", @@ -27021,7 +27080,7 @@ }, "caching-transform": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", + "resolved": false, "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", "dev": true, "requires": { @@ -27032,7 +27091,7 @@ "dependencies": { "md5-hex": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", + "resolved": false, "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", "dev": true, "requires": { @@ -27100,7 +27159,7 @@ }, "convert-source-map": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "resolved": false, "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, @@ -27146,7 +27205,7 @@ "dependencies": { "strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "resolved": false, "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } @@ -27154,7 +27213,7 @@ }, "error-ex": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "resolved": false, "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { @@ -27191,7 +27250,7 @@ }, "find-cache-dir": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "resolved": false, "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", "dev": true, "requires": { @@ -27202,7 +27261,7 @@ }, "find-up": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "resolved": false, "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { @@ -27227,7 +27286,7 @@ }, "get-caller-file": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "resolved": false, "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, @@ -27239,7 +27298,7 @@ }, "glob": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "resolved": false, "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { @@ -27288,7 +27347,7 @@ }, "hosted-git-info": { "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "resolved": false, "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, @@ -27361,13 +27420,13 @@ }, "istanbul-lib-coverage": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz", + "resolved": false, "integrity": "sha512-yMSw5xLIbdaxiVXHk3amfNM2WeBxLrwH/BCyZ9HvA/fylwziAIJOG2rKqWyLqEJqwKT725vxxqidv+SyynnGAA==", "dev": true }, "istanbul-lib-hook": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.0.tgz", + "resolved": false, "integrity": "sha512-qm3dt628HKpCVtIjbdZLuQyXn0+LO8qz+YHQDfkeXuSk5D+p299SEV5DrnUUnPi2SXvdMmWapMYWiuE75o2rUQ==", "dev": true, "requires": { @@ -27376,7 +27435,7 @@ }, "istanbul-lib-report": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.0.tgz", + "resolved": false, "integrity": "sha512-RiELmy9oIRYUv36ITOAhVum9PUvuj6bjyXVEKEHNiD1me6qXtxfx7vSEJWnjOGk2QmYw/GRFjLXWJv3qHpLceQ==", "dev": true, "requires": { @@ -27387,7 +27446,7 @@ }, "istanbul-lib-source-maps": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.0.tgz", + "resolved": false, "integrity": "sha512-jenUeC0gMSSMGkvqD9xuNfs3nD7XWeXLhqaIkqHsNZ3DJBWPdlKEydE7Ya5aTgdWjrEQhrCYTv+J606cGC2vuQ==", "dev": true, "requires": { @@ -27408,7 +27467,7 @@ }, "istanbul-reports": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.0.tgz", + "resolved": false, "integrity": "sha512-HeZG0WHretI9FXBni5wZ9DOgNziqDCEwetxnme5k1Vv5e81uTqcsy3fMH99gXGDGKr1ea87TyGseDMa2h4HEUA==", "dev": true, "requires": { @@ -27448,7 +27507,7 @@ }, "locate-path": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "resolved": false, "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { @@ -27458,7 +27517,7 @@ "dependencies": { "path-exists": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "resolved": false, "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } @@ -27491,7 +27550,7 @@ "dependencies": { "pify": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "resolved": false, "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } @@ -27555,7 +27614,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, @@ -27645,7 +27704,7 @@ }, "p-limit": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, "requires": { @@ -27654,7 +27713,7 @@ }, "p-locate": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "resolved": false, "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { @@ -27663,7 +27722,7 @@ }, "p-try": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "resolved": false, "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, @@ -27681,7 +27740,7 @@ }, "pkg-dir": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "resolved": false, "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { @@ -27772,7 +27831,7 @@ }, "slide": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "resolved": false, "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, @@ -27865,7 +27924,7 @@ }, "test-exclude": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.2.tgz", + "resolved": false, "integrity": "sha512-2kTGf+3tykCfrWVREgyTR0bmVO0afE6i7zVXi/m+bZZ8ujV89Aulxdcdv32yH+unVFg3Y5o6GA8IzsHnGQuFgQ==", "dev": true, "requires": { @@ -27877,7 +27936,7 @@ "dependencies": { "load-json-file": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "resolved": false, "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { @@ -27889,7 +27948,7 @@ }, "parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "resolved": false, "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { @@ -27899,7 +27958,7 @@ }, "path-type": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "resolved": false, "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { @@ -27908,13 +27967,13 @@ }, "pify": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "resolved": false, "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "read-pkg": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "resolved": false, "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { @@ -27925,7 +27984,7 @@ }, "read-pkg-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "resolved": false, "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { @@ -27935,7 +27994,7 @@ }, "strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "resolved": false, "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } @@ -28068,7 +28127,7 @@ }, "write-file-atomic": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "resolved": false, "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { @@ -28111,7 +28170,7 @@ "dependencies": { "camelcase": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "resolved": false, "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, @@ -28128,7 +28187,7 @@ }, "yargs-parser": { "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "resolved": false, "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { @@ -28443,7 +28502,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -28569,7 +28628,7 @@ }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { "lcid": "^1.0.0" @@ -28932,7 +28991,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -28945,7 +29004,7 @@ }, "pause-stream": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { @@ -29276,7 +29335,7 @@ }, "through2": { "version": "0.2.3", - "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", "dev": true, "requires": { @@ -29440,7 +29499,7 @@ }, "postcss-calc": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "resolved": "http://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { @@ -29577,7 +29636,7 @@ }, "postcss-discard-comments": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "resolved": "http://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { @@ -29665,7 +29724,7 @@ }, "postcss-discard-empty": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { @@ -29709,7 +29768,7 @@ }, "postcss-discard-overridden": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { @@ -29753,7 +29812,7 @@ }, "postcss-discard-unused": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "resolved": "http://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { @@ -29851,7 +29910,7 @@ }, "postcss-less": { "version": "0.14.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-0.14.0.tgz", + "resolved": "http://registry.npmjs.org/postcss-less/-/postcss-less-0.14.0.tgz", "integrity": "sha1-xjGwicbM5CK5oQ86lY0r7dOBkyQ=", "dev": true, "requires": { @@ -29958,7 +30017,7 @@ }, "postcss-merge-idents": { "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "resolved": "http://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { @@ -30112,7 +30171,7 @@ }, "postcss-minify-font-values": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "resolved": "http://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { @@ -30158,7 +30217,7 @@ }, "postcss-minify-gradients": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "resolved": "http://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { @@ -30203,7 +30262,7 @@ }, "postcss-minify-params": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "resolved": "http://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { @@ -30250,7 +30309,7 @@ }, "postcss-minify-selectors": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "resolved": "http://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { @@ -30336,7 +30395,7 @@ }, "postcss-normalize-charset": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { @@ -30380,7 +30439,7 @@ }, "postcss-normalize-url": { "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "resolved": "http://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { @@ -30509,7 +30568,7 @@ }, "postcss-reduce-idents": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "resolved": "http://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { @@ -30554,7 +30613,7 @@ }, "postcss-reduce-initial": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { @@ -30598,7 +30657,7 @@ }, "postcss-reduce-transforms": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "resolved": "http://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { @@ -30805,7 +30864,7 @@ }, "postcss-svgo": { "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "resolved": "http://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { @@ -30852,7 +30911,7 @@ }, "postcss-unique-selectors": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "resolved": "http://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { @@ -30904,7 +30963,7 @@ }, "postcss-zindex": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { @@ -30996,7 +31055,7 @@ }, "pretty-hrtime": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, @@ -31314,6 +31373,24 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.1.tgz", "integrity": "sha512-KOdSAyFBPf0/5Z3mra4JfSbjrDlUn2J3YH8Rm33tRGbptxP4vhogLWysvkQp8mp5ix9u80Wfr4vxHXTeR9o0Ug==" + "qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=" + }, + "qrcode-npm": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/qrcode-npm/-/qrcode-npm-0.0.3.tgz", + "integrity": "sha1-d+5vvvqcDyn6CdTRUggHxqYEK5o=" + }, + "qrcode.react": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-0.7.2.tgz", + "integrity": "sha512-s1x+E3bsp0ojI8cHQ+czr+aG3huLZegH+tqAuRsXh6oXvzNfC+9L2PeFRBBu8eRBiejMRrRzSH7iwi5LDyWfRg==", + "requires": { + "prop-types": "^15.5.8", + "qr.js": "0.0.0" + } }, "qs": { "version": "6.5.1", @@ -31353,7 +31430,7 @@ "dependencies": { "chokidar": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz", + "resolved": "http://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz", "integrity": "sha1-L0RHq16W5Q+z14n9kNTHLg5McMI=", "dev": true, "requires": { @@ -31370,7 +31447,7 @@ }, "commander": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { @@ -31495,7 +31572,7 @@ "dependencies": { "inline-style-prefixer": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz", + "resolved": "http://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz", "integrity": "sha1-wVPH6I/YT+9cYC6VqBaLJ3BnH+c=", "dev": true, "requires": { @@ -32396,7 +32473,7 @@ }, "reduce-css-calc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "resolved": "http://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { @@ -32523,7 +32600,7 @@ }, "regexpp": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", "dev": true }, @@ -32539,7 +32616,7 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { @@ -33008,7 +33085,7 @@ "dependencies": { "convert-source-map": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", "dev": true } @@ -33162,7 +33239,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -33189,7 +33266,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -33587,7 +33664,7 @@ }, "shasum": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", "dev": true, "requires": { @@ -34712,7 +34789,7 @@ }, "yargs": { "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "requires": { "cliui": "^3.2.0", @@ -34733,7 +34810,7 @@ }, "yargs-parser": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "requires": { "camelcase": "^3.0.0", @@ -34834,7 +34911,7 @@ }, "split": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "resolved": "http://registry.npmjs.org/split/-/split-0.3.3.tgz", "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { @@ -34888,7 +34965,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -35104,7 +35181,7 @@ "dependencies": { "ansi-regex": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "resolved": "http://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", "dev": true }, @@ -35116,7 +35193,7 @@ }, "chalk": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", "dev": true, "requires": { @@ -35138,7 +35215,7 @@ }, "strip-ansi": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { @@ -35395,7 +35472,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -35436,7 +35513,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -35826,7 +35903,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -36184,7 +36261,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -36209,7 +36286,7 @@ "dependencies": { "babelify": { "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "resolved": "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", "requires": { "babel-core": "^6.0.14", @@ -36254,7 +36331,7 @@ "dependencies": { "css-color-names": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.3.tgz", + "resolved": "http://registry.npmjs.org/css-color-names/-/css-color-names-0.0.3.tgz", "integrity": "sha1-3gzvFvTYqoIioyDVttfpu62nufY=", "dev": true } @@ -36556,7 +36633,7 @@ }, "text-encoding": { "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=" }, "text-table": { @@ -36631,7 +36708,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { @@ -37078,6 +37155,11 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "optional": true }, + "tweetnacl-util": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz", + "integrity": "sha1-RXbBzuXi1j0gf+5S8boCgZSAvHU=" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -37159,7 +37241,7 @@ }, "yargs": { "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { @@ -37690,7 +37772,7 @@ }, "utf8": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", + "resolved": "http://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" }, "util": { @@ -37735,7 +37817,7 @@ "dependencies": { "async": { "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz", "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", "dev": true }, @@ -37754,7 +37836,7 @@ }, "uuid": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" }, "v8flags": { @@ -37919,7 +38001,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, @@ -38413,7 +38495,7 @@ "dependencies": { "async": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz", "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=", "dev": true }, @@ -38458,7 +38540,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", @@ -38557,7 +38639,7 @@ }, "xmlbuilder": { "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, @@ -38606,7 +38688,7 @@ }, "yargs": { "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", "requires": { "camelcase": "^3.0.0", @@ -38626,7 +38708,7 @@ }, "yargs-parser": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", "requires": { "camelcase": "^3.0.0" diff --git a/package.json b/package.json index e2f6ff0d1560..416db71b141a 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,9 @@ "eth-hd-keyring": "^1.2.2", "eth-json-rpc-filters": "^3.0.1", "eth-json-rpc-infura": "^3.0.0", - "eth-keyring-controller": "^3.3.1", "eth-ledger-bridge-keyring": "^0.1.1", + "eth-keyring-controller": "github:r001/KeyringController#9a2bdcd030b0fed5fa28b9eac3949c35698cf00f", + "eth-external-account-keyring": "github:r001/eth-external-account-keyring#v1.0.0", "eth-method-registry": "^1.0.0", "eth-phishing-detect": "^1.1.4", "eth-query": "^2.1.2", @@ -124,7 +125,7 @@ "ethereumjs-abi": "^0.6.4", "ethereumjs-tx": "^1.3.0", "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", - "ethereumjs-wallet": "^0.6.0", + "ethereumjs-wallet": "github:r001/ethereumjs-wallet#4e35d91bd8b563f06c926b045f60371077e15d82", "etherscan-link": "^1.0.2", "ethjs": "^0.4.0", "ethjs-contract": "^0.2.3", @@ -176,6 +177,8 @@ "pump": "^3.0.0", "pumpify": "^1.3.4", "qrcode-generator": "1.4.1", + "qrcode-npm": "0.0.3", + "qrcode.react": "0.7.2", "ramda": "^0.24.1", "react": "^15.6.2", "react-addons-css-transition-group": "^15.6.0", diff --git a/ui/app/actions.js b/ui/app/actions.js index d8363eba6b21..8f29c9d4ddf2 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -90,6 +90,7 @@ var actions = { unlockAndGetSeedPhrase, addNewKeyring, importNewAccount, + addExternalAccount, addNewAccount, connectHardware, checkHardwareStatus, @@ -181,6 +182,7 @@ var actions = { VIEW_PENDING_TX: 'VIEW_PENDING_TX', updateTransactionParams, UPDATE_TRANSACTION_PARAMS: 'UPDATE_TRANSACTION_PARAMS', + updateSignature: updateSignature, // send screen UPDATE_GAS_LIMIT: 'UPDATE_GAS_LIMIT', UPDATE_GAS_PRICE: 'UPDATE_GAS_PRICE', @@ -353,9 +355,9 @@ var actions = { approveProviderRequest, rejectProviderRequest, clearApprovedOrigins, - setFirstTimeFlowType, SET_FIRST_TIME_FLOW_TYPE: 'SET_FIRST_TIME_FLOW_TYPE', + updateExternalSign, } module.exports = actions @@ -712,6 +714,32 @@ function addNewKeyring (type, opts) { } } +function addExternalAccount (address) { + return async (dispatch) => { + let newState + dispatch(actions.showLoadingIndication('This may take a while, please be patient.')) + try { + log.debug(`background.addExtAccount`) + await pify(background.addExtAccount).call(background, address) + log.debug(`background.getState`) + newState = await pify(background.getState).call(background) + } catch (err) { + dispatch(actions.hideLoadingIndication()) + dispatch(actions.displayWarning(err.message)) + throw err + } + dispatch(actions.hideLoadingIndication()) + dispatch(actions.updateMetamaskState(newState)) + if (newState.selectedAddress) { + dispatch({ + type: actions.SHOW_ACCOUNT_DETAIL, + value: newState.selectedAddress, + }) + } + return newState + } +} + function importNewAccount (strategy, args) { return async (dispatch) => { let newState @@ -854,7 +882,7 @@ function showInfoPage () { } } -function showQrScanner (ROUTE) { +function showQrScanner (ROUTE, props = {}) { return (dispatch, getState) => { return WebcamUtils.checkStatus() .then(status => { @@ -862,8 +890,10 @@ function showQrScanner (ROUTE) { // We need to switch to fullscreen mode to ask for permission global.platform.openExtensionInBrowser(`${ROUTE}`, `scan=true`) } else { + props.route = ROUTE dispatch(actions.showModal({ name: 'QR_SCANNER', + ...props, })) } }).catch(e => { @@ -871,6 +901,7 @@ function showQrScanner (ROUTE) { name: 'QR_SCANNER', error: true, errorType: e.type, + ...props, })) }) } @@ -1282,6 +1313,13 @@ function updateTransactionParams (id, txParams) { } } +function updateSignature(newSignature) { + return { + type: actions.UPDATE_SIGNATURE, + value: newSignature, + } +} + function txError (err) { return { type: actions.TRANSACTION_ERROR, @@ -2759,3 +2797,8 @@ function setFirstTimeFlowType (type) { }) } } +function updateExternalSign (payload) { +return (dispatch) => { + background.updateExternalSign(payload) + } +} diff --git a/ui/app/components/modals/external-sign-modal/external-sign-modal-container.js b/ui/app/components/modals/external-sign-modal/external-sign-modal-container.js new file mode 100644 index 000000000000..897f33e1c4bc --- /dev/null +++ b/ui/app/components/modals/external-sign-modal/external-sign-modal-container.js @@ -0,0 +1,49 @@ +const Component = require('react').Component +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../../actions') +const { getSelectedIdentity } = require('../../../selectors') + +function mapStateToProps (state, ownProps) { + return { + selectedIdentity: ownProps.selectedIdentity || getSelectedIdentity(state), + } +} + +function mapDispatchToProps (dispatch) { + return {} +} + +inherits(ExternalSignModalContainer, Component) +function ExternalSignModalContainer () { + Component.call(this) +} + +ExternalSignModalContainer.contextTypes = { + t: PropTypes.func, +} + +export default connect(mapStateToProps, mapDispatchToProps)(ExternalSignModalContainer) + + +ExternalSignModalContainer.prototype.render = function () { + let { children } = this.props + + if (children.constructor !== Array) { + children = [children] + } + + return h('div', { style: { borderRadius: '4px' }}, [ + h('div.account-modal-container', [ + + h('div.account-modal-close', { + onClick: this.props.hideModal, + }), + + ...children, + + ]), + ]) +} diff --git a/ui/app/components/modals/external-sign-modal/external-sign-modal.js b/ui/app/components/modals/external-sign-modal/external-sign-modal.js new file mode 100644 index 000000000000..f0ff09806d2c --- /dev/null +++ b/ui/app/components/modals/external-sign-modal/external-sign-modal.js @@ -0,0 +1,347 @@ +import React, { PureComponent } from 'react' +import ExternalSignModalContainer from './external-sign-modal-container' +import QrView from '../../qr-code' +import SendRowWrapper from '../../send/send-content/send-row-wrapper' +import TxInput from './tx-input.js' +import PageContainerFooter from '../../page-container/page-container-footer' +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const connect = require('react-redux').connect +const ethUtil = require('ethereumjs-util') +const sigUtil = require('eth-sig-util') +const Transaction = require('ethereumjs-tx') +const extend = require('xtend') + +import { + updateSignature, +} from '../../../ducks/confirm-transaction.duck' +import { + showQrScanner, + qrCodeDetected, + hideModal, + updateExternalSign, + hideLoadingIndication, +} from '../../../actions' +import { CONFIRM_TRANSACTION_ROUTE } from '../../../routes' + +const mapStateToProps = (state, ownProps) => { + const { confirmTransaction } = state + const { + txData, + signature, + } = confirmTransaction + const qrCodeData = state.appState.qrCodeData + const props = state.appState.modal.modalState.props + const signable = props.signable + const qrTxData = reduce(signable) + const extToSign = state.metamask.extToSign + const extCancel = state.metamask.extCancel + const extSigned = state.metamask.extSigned + const showError = !!signature && signatureInError(signable, signature) + var errorType + var errors = { + invalidSignatureLength: 'invalidSignatureLength', + invalidSignature: 'invalidSignature', + invalidSignatureChar: 'invalidSignatureChar', + } + if (signature.replace(/[^a-f0-9A-Fx]/g, '') !== signature) { + errorType = 'invalidSignatureChar' + } else if (ethUtil.stripHexPrefix(signature).length !== 130) { + errorType = 'invalidSignatureLength' + } else { + errorType = showError ? 'invalidSignature' : null + } + const qrScanner = true // display qr scanner icon on input field + return { + errors, + errorType, + extCancel, + extSigned, + extToSign, + qrCodeData, + qrScanner, + qrTxData, + showError, + signable, + signature, + txData, + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onChange: (newSignature) => { + dispatch(updateSignature(newSignature)) + }, + scanSignatureQrCode: (props) => { + dispatch(showQrScanner(CONFIRM_TRANSACTION_ROUTE, props)) + }, + qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), + onCancel: (extCancelCopy) => { + dispatch(updateExternalSign({extCancel: extCancelCopy})) + dispatch(hideModal()) + }, + onSubmit: (extSignedCopy) => { + dispatch(updateExternalSign({extSigned: extSignedCopy})) + dispatch(hideModal()) + }, + updateExternalSign: (update) => { + dispatch(updateExternalSign(update)) + }, + hideLodingIndication: () => { + dispatch(hideLoadingIndication()) + }, + } +} + +class ExternalSignModal extends PureComponent { + static propTypes = { + errors: PropTypes.object, + errorType: PropTypes.string, + extCancel: PropTypes.array, + extSigned: PropTypes.array, + extToSign: PropTypes.array, + hideLodingIndication: PropTypes.func, + onCancel: PropTypes.func, + onChange: PropTypes.func, + onSubmit: PropTypes.func, + qrCodeData: PropTypes.object, + qrCodeDetected: PropTypes.func, + qrScanner: PropTypes.bool, + qrTxData: PropTypes.string, + scanSignatureQrCode: PropTypes.func, + showError: PropTypes.bool, + signable: PropTypes.object, + signature: PropTypes.string, + updateExternalSign: PropTypes.func, + } + + static contextTypes = { + t: PropTypes.func, + } + constructor (props) { + super(props) + this.state = { cancelOrSubmitPressed: false } + this.onCancel = this.onCancel.bind(this) + this.onSubmit = this.onSubmit.bind(this) + this.container = null + + this.setContainerRef = element => { + this.container = element + } + } + render () { + const { + errors, + errorType, + onChange, + qrTxData, + qrScanner, + scanSignatureQrCode, + showError, + signable, + signature, + } = this.props + + return h(ExternalSignModalContainer, {hideModal: this.onCancel }, [ + h(QrView, { + Qr: { + data: qrTxData, + width: Math.min(480, window.innerWidth - 70), + isDataAddress: false, + }, + }), + h(SendRowWrapper, { + label: this.context.t('signature'), + errors: errors, + errorType: errorType, + showError: showError, + }, [ + h(TxInput, { + signature: signature, + onChange: onChange, + inError: showError, + qrScanner: qrScanner, + scanSignatureQrCode: scanSignatureQrCode, + scannerProps: {showNext: 'EXTERNAL_SIGN', nextProps: {signable: signable} }, + }), + ]), + h(PageContainerFooter, { + onCancel: this.onCancel, + onSubmit: this.onSubmit, + submitText: this.context.t('confirm'), + disabled: showError || !signature, + }), + ]) + } + + onCancel () { + this.setState({cancelOrSubmitPressed: true}, () => { + const {extCancel, signable} = this.props + this.extToSignUpdate() + var extCancelCopy = extCancel.slice() + extCancelCopy.push(signable) + this.props.onCancel(extCancelCopy) + }) + } + + onSubmit () { + this.setState({cancelOrSubmitPressed: true}, () => { + const {extSigned, signable, signature} = this.props + var signableCopy = extend({}, signable) + signableCopy.signature = signature + var extSignedCopy = extSigned.slice() + extSignedCopy.push(signableCopy) + this.extToSignUpdate() + this.props.onSubmit(extSignedCopy) + }) + } + + extToSignUpdate () { + const {extToSign, signable, updateExternalSign} = this.props + var signables = extToSign.filter(sgn => sgn.id !== signable.id) + updateExternalSign({extToSign: signables}) + } + + componentDidMount () { + const { + onChange, + qrCodeData, + qrCodeDetected, + } = this.props + if (qrCodeData && qrCodeData.type === 'signature') { + onChange(qrCodeData.values.signature) + qrCodeDetected(null) + } + this.props.hideLodingIndication() + } + + componentWillUnmount () { + if (!this.state.cancelOrSubmitPressed) { + this.onCancel() + } + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(ExternalSignModal) + +// converts hex encoded signature to r, s, v signature +function signatureHexToRSV (signature) { + signature = ethUtil.stripHexPrefix(signature) + const r = ethUtil.toBuffer('0x' + signature.substr(0, 64)) + const s = ethUtil.toBuffer('0x' + signature.substr(64, 64)) + const v = ethUtil.toBuffer('0x' + signature.substr(128, 2)) + return {r: r, s: s, v: v} +} + +function signatureInError (signable, signature) { + try { + const {r, s, v} = signatureHexToRSV(signature) + switch (signable.type) { + case 'sign_transaction': + const tx = new Transaction(signable.payload) + tx.r = r + tx.s = s + tx.v = v + return !tx.verifySignature() + case 'sign_message': + ethUtil.ecrecover(ethUtil.sha3(ethUtil.toBuffer(signable.payload)), ethUtil.bufferToInt(v), r, s) + return false + case 'sign_personal_message': + ethUtil.ecrecover(ethUtil.hashPersonalMessage(ethUtil.toBuffer(signable.payload)), ethUtil.bufferToInt(v), r, s) + return false + case 'sign_typed_data': + ethUtil.ecrecover(sigUtil.sign(signable.payload), ethUtil.bufferToInt(v), r, s) + return false + } + } catch (e) { + return true + } +} + +function reduce (signable) { + const fromAddress = ethUtil.stripHexPrefix(signable.from) + const partFrom = fromAddress.substr(0, 4) + + fromAddress.substr(18, 2) + fromAddress.slice(-4) + switch (signable.type) { + case 'sign_message': + return 'eths:/?m=' + partFrom + signable.payloadd + case 'sign_personal_message': + return 'eths:/?p=' + partFrom + signable.payload + case 'sign_typed_data': + return 'eths:/?y=' + partFrom + signable.payload + case 'sign_transaction': + const tx = signable.payload + var chainId = tx.chainId + var chainCode + switch (chainId) { + case 1: + chainCode = 0 + break + case 61: + chainCode = 1 + break + case 2: + chainCode = 3 // Morden testnet + break + case 3: + chainCode = 4 + break + case 4: + chainCode = 5 + break + case 42: + chainCode = 6 + break + case 77: + chainCode = 7 + break + case 99: + chainCode = 9 + break + case 7762959: + chainCode = 10 + break + default: + chainCode = 8 + break + } + var signingType = 0 + var signChainVersion = ethUtil.stripHexPrefix(ethUtil.intToHex(signingType * 4 + chainCode * 16)) + var flatStr = signChainVersion + partFrom + flatStr += ethUtil.stripHexPrefix(tx.to) + flatStr += chainCode === 8 ? chainId.toString() + '|' : '' + flatStr += ethUtil.stripHexPrefix(tx.nonce) + '|' + flatStr += ethUtil.stripHexPrefix(tx.gasPrice) + '|' + flatStr += ethUtil.stripHexPrefix(tx.gasLimit) + '|' + flatStr += ethUtil.stripHexPrefix(tx.value) + '|' + flatStr += ethUtil.stripHexPrefix(tx.data) + flatStr = flatStr.toLowerCase() + + // escape all '9' in flat string + const numStr = flatStr + .replace(/9/g, '99') + .replace(/a/g, '90') + .replace(/b/g, '91') + .replace(/c/g, '92') + .replace(/d/g, '93') + .replace(/e/g, '94') + .replace(/f/g, '95') + .replace(/\|/g, '96') + + // zero compressing + const zeroCompStr = numStr.replace(/0{48}/g, '975').replace(/0{24}/g, '974').replace(/0{12}/g, '973').replace(/0{6}/g, '972').replace(/0{5}/g, '971').replace(/0{4}/g, '970') + var errorChk = ethUtil.stripHexPrefix(ethUtil.bufferToHex(ethUtil.sha3(ethUtil.toBuffer(zeroCompStr))).slice(-2)) + + // error check + errorChk = errorChk + .replace(/9/g, '99') + .replace(/a/g, '90') + .replace(/b/g, '91') + .replace(/c/g, '92') + .replace(/d/g, '93') + .replace(/e/g, '94') + .replace(/f/g, '95') + return 'eths:/?t=' + errorChk + zeroCompStr + } +} diff --git a/ui/app/components/modals/external-sign-modal/index.js b/ui/app/components/modals/external-sign-modal/index.js new file mode 100644 index 000000000000..348f929b0a60 --- /dev/null +++ b/ui/app/components/modals/external-sign-modal/index.js @@ -0,0 +1 @@ +export { default } from './external-sign-modal' diff --git a/ui/app/components/modals/external-sign-modal/tx-input.js b/ui/app/components/modals/external-sign-modal/tx-input.js new file mode 100644 index 000000000000..cfa892d916cb --- /dev/null +++ b/ui/app/components/modals/external-sign-modal/tx-input.js @@ -0,0 +1,49 @@ +const Component = require('react').Component +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const Tooltip = require('../../tooltip') + +TxInput.contextTypes = { + t: PropTypes.func, +} + +module.exports = connect()(TxInput) + + +inherits(TxInput, Component) +function TxInput () { + Component.call(this) +} + +TxInput.prototype.render = function () { + const { + signature, + onChange, + inError, + qrScanner, + scanSignatureQrCode, + scannerProps, + } = this.props + + return h('div.send-v2__to-autocomplete', {}, [ + + h(`input.send-v2__to-autocomplete__input${qrScanner ? '.with-qr' : ''}`, { + placeholder: this.context.t('signature'), + className: inError ? `send-v2__error-border` : '', + value: signature, + onChange: event => onChange(event.target.value), + style: { + borderColor: inError ? 'red' : null, + }, + }), + qrScanner && h(Tooltip, { + title: this.context.t('scanQrCode'), + position: 'bottom', + }, h(`i.fa.fa-qrcode.fa-lg.send-v2__to-autocomplete__qr-code`, { + style: { color: '#33333' }, + onClick: () => scanSignatureQrCode(scannerProps), + })), + ]) +} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 8ab599a716dc..e1f923d3e629 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -8,6 +8,7 @@ const { resetCustomData: resetCustomGasData } = require('../../ducks/gas.duck') const isMobileView = require('../../../lib/is-mobile-view') const { getEnvironmentType } = require('../../../../app/scripts/lib/util') const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums') +const extend = require('xtend') // Modal Components const BuyOptions = require('./buy-options-modal') @@ -30,6 +31,7 @@ import MetaMetricsOptInModal from './metametrics-opt-in-modal' import RejectTransactions from './reject-transactions' import ClearApprovedOrigins from './clear-approved-origins' import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' +import ExternalSignModal from './external-sign-modal' const modalContainerBaseStyle = { transform: 'translate3d(-50%, 0, 0px)', @@ -174,6 +176,30 @@ const MODALS = { ...accountModalStyle, }, + EXTERNAL_SIGN: { + contents: [ + h(ExternalSignModal), + ], + mobileModalStyle: { + width: '100vw', + height: '100vh', + top: '0', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + }, + laptopModalStyle: { + width: '600px', + height: '640px', + top: '20px', + transform: 'none', + left: '0', + right: '0', + margin: '0 auto', + }, + }, + EXPORT_PRIVATE_KEY: { contents: [ h(ExportPrivateKeyModal, {}, []), @@ -431,7 +457,9 @@ const BACKDROPSTYLE = { function mapStateToProps (state) { return { active: state.appState.modal.open, + currentView: state.appState.currentView.name, modalState: state.appState.modal.modalState, + extToSign: state.metamask.extToSign, } } @@ -446,7 +474,9 @@ function mapDispatchToProps (dispatch) { hideWarning: () => { dispatch(actions.hideWarning()) }, - + showModal: (payload) => { + dispatch(actions.showModal(payload)) + }, } } @@ -488,6 +518,18 @@ Modal.prototype.render = function () { } Modal.prototype.componentWillReceiveProps = function (nextProps) { + if ( + nextProps.extToSign.length > this.props.extToSign.length && + this.props.currentView === 'confTx' && + !(this.props.modalState.name === 'EXTERNAL_SIGN' && + this.props.modalState.open) + ) { + this.props.showModal({ + name: 'EXTERNAL_SIGN', + signable: extend({}, nextProps.extToSign[0]), + updateMetamask: true, + }) + } if (nextProps.active) { this.show() } else if (this.props.active) { diff --git a/ui/app/components/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/modals/qr-scanner/qr-scanner.component.js index cb8d07d83831..64dcb6614701 100644 --- a/ui/app/components/modals/qr-scanner/qr-scanner.component.js +++ b/ui/app/components/modals/qr-scanner/qr-scanner.component.js @@ -9,10 +9,14 @@ import PageContainerFooter from '../../page-container/page-container-footer/page export default class QrScanner extends Component { static propTypes = { hideModal: PropTypes.func.isRequired, + showModal: PropTypes.func.isRequired, qrCodeDetected: PropTypes.func, scanQrCode: PropTypes.func, error: PropTypes.bool, errorType: PropTypes.string, + showNext: PropTypes.string, + nextProps: PropTypes.object, + route: PropTypes.string, } static contextTypes = { @@ -25,6 +29,7 @@ export default class QrScanner extends Component { this.state = { ready: false, msg: context.t('accessingYourCamera'), + showNextModal: true, } this.codeReader = null this.permissionChecker = null @@ -66,6 +71,7 @@ export default class QrScanner extends Component { if (this.codeReader) { this.codeReader.reset() } + this.showNextOrHide() } initCamera () { @@ -112,6 +118,11 @@ export default class QrScanner extends Component { type = 'address' values = {'address': content.split('ethereum:')[1] } + } else if (content.split('eths:').length > 1) { + // signature from external signer + type = 'signature' + values = {'signature': content.split('signature:')[1]} + // Regular ethereum addresses - fox ex. 0x.....1111 } else if (content.substring(0, 2).toLowerCase() === '0x') { @@ -122,22 +133,36 @@ export default class QrScanner extends Component { return {type, values} } + showNextOrHide = () => { + if (this.state.showNextModal && this.props.showNext) { + setTimeout(_ => { + this.props.showModal({ + name: this.props.showNext, + ...this.props.nextProps, + }) + }, 300) + } else { + this.props.hideModal() + } + } stopAndClose = () => { if (this.codeReader) { this.codeReader.reset() } this.setState({ ready: false }) - this.props.hideModal() + this.showNextOrHide() } tryAgain = () => { - // close the modal - this.stopAndClose() - // wait for the animation and try again - setTimeout(_ => { - this.props.scanQrCode() - }, 1000) + this.setState({showNextModal: false}, () => { + // close the modal + this.stopAndClose() + // wait for the animation and try again + setTimeout(_ => { + this.props.scanQrCode(this.props.route, {showNext: this.props.showNext, nextProps: this.props.nextProps}) + }, 1000) + }) } renderVideo () { diff --git a/ui/app/components/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/modals/qr-scanner/qr-scanner.container.js index d0a35e03b70e..aaae59cf8d80 100644 --- a/ui/app/components/modals/qr-scanner/qr-scanner.container.js +++ b/ui/app/components/modals/qr-scanner/qr-scanner.container.js @@ -1,23 +1,28 @@ import { connect } from 'react-redux' import QrScanner from './qr-scanner.component' -const { hideModal, qrCodeDetected, showQrScanner } = require('../../../actions') +const { hideModal, showModal, qrCodeDetected, showQrScanner } = require('../../../actions') import { SEND_ROUTE, } from '../../../routes' const mapStateToProps = state => { + const props = state.appState.modal.modalState.props return { - error: state.appState.modal.modalState.props.error, - errorType: state.appState.modal.modalState.props.errorType, + error: props.error, + errorType: props.errorType, + showNext: props.showNext, + nextProps: props.nextProps, + route: props.route, } } const mapDispatchToProps = dispatch => { return { + showModal: (props) => dispatch(showModal(props)), hideModal: () => dispatch(hideModal()), qrCodeDetected: (data) => dispatch(qrCodeDetected(data)), - scanQrCode: () => dispatch(showQrScanner(SEND_ROUTE)), + scanQrCode: (route, props) => dispatch(showQrScanner(route || SEND_ROUTE, props)), } } diff --git a/ui/app/components/pages/create-account/external-account/external-account.js b/ui/app/components/pages/create-account/external-account/external-account.js new file mode 100644 index 000000000000..4d13a9594687 --- /dev/null +++ b/ui/app/components/pages/create-account/external-account/external-account.js @@ -0,0 +1,112 @@ +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 { DEFAULT_ROUTE } = require('../../../../routes') +import Button from '../../../button' + +ExternalAccountImportView.contextTypes = { + t: PropTypes.func, +} + +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(ExternalAccountImportView) + + +function mapStateToProps (state) { + return { + error: state.appState.warning, + firstAddress: Object.keys(state.metamask.accounts)[0], + } +} + +function mapDispatchToProps (dispatch) { + return { + addExternalAccount: (address) => { + return dispatch(actions.addExternalAccount(address)) + }, + displayWarning: (message) => dispatch(actions.displayWarning(message || null)), + setSelectedAddress: (address) => dispatch(actions.setSelectedAddress(address)), + } +} + +inherits(ExternalAccountImportView, Component) +function ExternalAccountImportView () { + this.createKeyringOnEnter = this.createKeyringOnEnter.bind(this) + Component.call(this) +} + +ExternalAccountImportView.prototype.render = function () { + const { error, displayWarning } = this.props + + return ( + h('div.new-account-import-form__private-key', [ + + h('span.new-account-create-form__instruction', this.context.t('pasteExternalAccount')), + + h('div.new-account-import-form__private-key-password-container', [ + + h('input.new-account-import-form__input-password', { + type: 'text', + id: 'external-account-box', + onKeyPress: e => this.createKeyringOnEnter(e), + }), + + ]), + + h('div.new-account-import-form__buttons', {}, [ + + h(Button, { + type: 'default', + large: true, + className: 'new-account-create-form__button', + onClick: () => { + displayWarning(null) + this.props.history.push(DEFAULT_ROUTE) + }, + }, [this.context.t('cancel')]), + + h(Button, { + type: 'primary', + large: true, + className: 'new-account-create-form__button', + onClick: () => this.createNewKeychain(), + }, [this.context.t('create')]), + + ]), + + error ? h('span.error', error) : null, + ]) + ) +} + +ExternalAccountImportView.prototype.createKeyringOnEnter = function (event) { + if (event.key === 'Enter') { + event.preventDefault() + this.createNewKeychain() + } +} + +ExternalAccountImportView.prototype.createNewKeychain = function () { + const input = document.getElementById('external-account-box') + const address = input.value + const { addExternalAccount, history, displayWarning, setSelectedAddress, firstAddress } = this.props + + addExternalAccount(address) + .then(({ selectedAddress }) => { + if (selectedAddress) { + history.push(DEFAULT_ROUTE) + displayWarning(null) + } else { + displayWarning('Error adding external account.') + setSelectedAddress(firstAddress) + } + }) + .catch(err => err && displayWarning(err.message || err)) +} diff --git a/ui/app/components/pages/create-account/external-account/index.js b/ui/app/components/pages/create-account/external-account/index.js new file mode 100644 index 000000000000..73075e979c6f --- /dev/null +++ b/ui/app/components/pages/create-account/external-account/index.js @@ -0,0 +1,39 @@ +const inherits = require('util').inherits +const Component = require('react').Component +//const React = require('react').React +const h = require('react-hyperscript') +const PropTypes = require('prop-types') +const connect = require('react-redux').connect + +// Subviews +const ExternalAccountImportView = require('./external-account.js') + + +ExternalAccountForm.contextTypes = { + t: PropTypes.func, +} + +module.exports = connect()(ExternalAccountForm) + + +inherits(ExternalAccountForm, Component) +function ExternalAccountForm () { + Component.call(this) +} + +ExternalAccountForm.prototype.render = function () { + + return ( + h('div.new-account-import-form', [ + + h('.new-account-import-disclaimer', [ + h('span', this.context.t('externalAccountMsg')), + ]), + + h('div.new-account-import-form__select-section', [ + + h(ExternalAccountImportView), + ]), + ]) + ) +} diff --git a/ui/app/components/pages/create-account/external-account/seed.js b/ui/app/components/pages/create-account/external-account/seed.js new file mode 100644 index 000000000000..d98909baa1f3 --- /dev/null +++ b/ui/app/components/pages/create-account/external-account/seed.js @@ -0,0 +1,35 @@ +const inherits = require('util').inherits +const Component = require('react').Component +const h = require('react-hyperscript') +const PropTypes = require('prop-types') +const connect = require('react-redux').connect + +SeedImportSubview.contextTypes = { + t: PropTypes.func, +} + +module.exports = connect(mapStateToProps)(SeedImportSubview) + + +function mapStateToProps (state) { + return {} +} + +inherits(SeedImportSubview, Component) +function SeedImportSubview () { + Component.call(this) +} + +SeedImportSubview.prototype.render = function () { + return ( + h('div', { + style: { + }, + }, [ + this.context.t('pasteSeed'), + h('textarea'), + h('br'), + h('button', this.context.t('submit')), + ]) + ) +} diff --git a/ui/app/components/pages/create-account/index.js b/ui/app/components/pages/create-account/index.js index d3de1ea0118e..41eb06878f1a 100644 --- a/ui/app/components/pages/create-account/index.js +++ b/ui/app/components/pages/create-account/index.js @@ -9,10 +9,12 @@ const classnames = require('classnames') const NewAccountCreateForm = require('./new-account') const NewAccountImportForm = require('./import-account') const ConnectHardwareForm = require('./connect-hardware') +const ExternalAccountForm = require('./external-account') const { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, + EXTERNAL_ACCOUNT_ROUTE, } = require('../../../routes') class CreateAccountPage extends Component { @@ -54,6 +56,19 @@ class CreateAccountPage extends Component { }, this.context.t('connect') ), + h( + 'div.new-account__tabs__tab', + { + className: classnames('new-account__tabs__tab', { + 'new-account__tabs__selected': matchPath(location.pathname, { + path: EXTERNAL_ACCOUNT_ROUTE, + exact: true, + }), + }), + onClick: () => history.push(EXTERNAL_ACCOUNT_ROUTE), + }, + this.context.t('external') + ), ]) } @@ -80,6 +95,11 @@ class CreateAccountPage extends Component { path: CONNECT_HARDWARE_ROUTE, component: ConnectHardwareForm, }), + h(Route, { + exact: true, + path: EXTERNAL_ACCOUNT_ROUTE, + component: ExternalAccountForm, + }), ]), ]), ]) diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 312815891f5c..7500083fa76c 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -6,7 +6,7 @@ const connect = require('react-redux').connect const { isHexPrefixed } = require('ethereumjs-util') const ReadOnlyInput = require('./readonly-input') const { checksumAddress } = require('../util') - +import QRCode from 'qrcode.react' module.exports = connect(mapStateToProps)(QrCodeView) function mapStateToProps (state) { @@ -25,12 +25,15 @@ function QrCodeView () { QrCodeView.prototype.render = function () { const props = this.props - const { message, data, network } = props.Qr - const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${checksumAddress(data, network)}` - const qrImage = qrCode(4, 'M') - qrImage.addData(address) - qrImage.make() - + const { message, data, network, isDataAddress, width} = props.Qr + const isAddress = isDataAddress !== false + var qrImage + if (isAddress) { + const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${checksumAddress(data, network)}` + qrImage = qrCode(4, 'M') + qrImage.addData(address) + qrImage.make() + } return h('.div.flex-column.flex-center', [ Array.isArray(message) ? h('.message-container', this.renderMultiMessage()) @@ -42,16 +45,22 @@ QrCodeView.prototype.render = function () { }, this.props.warning) : null, - h('.div.qr-wrapper', { + isAddress ? h('.div.qr-wrapper', { style: {}, dangerouslySetInnerHTML: { __html: qrImage.createTableTag(4), }, - }), + }) : h('.div.qr-wrapper', { style: {} }, [ + h(QRCode, { + value: data, + size: width || 480, + }), + ]), + h(ReadOnlyInput, { wrapperClass: 'ellip-address-wrapper', inputClass: 'qr-ellip-address', - value: checksumAddress(data, network), + value: isDataAddress ? checksumAddress(data) : data, }), ]) } diff --git a/ui/app/components/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js b/ui/app/components/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js index 61bc7bab77ed..7fb4ca598118 100644 --- a/ui/app/components/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js +++ b/ui/app/components/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js @@ -6,6 +6,7 @@ export default class SendRowErrorMessage extends Component { static propTypes = { errors: PropTypes.object, errorType: PropTypes.string, + customErrors: PropTypes.object, }; static contextTypes = { @@ -13,9 +14,9 @@ export default class SendRowErrorMessage extends Component { }; render () { - const { errors, errorType } = this.props + const { errors, errorType, customErrors } = this.props - const errorMessage = errors[errorType] + const errorMessage = errors[errorType] || customErrors[errorType] return ( errorMessage diff --git a/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js b/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js index 0146ce6452ac..a1440ac32a4e 100644 --- a/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js +++ b/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js @@ -7,6 +7,7 @@ export default class SendRowWrapper extends Component { static propTypes = { children: PropTypes.node, + errors: PropTypes.object, errorType: PropTypes.string, label: PropTypes.string, showError: PropTypes.bool, @@ -26,6 +27,7 @@ export default class SendRowWrapper extends Component { showError = false, showWarning = false, warningType = '', + errors, } = this.props const formField = Array.isArray(children) ? children[1] || children[0] : children const customLabelContent = children.length > 1 ? children[0] : null @@ -34,7 +36,7 @@ export default class SendRowWrapper extends Component {
{label} - {showError && } + {showError && } {!showError && showWarning && } {customLabelContent}
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index db572e5cbfc2..4506af97ecb9 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -151,15 +151,23 @@ WalletView.prototype.render = function () { let type if (keyring) { type = keyring.type - if (type !== 'HD Key Tree') { - if (type.toLowerCase().search('hardware') !== -1) { + switch (type) { + case 'Trezor Hardware': + case 'Ledger Hardware': label = this.context.t('hardware') - } else { + break + case 'Simple Key Pair': label = this.context.t('imported') - } + break + case 'External Account': + label = this.context.t('external') + break + default: + label = '' } } + return h('div.wallet-view.flex-column', { style: {}, className: responsiveDisplayClassname, diff --git a/ui/app/ducks/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction.duck.js index f75ff809a1d4..3504ffadf9aa 100644 --- a/ui/app/ducks/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction.duck.js @@ -44,6 +44,7 @@ const UPDATE_NONCE = createActionType('UPDATE_NONCE') const UPDATE_TO_SMART_CONTRACT = createActionType('UPDATE_TO_SMART_CONTRACT') const FETCH_DATA_START = createActionType('FETCH_DATA_START') const FETCH_DATA_END = createActionType('FETCH_DATA_END') +const UPDATE_SIGNATURE = createActionType('UPDATE_SIGNATURE') // Initial state const initState = { @@ -66,6 +67,7 @@ const initState = { nonce: '', toSmartContract: false, fetchingData: false, + signature: '', } // Reducer @@ -163,6 +165,11 @@ export default function reducer ({ confirmTransaction: confirmState = initState } case CLEAR_CONFIRM_TRANSACTION: return initState + case UPDATE_SIGNATURE: + return { + ...confirmState, + signature: action.payload, + } default: return confirmState } @@ -418,3 +425,11 @@ export function clearConfirmTransaction () { type: CLEAR_CONFIRM_TRANSACTION, } } + +export function updateSignature (newSignature) { + return { + type: UPDATE_SIGNATURE, + payload: newSignature, + } +} + diff --git a/ui/app/routes.js b/ui/app/routes.js index 932dfa7df2e9..1e215edbc35c 100644 --- a/ui/app/routes.js +++ b/ui/app/routes.js @@ -13,6 +13,7 @@ const CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE = '/confirm-add-suggested-token' const NEW_ACCOUNT_ROUTE = '/new-account' const IMPORT_ACCOUNT_ROUTE = '/new-account/import' const CONNECT_HARDWARE_ROUTE = '/new-account/connect' +const EXTERNAL_ACCOUNT_ROUTE = '/new-account/external' const SEND_ROUTE = '/send' const NOTICE_ROUTE = '/notice' const WELCOME_ROUTE = '/welcome' @@ -56,6 +57,7 @@ module.exports = { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, + EXTERNAL_ACCOUNT_ROUTE, SEND_ROUTE, NOTICE_ROUTE, WELCOME_ROUTE,