diff options
49 files changed, 453 insertions, 1066 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 68cd4f7a9..a69903373 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -80,7 +80,7 @@ workflows: jobs: prep-deps-npm: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - run: @@ -94,7 +94,7 @@ jobs: prep-build: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -113,7 +113,7 @@ jobs: prep-docs: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -128,7 +128,7 @@ jobs: prep-scss: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -147,7 +147,7 @@ jobs: test-lint: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -158,7 +158,7 @@ jobs: test-deps: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -182,7 +182,7 @@ jobs: # destination: test-artifacts test-e2e-chrome: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -197,7 +197,7 @@ jobs: test-e2e-firefox: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - run: @@ -215,7 +215,7 @@ jobs: job-screens: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -230,7 +230,7 @@ jobs: job-publish-prerelease: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -250,7 +250,7 @@ jobs: job-publish-release: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -267,7 +267,7 @@ jobs: test-unit: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -277,7 +277,7 @@ jobs: command: npm run test:coverage test-mozilla-lint: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -288,7 +288,7 @@ jobs: test-integration-flat-firefox: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -304,7 +304,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - checkout - attach_workspace: @@ -315,7 +315,7 @@ jobs: all-tests-pass: docker: - - image: circleci/node:8.15.1-browsers + - image: circleci/node:10.16-browsers steps: - run: name: All Tests Passed diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7a7d51936..5ee6fac12 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,6 +1,7 @@ # Lines starting with '#' are comments. # Each line is a file pattern followed by one or more owners. +package*.json @whymarrh ui/ @danjm @whymarrh app/scripts/controllers/transactions @frankiebee @@ -1 +1 @@ -v8.15 +v10.16.0 @@ -11,18 +11,16 @@ To learn how to contribute to the MetaMask project itself, visit our [Internal D ## Building locally -- Install [Node.js](https://nodejs.org) version 8 and the latest available npm@6 +- Install [Node.js](https://nodejs.org) version 10 and the latest available npm@6 - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you. - If you install Node.js manually, ensure you're using npm@6 - Install npm@6 using `npm install -g npm@6` -- Install dependencies: `npm install` +- Install dependencies: `npm ci` - If you have issues with node-sass compilation, try `npm rebuild node-sass` -- Install gulp globally with `npm install -g gulp-cli`. -- Build the project to the `./dist/` folder with `gulp build`. -- Optionally, to rebuild on file changes, run `gulp dev`. -- To package .zip files for distribution, run `gulp zip`, or run the full build & zip with `gulp dist`. +- Build the project to the `./dist/` folder with `npm run dist`. +- Optionally, to start a development build (e.g. with logging and file watching) run `npm start` instead. - Uncompressed builds can be found in `/dist`, compressed builds can be found in `/builds` once they're built. +Uncompressed builds can be found in `/dist`, compressed builds can be found in `/builds` once they're built. ## Contributing @@ -32,13 +30,11 @@ You can re-generate the docs locally by running `npm run doc`, and contributors ### Running Tests -Requires `mocha` installed. Run `npm install -g mocha`. - -Then just run `npm test`. +Run tests with `npm test`. You can also test with a continuously watching process, via `npm run watch`. -You can run the linter by itself with `gulp lint`. +You can run the linter by itself with `npm run lint`. ## Architecture diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index a28c4cb4a..187ffd95f 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -252,10 +252,6 @@ "depositBTC": { "message": "Vložte BTC na níže uvedenou adresu:" }, - "depositCoin": { - "message": "Vložte $1 na níže uvedenou adresu", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "Vložit Eth" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index b76f87772..98a8bf972 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -249,10 +249,6 @@ "depositBTC": { "message": "Zahle dein BTC in die unten stehende Adresse ein:" }, - "depositCoin": { - "message": "Zahle deine $1 in die unten stehende Adresse ein", - "description": "Teilt dem Benutzer mit welchen Token er beim Einzahlen mit Shapeshift ausgewählt hat" - }, "depositEth": { "message": "Eth kaufen" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 774ae4c85..cc087867a 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -466,10 +466,6 @@ "depositBTC": { "message": "Deposit your BTC to the address below:" }, - "depositCoin": { - "message": "Deposit your $1 to the address below", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "Deposit Eth" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 3bdbfa852..06531b1dc 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -264,10 +264,6 @@ "depositBTC": { "message": "Deposita tus BTC a la dirección de abajo:" }, - "depositCoin": { - "message": "Deposita tu $1 a la dirección de abajo", - "description": "Informa al usuario que moneda ha elegido para depositar en shapeshift" - }, "depositEth": { "message": "Depositar Ether" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index d2ba10009..70effb3ea 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -330,10 +330,6 @@ "depositBTC": { "message": "Déposez vos BTC à l'adresse ci-dessous:" }, - "depositCoin": { - "message": "Déposer votre $1 à l'adresse ci-dessous", - "description": "Indique à l'utilisateur quelle monnaie il a choisi de déposer avec Shapeshift" - }, "depositEth": { "message": "Déposer Eth" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 6c27ee1bc..54ddcc02b 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -240,10 +240,6 @@ "depositBTC": { "message": "नीचे दिए गए पते पर अपना बीटीसी जमा करें:" }, - "depositCoin": { - "message": "नीचे दिए गए पते पर अपना $1 जमा करें", - "description": "उपयोगकर्ता को बताता है कि उन्होंने सिक्का के साथ जमा करने के लिए किस सिक्का का चयन किया है" - }, "depositEth": { "message": "Eth जमाआर्थ" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 4a4c92f3a..720c35889 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -336,10 +336,6 @@ "depositBTC": { "message": "Depoze BTC ou nan adrès ki anba a:" }, - "depositCoin": { - "message": "Depoze $1 ou nan adrès ki anba a", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "Depo Eth" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 09ba045b9..c79f22b71 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -463,10 +463,6 @@ "depositBTC": { "message": "Deposita i tuoi BTC all'indirizzo sotto:" }, - "depositCoin": { - "message": "Deposita $1 all'indirizzo sotto", - "description": "Dice all'utente quale moneta ha selezionato per depositare con Shapeshift" - }, "depositEth": { "message": "Deposita Eth" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index fcac67894..49b033997 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -228,10 +228,6 @@ "depositBTC": { "message": "BTCを下記のアドレスへ振込んでください:" }, - "depositCoin": { - "message": "$1を下記のアドレスへ振込んでください", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "ETHを入金" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index bf11640e2..541d9dd5c 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -402,10 +402,6 @@ "depositBTC": { "message": "다음 주소로 BTC를 입금해주세요." }, - "depositCoin": { - "message": "다음 주소로 $1 만큼 입금해주세요.", - "description": "사용자에게 shapeshift에서 어떤 코인을 선택해 입금했는지 알려줍니다" - }, "depositEth": { "message": "이더 입금하기" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index 12bde6585..ade7327de 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -240,10 +240,6 @@ "depositBTC": { "message": "Stort uw BTC op het onderstaande adres:" }, - "depositCoin": { - "message": "Stort uw $1 op het onderstaande adres", - "description": "Laat de gebruiker weten welk muntje ze hebben geselecteerd om te deponeren met shapeshift" - }, "depositEth": { "message": "Aanbetaling Eth" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index da3cf266d..c8cde27f6 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -201,10 +201,6 @@ "depositBTC": { "message": "I-deposito ang iyong BTC sa address na ito:" }, - "depositCoin": { - "message": "I-deposito ang iyong $1 sa address na ito", - "description": "Sinasabihan ang user kung ano ang coin na kanilang pinili para I-deposito gamit ang shapeshift" - }, "depositEth": { "message": "I-deposito ang Eth" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index 026f4b3ec..868ab0cae 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -249,10 +249,6 @@ "depositBTC": { "message": "Zdeponuj swoje BTC na poniższy adres:" }, - "depositCoin": { - "message": "Zdeponuj $1 na poniższy adres", - "description": "Pokazuje użytkownikowi jakie waluty wybrał do zdeponowania w ShapeShift" - }, "depositEth": { "message": "Zdeponuj Eth" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index e51b1f72e..5724bce88 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -240,10 +240,6 @@ "depositBTC": { "message": "Deposite as suas BTC no endereço abaixo:" }, - "depositCoin": { - "message": "Deposite $1 no endereço abaixo", - "description": "Diz ao usuário que moeda selecionou para depositar com shapeshift" - }, "depositEth": { "message": "Depositar Eth" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index f80efcc56..e56441186 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -252,10 +252,6 @@ "depositBTC": { "message": "Отправьте ваш BTC на адрес ниже:" }, - "depositCoin": { - "message": "Отправьте ваш $1 на адрес ниже", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "Пополнить Eth" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index febcc9141..f98de674b 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -243,10 +243,6 @@ "depositBTC": { "message": "Vložte BTC na níže uvedenou adresu:" }, - "depositCoin": { - "message": "Vložte $1 na níže uvedenou adresu", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "Vložit Eth" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 2f3616dee..d04ba1ee7 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -408,10 +408,6 @@ "depositBTC": { "message": "Vplačajte vaš BTC na spodnji naslov:" }, - "depositCoin": { - "message": "Vplačajte vaš $1 na spodnji naslov", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "Vplačilo ETH" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index d851d325f..a49cf31ad 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -240,10 +240,6 @@ "depositBTC": { "message": "ฝากบิตคอยน์ของคุณไปที่แอดเดรสด้านล่างนี้:" }, - "depositCoin": { - "message": "ฝาก $1 ของคุณไปที่แอดเดรสด้านล่างนี้:", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "การฝากอีเธอร์" }, diff --git a/app/_locales/tml/messages.json b/app/_locales/tml/messages.json index e1ef45138..2f883b26b 100644 --- a/app/_locales/tml/messages.json +++ b/app/_locales/tml/messages.json @@ -252,10 +252,6 @@ "depositBTC": { "message": "கீழே உங்கள் முகவரிக்கு உங்கள் BTC வைப்போம்:" }, - "depositCoin": { - "message": "உங்கள் முகவரிக்கு $ 1 ஐ கீழே உள்ளிடவும்", - "description": "சேபஷிபிட் உடன் வைப்புக்குத் தேர்ந்தெடுக்கப்பட்ட நாணயத்தை பயனரிடம் கூறுகிறார்" - }, "depositEth": { "message": "வைப்புத்தொகை எது " }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index bcf96dece..726024764 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -252,10 +252,6 @@ "depositBTC": { "message": "BTC'inizi aşağıdaki adrese yatırın:" }, - "depositCoin": { - "message": "$1'nızı aşağıdaki adrese yatırın", - "description": "Kullanıcıya hangi jetonu seçtiyse onu yatırmasını shapeshift ile söyler." - }, "depositEth": { "message": "Eth yatır" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 857f78597..aee6474b6 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -201,10 +201,6 @@ "depositBTC": { "message": "Ký gửi BTC đến địa chỉ sau:" }, - "depositCoin": { - "description": "Báo cho người dùng biết đồng tiền nào họ đã chọn để ký gửi với ShapeShift", - "message": "Ký gửi $1 đến địa chỉ sau:" - }, "depositEth": { "message": "Ký gửi Eth" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 0d3727703..d14b99acb 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -261,10 +261,6 @@ "depositBTC": { "message": "将你的 BTC 存入到下面的地址:" }, - "depositCoin": { - "message": "将你的 $1 存入到下面的地址", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "存入 Eth" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 4df95f72f..18e30188e 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -378,10 +378,6 @@ "depositBTC": { "message": "將您的 BTC 存入到下面的位址:" }, - "depositCoin": { - "message": "將您的 $1 存入到下面的位址", - "description": "Tells the user what coin they have selected to deposit with shapeshift" - }, "depositEth": { "message": "存入乙太幣" }, diff --git a/app/images/spinner.gif b/app/images/spinner.gif Binary files differnew file mode 100644 index 000000000..8891f9596 --- /dev/null +++ b/app/images/spinner.gif diff --git a/app/notification.html b/app/notification.html index 042ffa6b8..82bf95ada 100644 --- a/app/notification.html +++ b/app/notification.html @@ -1,16 +1,39 @@ <!doctype html> <html style="height:600px;"> <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta charset="utf-8"> <title>MetaMask Notification</title> <style> body { overflow: hidden; } + + #app-content { + display: flex; + flex-flow: column; + } + + #loading__logo { + width: 10rem; + height: 10rem; + align-self: center; + margin: 10rem 0 0 0; + } + + #loading__spinner { + width: 2rem; + height: 2rem; + align-self: center; + margin-top: 1rem; + } </style> </head> <body class="notification" style="height:600px;"> - <div id="app-content"></div> + <div id="app-content"> + <img id="loading__logo" src="./images/logo/metamask-fox.svg" /> + <img id="loading__spinner" src="./images/spinner.gif" /> + </div> <script src="./libs.js" type="text/javascript" charset="utf-8"></script> <script src="./ui.js" type="text/javascript" charset="utf-8"></script> </body> diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index 84f7592a0..5a8a0cefe 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -17,8 +17,8 @@ module.exports = { // functions that handle normalizing of that key in txParams const normalizers = { - from: from => addHexPrefix(from).toLowerCase(), - to: to => addHexPrefix(to).toLowerCase(), + from: (from, LowerCase = true) => LowerCase ? addHexPrefix(from).toLowerCase() : addHexPrefix(from), + to: (to, LowerCase = true) => LowerCase ? addHexPrefix(to).toLowerCase() : addHexPrefix(to), nonce: nonce => addHexPrefix(nonce), value: value => addHexPrefix(value), data: data => addHexPrefix(data), @@ -31,11 +31,11 @@ const normalizers = { @param txParams {object} @returns {object} normalized txParams */ -function normalizeTxParams (txParams) { +function normalizeTxParams (txParams, LowerCase) { // apply only keys in the normalizers const normalizedTxParams = {} for (const key in normalizers) { - if (txParams[key]) normalizedTxParams[key] = normalizers[key](txParams[key]) + if (txParams[key]) normalizedTxParams[key] = normalizers[key](txParams[key], LowerCase) } return normalizedTxParams } diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 1a2cb5dee..2aa28c270 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -1,11 +1,10 @@ const extend = require('xtend') const EventEmitter = require('safe-event-emitter') const ObservableStore = require('obs-store') -const ethUtil = require('ethereumjs-util') const log = require('loglevel') const txStateHistoryHelper = require('./lib/tx-state-history-helper') const createId = require('../../lib/random-id') -const { getFinalStates } = require('./lib/util') +const { getFinalStates, normalizeTxParams } = require('./lib/util') /** TransactionStateManager is responsible for the state of a transaction and storing the transaction @@ -126,6 +125,11 @@ class TransactionStateManager extends EventEmitter { @returns {object} the txMeta */ addTx (txMeta) { + // normalize and validate txParams if present + if (txMeta.txParams) { + txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams) + } + this.once(`${txMeta.id}:signed`, function () { this.removeAllListeners(`${txMeta.id}:rejected`) }) @@ -175,13 +179,9 @@ class TransactionStateManager extends EventEmitter { @param [note] {string} - a note about the update for history */ updateTx (txMeta, note) { - // validate txParams + // normalize and validate txParams if present if (txMeta.txParams) { - if (typeof txMeta.txParams.data === 'undefined') { - delete txMeta.txParams.data - } - - this.validateTxParams(txMeta.txParams) + txMeta.txParams = this.normalizeAndValidateTxParams(txMeta.txParams) } // create txMeta snapshot for history @@ -214,6 +214,19 @@ class TransactionStateManager extends EventEmitter { } /** + * normalize and validate txParams members + * @param txParams {object} - txParams + */ + normalizeAndValidateTxParams (txParams) { + if (typeof txParams.data === 'undefined') { + delete txParams.data + } + txParams = normalizeTxParams(txParams, false) + this.validateTxParams(txParams) + return txParams + } + + /** validates txParams members by type @param txParams {object} - txParams to validate */ @@ -227,7 +240,6 @@ class TransactionStateManager extends EventEmitter { break default: if (typeof value !== 'string') throw new Error(`${key} in txParams is not a string. got: (${value})`) - if (!ethUtil.isHexPrefixed(value)) throw new Error(`${key} in txParams is not hex prefixed. got: (${value})`) break } }) diff --git a/docs/publishing.md b/docs/publishing.md index 392e20955..8d50e6869 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -42,3 +42,16 @@ With each pull request, the @MetaMaskBot will comment with a build of that new p 4. Publish to [Opera store](https://addons.opera.com/en/extensions/details/metamask/). 5. Post on [Github releases](https://github.com/MetaMask/metamask-extension/releases) page. 6. Run the `npm run announce` script, and post that announcement in our public places. + +## Hotfix Differences + +Our `develop` branch is usually not yet fully tested for quality assurance, and so should be treated as if it is in an unstable state. + +For this reason, when an urgent change is needed in production, its pull request should: + +- Describe it as a hotfix. +- Use a hotfix tag. +- Should be proposed against the `master` branch. + +The version and changelog bump should then be made off the `master` branch, and then merged to `develop` to bring the two branches back into sync. Further time can be saved by incorporating the version/changelog bump into the PR against `master`, since we rely on @MetaMaskBot to run tests before merging. + diff --git a/gulpfile.js b/gulpfile.js index 35c6331e8..6ea02c52c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -47,6 +47,7 @@ function gulpParallel (...args) { const browserPlatforms = [ 'firefox', 'chrome', + 'brave', 'edge', 'opera', ] @@ -180,6 +181,7 @@ gulp.task('manifest:production', function () { return gulp.src([ './dist/firefox/manifest.json', './dist/chrome/manifest.json', + './dist/brave/manifest.json', './dist/edge/manifest.json', './dist/opera/manifest.json', ], {base: './dist/'}) @@ -345,7 +347,7 @@ function createTasksForBuildJsExtension ({ buildJsFiles, taskPrefix, devMode, te const destinations = browserPlatforms.map(platform => `./dist/${platform}`) bundleTaskOpts = Object.assign({ buildSourceMaps: true, - sourceMapDir: devMode ? './' : '../sourcemaps', + sourceMapDir: '../sourcemaps', minifyBuild: !devMode, buildWithFullPaths: devMode, watch: devMode, @@ -602,10 +604,17 @@ function bundleTask (opts) { })) } - // Finalize Source Maps (writes .map file) + // Finalize Source Maps if (opts.buildSourceMaps) { - buildStream = buildStream - .pipe(sourcemaps.write(opts.sourceMapDir)) + if (opts.devMode) { + // Use inline source maps for development due to Chrome DevTools bug + // https://bugs.chromium.org/p/chromium/issues/detail?id=931675 + buildStream = buildStream + .pipe(sourcemaps.write()) + } else { + buildStream = buildStream + .pipe(sourcemaps.write(opts.sourceMapDir)) + } } // write completed bundles diff --git a/package-lock.json b/package-lock.json index 73b748f1b..777cf424e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9974,7 +9974,8 @@ "bail": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.2.tgz", - "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=" + "integrity": "sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q=", + "dev": true }, "balanced-match": { "version": "1.0.0", @@ -11163,17 +11164,20 @@ "character-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.1.tgz", - "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=" + "integrity": "sha1-92hxvl72bdt/j440eOzDdMJ9bco=", + "dev": true }, "character-entities-legacy": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz", - "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=" + "integrity": "sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8=", + "dev": true }, "character-reference-invalid": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz", - "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=" + "integrity": "sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw=", + "dev": true }, "chardet": { "version": "0.4.2", @@ -12043,11 +12047,6 @@ } } }, - "collapse-white-space": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", - "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=" - }, "collection-map": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", @@ -13166,7 +13165,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", - "dev": true + "dev": true, + "optional": true }, "cyclist": { "version": "0.2.2", @@ -14731,6 +14731,7 @@ "version": "3.5.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, "requires": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", @@ -14989,14 +14990,6 @@ "tapable": "^1.0.0" } }, - "ensnare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ensnare/-/ensnare-1.0.0.tgz", - "integrity": "sha1-ctK/fvSKuiH2at8p0AoJBO3bYcc=", - "requires": { - "tape": "^4.6.0" - } - }, "ensure-posix-path": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.0.2.tgz", @@ -15816,15 +15809,6 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, - "eth-bin-to-ops": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/eth-bin-to-ops/-/eth-bin-to-ops-1.0.1.tgz", - "integrity": "sha1-TScDuYeIJbw4xiWZEOkLTbAFx94=", - "requires": { - "ethereumjs-vm": "^2.0.0", - "tape": "^4.6.2" - } - }, "eth-block-tracker": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-4.1.0.tgz", @@ -18401,14 +18385,6 @@ "is-extendable": "^0.1.0" } }, - "extension-link-enabler": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/extension-link-enabler/-/extension-link-enabler-1.0.0.tgz", - "integrity": "sha1-V7kZru7fOL6XJwuYmM7nimN+RvM=", - "requires": { - "extensionizer": "^1.0.0" - } - }, "extension-port-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/extension-port-stream/-/extension-port-stream-1.0.0.tgz", @@ -18521,7 +18497,8 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", - "dev": true + "dev": true, + "optional": true }, "fake-merkle-patricia-tree": { "version": "1.0.1", @@ -22801,6 +22778,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, "requires": { "file-uri-to-path": "1.0.0" } @@ -22822,6 +22800,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -24060,6 +24039,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "dev": true, "requires": { "browserify-aes": "^1.0.6", "create-hash": "^1.1.2", @@ -24775,6 +24755,7 @@ "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", + "dev": true, "requires": { "bn.js": "^4.10.0", "ethereumjs-util": "^5.0.0" @@ -24969,6 +24950,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -25226,6 +25208,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, "requires": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -25559,7 +25542,8 @@ "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true }, "filesize": { "version": "3.6.1", @@ -27048,7 +27032,8 @@ "is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", + "dev": true }, "is-natural-number": { "version": "4.0.1", @@ -27374,6 +27359,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "dev": true, "requires": { "bindings": "^1.2.1", "inherits": "^2.0.3", @@ -30474,6 +30460,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "dev": true, "requires": { "safe-buffer": "^5.1.1" } @@ -30589,6 +30576,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.6.2.tgz", "integrity": "sha512-90nYt7yb0LmI4A2jJs1grglkTAXrBwxYAjP9bpeKjvJKOjG2fOeH/YI/lchDMIvjrOasd5QXwvV2jwN168xNng==", + "dev": true, "requires": { "bindings": "^1.2.1", "bip66": "^1.1.3", @@ -30752,15 +30740,6 @@ "safe-buffer": "^5.0.1" } }, - "sha3": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", - "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", - "dev": true, - "requires": { - "nan": "2.10.0" - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -31254,6 +31233,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "dev": true, "requires": { "is-hex-prefixed": "1.0.0" } @@ -31637,6 +31617,7 @@ "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { "is-typedarray": "^1.0.0" } @@ -32252,6 +32233,7 @@ "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215", + "dev": true, "requires": { "bn.js": "^4.10.0", "ethereumjs-util": "^5.0.0" @@ -32331,6 +32313,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -32338,6 +32321,7 @@ "websocket": { "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", "from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2", + "dev": true, "requires": { "debug": "^2.2.0", "nan": "^2.3.3", @@ -32790,7 +32774,8 @@ "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", + "dev": true }, "yallist": { "version": "2.1.2", @@ -35804,11 +35789,6 @@ "space-separated-tokens": "^1.0.0" } }, - "hat": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/hat/-/hat-0.0.3.tgz", - "integrity": "sha1-uwFKnmSzeIrtgAWRdBPU/z1QLYo=" - }, "hdkey": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.7.1.tgz", @@ -36186,12 +36166,6 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz", "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=" }, - "i": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", - "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=", - "dev": true - }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", @@ -36277,11 +36251,6 @@ } } }, - "identicon.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/identicon.js/-/identicon.js-2.3.1.tgz", - "integrity": "sha512-PsxOTpq2Mwj2dgpHW50vcBdSebozcL9xKLIqRVkh2c4lqbCB75pkpdDKoKkVtTfpha/rl4BubXm3Q90vxlmUxQ==" - }, "idna-uts46": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/idna-uts46/-/idna-uts46-1.1.0.tgz", @@ -36724,12 +36693,14 @@ "is-alphabetical": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.1.tgz", - "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=" + "integrity": "sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg=", + "dev": true }, "is-alphanumerical": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz", "integrity": "sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts=", + "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -36758,7 +36729,8 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-builtin-module": { "version": "1.0.0", @@ -36807,7 +36779,8 @@ "is-decimal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz", - "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=" + "integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI=", + "dev": true }, "is-descriptor": { "version": "1.0.2", @@ -36909,7 +36882,8 @@ "is-hexadecimal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz", - "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=" + "integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk=", + "dev": true }, "is-in-browser": { "version": "1.1.3", @@ -37034,7 +37008,8 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true }, "is-plain-object": { "version": "2.0.4", @@ -37193,22 +37168,12 @@ "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", "dev": true }, - "is-whitespace-character": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz", - "integrity": "sha1-muAXbzKCtlRXoZks2whPil+DPjs=" - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "is-word-character": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.1.tgz", - "integrity": "sha1-WgP6HqkazopusMfNdw64bWXIvvs=" - }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -37785,20 +37750,6 @@ } } }, - "jshint-stylish": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jshint-stylish/-/jshint-stylish-2.2.1.tgz", - "integrity": "sha1-JCCCosA1rgP9gQROBXDMQgjPbmE=", - "dev": true, - "requires": { - "beeper": "^1.1.0", - "chalk": "^1.0.0", - "log-symbols": "^1.0.0", - "plur": "^2.1.0", - "string-length": "^1.0.0", - "text-table": "^0.2.0" - } - }, "json-merge-patch": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-merge-patch/-/json-merge-patch-0.2.3.tgz", @@ -39020,7 +38971,8 @@ "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true }, "lodash.restparam": { "version": "3.6.1", @@ -39093,7 +39045,8 @@ "lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=" + "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=", + "dev": true }, "log-driver": { "version": "1.2.5", @@ -39329,11 +39282,6 @@ "object-visit": "^1.0.0" } }, - "markdown-escapes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.1.tgz", - "integrity": "sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg=" - }, "markdown-it": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", @@ -40591,18 +40539,6 @@ "duplexer2": "0.0.2" } }, - "multiplex": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/multiplex/-/multiplex-6.7.0.tgz", - "integrity": "sha1-/3Pk5AB5FwxEQtFgllZY+N75YMI=", - "requires": { - "duplexify": "^3.4.2", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2", - "varint": "^4.0.0", - "xtend": "^4.0.0" - } - }, "mustache": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.0.1.tgz", @@ -40779,12 +40715,6 @@ } } }, - "ncp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz", - "integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=", - "dev": true - }, "nearley": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz", @@ -43223,19 +43153,6 @@ "pbkdf2": "^3.0.3" } }, - "parse-entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.1.tgz", - "integrity": "sha1-gRLYhHExnyerrk1klksSL+ThuJA=", - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -43703,12 +43620,6 @@ } } }, - "pkginfo": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", - "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=", - "dev": true - }, "plucker": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/plucker/-/plucker-0.0.0.tgz", @@ -43906,11 +43817,6 @@ } } }, - "pojo-migrator": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pojo-migrator/-/pojo-migrator-2.1.0.tgz", - "integrity": "sha1-PCo7n4C6Wp+367kh0zRNtO+l9mk=" - }, "polished": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/polished/-/polished-3.4.0.tgz", @@ -45051,28 +44957,6 @@ "function-bind": "^1.1.1" } }, - "prompt": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.0.0.tgz", - "integrity": "sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4=", - "dev": true, - "requires": { - "colors": "^1.1.2", - "pkginfo": "0.x.x", - "read": "1.0.x", - "revalidator": "0.1.x", - "utile": "0.3.x", - "winston": "2.1.x" - }, - "dependencies": { - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - } - } - }, "prop-types": { "version": "15.6.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", @@ -45248,6 +45132,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "dev": true, "requires": { "duplexify": "^3.1.2", "inherits": "^2.0.1", @@ -45258,6 +45143,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -45714,12 +45600,6 @@ } } }, - "react-addons-test-utils": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz", - "integrity": "sha1-wStu/cIkfBDae4dw0YUICnsEcVY=", - "dev": true - }, "react-clientside-effect": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.0.tgz", @@ -46524,18 +46404,6 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.2.tgz", "integrity": "sha512-pbZOSMVVkvppW7XRn9fcHK5OgEDnYLwMva7P6TgS44/SN9uGGjfh3Z1c8tomO+y4IsHQ6Fsz2EGwmE7sMeNZgQ==" }, - "react-markdown": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-3.1.4.tgz", - "integrity": "sha512-i8WueytRXbYzyJ2GemIOTMRx/NigPo8r4m3R/KvWD7r+PxPyc9ke66cI3DR7MBRSS+nVG82VWEgRDE1VaZUCqA==", - "requires": { - "prop-types": "^15.6.0", - "remark-parse": "^4.0.0", - "unified": "^6.1.5", - "unist-util-visit": "^1.1.3", - "xtend": "^4.0.1" - } - }, "react-media": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/react-media/-/react-media-1.8.0.tgz", @@ -46805,24 +46673,6 @@ "object-assign": "^4.1.0" } }, - "react-testutils-additions": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/react-testutils-additions/-/react-testutils-additions-15.3.0.tgz", - "integrity": "sha1-DulqWZj1TivaLPCjQwo0XfBLf2Q=", - "dev": true, - "requires": { - "object-assign": "3.0.0", - "sizzle": "2.3.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, "react-textarea-autosize": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-5.2.1.tgz", @@ -46899,15 +46749,6 @@ "through": "~2.3.4" } }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, "read-all-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", @@ -47331,28 +47172,6 @@ } } }, - "remark-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-4.0.0.tgz", - "integrity": "sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw==", - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", @@ -47402,7 +47221,8 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "repeating": { "version": "2.0.1", @@ -47415,7 +47235,8 @@ "replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true }, "replace-homedir": { "version": "1.0.0", @@ -47686,12 +47507,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "revalidator": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", - "dev": true - }, "rework": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", @@ -47861,49 +47676,6 @@ "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, - "sandwich-expando": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sandwich-expando/-/sandwich-expando-1.1.3.tgz", - "integrity": "sha1-a6eNA0wy+L9atZNMIU+DhGFKiKU=", - "requires": { - "babel-preset-es2015": "^6.6.0", - "babelify": "^7.3.0", - "react": "^15.0.2", - "react-dom": "^15.0.2", - "react-hyperscript": "^2.4.0" - }, - "dependencies": { - "babelify": { - "version": "7.3.0", - "resolved": "https://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" - } - }, - "react": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz", - "integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=", - "requires": { - "create-react-class": "^15.6.0", - "fbjs": "^0.8.9", - "loose-envify": "^1.1.0", - "object-assign": "^4.1.0", - "prop-types": "^15.5.10" - } - }, - "react-hyperscript": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/react-hyperscript/-/react-hyperscript-2.4.2.tgz", - "integrity": "sha1-wZsfWhYcot8QvM5t0imehUepgv4=", - "requires": { - "react": ">= 0.12.0 < 16.0.0" - } - } - } - }, "sass-graph": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", @@ -48338,11 +48110,18 @@ } }, "sha3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.0.tgz", - "integrity": "sha1-aYnxtwpJhwWHajc+LGKs6WqpOZo=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.3.tgz", + "integrity": "sha512-sOWDZi8cDBRkLfWOw18wvJyNblXDHzwMGnRWut8zNNeIeLnmMRO17bjpLc7OzMuj1ASUgx2IyohzUCAl+Kx5vA==", "requires": { - "nan": "^2.0.5" + "nan": "2.13.2" + }, + "dependencies": { + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==" + } } }, "shallow-clone": { @@ -48367,7 +48146,8 @@ "shallow-copy": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true }, "shallow-equal": { "version": "1.1.0", @@ -48655,12 +48435,6 @@ } } }, - "sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha1-TrB4w3IxpWtS5Bk/cB5++JN+YGs=", - "dev": true - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -50136,11 +49910,6 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, - "state-toggle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.0.tgz", - "integrity": "sha1-0g+aYWu08MO5i5GSLSW2QKorxCU=" - }, "static-eval": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", @@ -50454,7 +50223,8 @@ "stream-shift": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true }, "streamroller": { "version": "1.0.5", @@ -50526,15 +50296,6 @@ "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", "integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=" }, - "string-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", - "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=", - "dev": true, - "requires": { - "strip-ansi": "^3.0.0" - } - }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -52417,15 +52178,11 @@ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, - "trim-trailing-lines": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz", - "integrity": "sha1-eu+7eAjfnWafbaLkOMrIxGradoQ=" - }, "trough": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.1.tgz", - "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=" + "integrity": "sha1-qf2LA5Swro//guBjOgo2zK1bX4Y=", + "dev": true }, "true-case-path": { "version": "1.0.2", @@ -52621,15 +52378,6 @@ "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", "dev": true }, - "unherit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.0.tgz", - "integrity": "sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0=", - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } - }, "unicode-5.2.0": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/unicode-5.2.0/-/unicode-5.2.0-0.7.5.tgz", @@ -52664,20 +52412,6 @@ "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, - "unified": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.1.6.tgz", - "integrity": "sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w==", - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-function": "^1.0.4", - "x-is-string": "^0.1.0" - } - }, "union": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", @@ -52763,31 +52497,11 @@ "crypto-random-string": "^1.0.0" } }, - "unist-util-is": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.1.tgz", - "integrity": "sha1-DDEmKeP5YMZukx6BLT2A53AQlHs=" - }, - "unist-util-remove-position": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz", - "integrity": "sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs=", - "requires": { - "unist-util-visit": "^1.1.0" - } - }, "unist-util-stringify-position": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz", - "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=" - }, - "unist-util-visit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.0.tgz", - "integrity": "sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ==", - "requires": { - "unist-util-is": "^2.1.1" - } + "integrity": "sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw=", + "dev": true }, "universalify": { "version": "0.1.1", @@ -53131,34 +52845,6 @@ "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", "dev": true }, - "utile": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/utile/-/utile-0.3.0.tgz", - "integrity": "sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo=", - "dev": true, - "requires": { - "async": "~0.9.0", - "deep-equal": "~0.2.1", - "i": "0.3.x", - "mkdirp": "0.x.x", - "ncp": "1.0.x", - "rimraf": "2.x.x" - }, - "dependencies": { - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "deep-equal": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", - "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", - "dev": true - } - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -53204,11 +52890,6 @@ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, - "varint": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/varint/-/varint-4.0.1.tgz", - "integrity": "sha1-SQgpuULSSEY7KzUJeZXDv3NxmOk=" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -53225,26 +52906,11 @@ "extsprintf": "^1.2.0" } }, - "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } - }, - "vfile-location": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.2.tgz", - "integrity": "sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU=" - }, "vfile-message": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.0.tgz", "integrity": "sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw==", + "dev": true, "requires": { "unist-util-stringify-position": "^1.1.1" } @@ -54684,41 +54350,6 @@ "execa": "^1.0.0" } }, - "winston": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz", - "integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=", - "dev": true, - "requires": { - "async": "~1.0.0", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "pkginfo": "0.3.x", - "stack-trace": "0.0.x" - }, - "dependencies": { - "async": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", - "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=", - "dev": true - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true - }, - "pkginfo": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", - "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", - "dev": true - } - } - }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -54804,15 +54435,11 @@ "ultron": "~1.1.0" } }, - "x-is-function": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/x-is-function/-/x-is-function-1.0.4.tgz", - "integrity": "sha1-XSlNw9Joy90GJYDgxd93o5HR+h4=" - }, "x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true }, "xdg-basedir": { "version": "3.0.0", diff --git a/package.json b/package.json index c9c3bd633..af4c83af5 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "lint": "eslint .", "lint:fix": "eslint . --fix", "mozilla-lint": "addons-linter dist/firefox", - "watch": "mocha watch --recursive \"test/unit/**/*.js\"", + "watch": "cross-env METAMASK_ENV=test mocha --watch --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", "disc": "gulp disc --debug", "announce": "node development/announcer.js", "version:bump": "node development/run-version-bump.js", @@ -48,7 +48,6 @@ "browserify": { "transform": [ "babelify", - "reactify", "brfs" ] }, @@ -84,12 +83,9 @@ "disc": "^1.3.2", "dnode": "^1.2.2", "end-of-stream": "^1.1.0", - "ensnare": "^1.0.0", - "eth-bin-to-ops": "^1.0.1", "eth-block-tracker": "^4.1.0", "eth-contract-metadata": "github:MetaMask/eth-contract-metadata#dc68506221859bc90792bc5e0279a6835f2484d8", "eth-ens-namehash": "^2.0.8", - "eth-hd-keyring": "^1.2.2", "eth-json-rpc-filters": "^3.0.4", "eth-json-rpc-infura": "^3.2.0", "eth-keyring-controller": "^3.3.1", @@ -109,39 +105,31 @@ "ethjs-contract": "^0.2.3", "ethjs-ens": "^2.0.0", "ethjs-query": "^0.3.4", - "extension-link-enabler": "^1.0.0", "extension-port-stream": "^1.0.0", "extensionizer": "^1.0.1", "fast-json-patch": "^2.0.4", - "fast-levenshtein": "^2.0.6", "fuse.js": "^3.2.0", "gaba": "^1.3.0", - "hat": "0.0.3", "human-standard-token-abi": "^2.0.0", - "identicon.js": "^2.3.1", "inject-css": "^0.1.1", "jazzicon": "^1.2.0", "json-rpc-engine": "^4.0.0", "json-rpc-middleware-stream": "^2.1.1", "jsonschema": "^1.2.4", "lodash.debounce": "^4.0.8", - "lodash.memoize": "^4.1.2", "lodash.shuffle": "^4.2.0", - "lodash.uniqby": "^4.7.0", "loglevel": "^1.4.1", "luxon": "^1.8.2", "metamask-inpage-provider": "^1.3.0", "metamask-logo": "^2.1.4", "mkdirp": "^0.5.1", "multihashes": "^0.4.12", - "multiplex": "^6.7.0", "nonce-tracker": "^1.0.0", "number-to-bn": "^1.7.0", "obj-multiplex": "^1.0.0", "obs-store": "^3.0.2", "percentile": "^1.2.0", "pify": "^3.0.0", - "pojo-migrator": "^2.1.0", "polyfill-crypto.getrandomvalues": "^1.0.0", "post-message-stream": "^3.0.0", "promise-filter": "^1.1.0", @@ -149,7 +137,6 @@ "prop-types": "^15.6.1", "pubnub": "^4.21.5", "pump": "^3.0.0", - "pumpify": "^1.3.4", "qrcode-generator": "1.4.1", "ramda": "^0.24.1", "react": "^15.6.2", @@ -160,7 +147,6 @@ "react-hyperscript": "^3.0.0", "react-idle-timer": "^4.2.5", "react-inspector": "^2.3.0", - "react-markdown": "^3.0.0", "react-media": "^1.8.0", "react-redux": "^5.0.5", "react-router-dom": "^4.2.2", @@ -180,10 +166,6 @@ "request-promise": "^4.2.1", "reselect": "^3.0.1", "safe-event-emitter": "^1.0.1", - "sandwich-expando": "^1.1.3", - "semaphore": "^1.0.5", - "semver": "^5.4.1", - "shallow-copy": "0.0.1", "single-call-balance-checker-abi": "^1.0.0", "swappable-obj-proxy": "^1.1.0", "textarea-caret": "^3.0.1", @@ -198,9 +180,9 @@ "@storybook/addon-info": "^5.1.1", "@storybook/addon-knobs": "^3.4.2", "@storybook/react": "^5.1.1", + "abortcontroller-polyfill": "^1.3.0", "addons-linter": "^1.10.0", "babel-core": "^6.26.3", - "abortcontroller-polyfill": "^1.3.0", "babel-eslint": "^8.0.0", "babel-plugin-transform-async-to-generator": "^6.24.1", "babel-plugin-transform-runtime": "^6.23.0", @@ -261,7 +243,6 @@ "jsdoc": "^3.6.2", "jsdom": "^11.2.0", "jsdom-global": "^3.0.2", - "jshint-stylish": "~2.2.1", "karma": "^4.1.0", "karma-chrome-launcher": "^2.2.0", "karma-cli": "^1.0.1", @@ -278,14 +259,11 @@ "path": "^0.12.7", "png-file-stream": "^1.1.0", "prepend-file": "^1.3.1", - "prompt": "^1.0.0", "proxyquire": "2.0.1", "qs": "^6.2.0", "qunitjs": "^2.4.1", "radgrad-jsdoc-template": "^1.1.3", - "react-addons-test-utils": "^15.5.1", "react-test-renderer": "^15.6.2", - "react-testutils-additions": "^15.2.0", "redux-mock-store": "^1.5.3", "redux-test-utils": "^0.2.2", "resolve-url-loader": "^2.3.0", diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 4ccade2aa..72dbbc4a1 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -93,6 +93,37 @@ describe('TransactionStateManager', function () { assert.equal(result[0].id, 1) }) + it('throws error and does not add tx if txParams are invalid', function () { + const validTxParams = { + from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + to: '0x0039f22efb07a647557c7c5d17854cfd6d489ef3', + nonce: '0x3', + gas: '0x77359400', + gasPrice: '0x77359400', + value: '0x0', + data: '0x0', + } + const invalidValues = [1, true, {}, Symbol('1')] + + for (const key in validTxParams) { + for (const value of invalidValues) { + const tx = { + id: 1, + status: 'unapproved', + metamaskNetworkId: currentNetworkId, + txParams: { + ...validTxParams, + [key]: value, + }, + } + assert.throws(txStateManager.addTx.bind(txStateManager, tx), 'addTx should throw error') + const result = txStateManager.getTxList() + assert.ok(Array.isArray(result), 'txList should be an array') + assert.equal(result.length, 0, 'txList should be empty') + } + } + }) + it('does not override txs from other networks', function () { const tx = { id: 1, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {} } const tx2 = { id: 2, status: 'confirmed', metamaskNetworkId: otherNetworkId, txParams: {} } @@ -153,6 +184,37 @@ describe('TransactionStateManager', function () { assert.equal(result.hash, 'foo') }) + it('throws error and does not update tx if txParams are invalid', function () { + const validTxParams = { + from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + to: '0x0039f22efb07a647557c7c5d17854cfd6d489ef3', + nonce: '0x3', + gas: '0x77359400', + gasPrice: '0x77359400', + value: '0x0', + data: '0x0', + } + const invalidValues = [1, true, {}, Symbol('1')] + + txStateManager.addTx({ id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: validTxParams }) + + for (const key in validTxParams) { + for (const value of invalidValues) { + const originalTx = txStateManager.getTx(1) + const newTx = { + ...originalTx, + txParams: { + ...originalTx.txParams, + [key]: value, + }, + } + assert.throws(txStateManager.updateTx.bind(txStateManager, newTx), 'updateTx should throw an error') + const result = txStateManager.getTx(1) + assert.deepEqual(result, originalTx, 'tx should not be updated') + } + } + }) + it('updates gas price and adds history items', function () { const originalGasPrice = '0x01' const desiredGasPrice = '0x02' diff --git a/ui/app/components/app/modals/account-details-modal.js b/ui/app/components/app/modals/account-details-modal.js deleted file mode 100644 index 6cffc918b..000000000 --- a/ui/app/components/app/modals/account-details-modal.js +++ /dev/null @@ -1,107 +0,0 @@ -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('../../../store/actions') -const AccountModalContainer = require('./account-modal-container') -const { getSelectedIdentity, getRpcPrefsForCurrentProvider } = require('../../../selectors/selectors') -const genAccountLink = require('../../../../lib/account-link.js') -const QrView = require('../../ui/qr-code') -const EditableLabel = require('../../ui/editable-label') - -import Button from '../../ui/button' - -function mapStateToProps (state) { - return { - network: state.metamask.network, - selectedIdentity: getSelectedIdentity(state), - keyrings: state.metamask.keyrings, - rpcPrefs: getRpcPrefsForCurrentProvider(state), - } -} - -function mapDispatchToProps (dispatch) { - return { - // Is this supposed to be used somewhere? - showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), - showExportPrivateKeyModal: () => { - dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) - }, - hideModal: () => dispatch(actions.hideModal()), - setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)), - } -} - -inherits(AccountDetailsModal, Component) -function AccountDetailsModal () { - Component.call(this) -} - -AccountDetailsModal.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) - - -// Not yet pixel perfect todos: - // fonts of qr-header - -AccountDetailsModal.prototype.render = function () { - const { - selectedIdentity, - network, - showExportPrivateKeyModal, - setAccountLabel, - keyrings, - rpcPrefs, - } = this.props - const { name, address } = selectedIdentity - - const keyring = keyrings.find((kr) => { - return kr.accounts.includes(address) - }) - - let exportPrivateKeyFeatureEnabled = true - // This feature is disabled for hardware wallets - if (keyring && keyring.type.search('Hardware') !== -1) { - exportPrivateKeyFeatureEnabled = false - } - - return h(AccountModalContainer, {}, [ - h(EditableLabel, { - className: 'account-modal__name', - defaultValue: name, - onSubmit: label => setAccountLabel(address, label), - }), - - h(QrView, { - Qr: { - data: address, - network: network, - }, - }), - - h('div.account-modal-divider'), - - h(Button, { - type: 'secondary', - className: 'account-modal__button', - onClick: () => { - global.platform.openWindow({ url: genAccountLink(address, network, rpcPrefs) }) - }, - }, (rpcPrefs.blockExplorerUrl - ? this.context.t('blockExplorerView', [rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1]]) - : this.context.t('viewOnEtherscan'))), - - // Holding on redesign for Export Private Key functionality - - exportPrivateKeyFeatureEnabled ? h(Button, { - type: 'secondary', - className: 'account-modal__button', - onClick: () => showExportPrivateKeyModal(), - }, this.context.t('exportPrivateKey')) : null, - - ]) -} diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js new file mode 100644 index 000000000..e3919edcf --- /dev/null +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js @@ -0,0 +1,87 @@ +import React, { Component} from 'react' +import PropTypes from 'prop-types' +import AccountModalContainer from '../account-modal-container' +import genAccountLink from '../../../../../lib/account-link.js' +import QrView from '../../../ui/qr-code' +import EditableLabel from '../../../ui/editable-label' +import Button from '../../../ui/button' + +export default class AccountDetailsModal extends Component { + static propTypes = { + selectedIdentity: PropTypes.object, + network: PropTypes.string, + showExportPrivateKeyModal: PropTypes.func, + setAccountLabel: PropTypes.func, + keyrings: PropTypes.array, + rpcPrefs: PropTypes.object, + } + + static contextTypes = { + t: PropTypes.func, + } + + render () { + const { + selectedIdentity, + network, + showExportPrivateKeyModal, + setAccountLabel, + keyrings, + rpcPrefs, + } = this.props + const { name, address } = selectedIdentity + + const keyring = keyrings.find((kr) => { + return kr.accounts.includes(address) + }) + + let exportPrivateKeyFeatureEnabled = true + // This feature is disabled for hardware wallets + if (keyring && keyring.type.search('Hardware') !== -1) { + exportPrivateKeyFeatureEnabled = false + } + + return ( + <AccountModalContainer> + <EditableLabel + className="account-modal__name" + defaultValue={name} + onSubmit={label => setAccountLabel(address, label)} + /> + + <QrView + Qr={{ + data: address, + network: network, + }} + /> + + <div className="account-modal-divider"/> + + <Button + type="secondary" + className="account-modal__button" + onClick={() => { + global.platform.openWindow({ url: genAccountLink(address, network, rpcPrefs) }) + }} + > + {rpcPrefs.blockExplorerUrl + ? this.context.t('blockExplorerView', [rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1]]) + : this.context.t('viewOnEtherscan') + } + </Button> + + {exportPrivateKeyFeatureEnabled + ? <Button + type="secondary" + className="account-modal__button" + onClick={() => showExportPrivateKeyModal()} + > + {this.context.t('exportPrivateKey')} + </Button> + : null + } + </AccountModalContainer> + ) + } +} diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js b/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js new file mode 100644 index 000000000..4b2283ced --- /dev/null +++ b/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js @@ -0,0 +1,27 @@ +import { connect } from 'react-redux' +import actions from '../../../../store/actions' +import { getSelectedIdentity, getRpcPrefsForCurrentProvider } from '../../../../selectors/selectors' +import AccountDetailsModal from './account-details-modal.component' + +const mapStateToProps = (state) => { + return { + network: state.metamask.network, + selectedIdentity: getSelectedIdentity(state), + keyrings: state.metamask.keyrings, + rpcPrefs: getRpcPrefsForCurrentProvider(state), + } +} + +const mapDispatchToProps = (dispatch) => { + return { + // Is this supposed to be used somewhere? + showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)), + showExportPrivateKeyModal: () => { + dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) + }, + hideModal: () => dispatch(actions.hideModal()), + setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)), + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal) diff --git a/ui/app/components/app/modals/account-details-modal/index.js b/ui/app/components/app/modals/account-details-modal/index.js new file mode 100644 index 000000000..433f4d170 --- /dev/null +++ b/ui/app/components/app/modals/account-details-modal/index.js @@ -0,0 +1 @@ +export { default } from './account-details-modal.container' diff --git a/ui/app/components/app/modals/deposit-ether-modal.js b/ui/app/components/app/modals/deposit-ether-modal.js index f56069d65..20c4d018c 100644 --- a/ui/app/components/app/modals/deposit-ether-modal.js +++ b/ui/app/components/app/modals/deposit-ether-modal.js @@ -5,7 +5,6 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../../store/actions') const { getNetworkDisplayName } = require('../../../../../app/scripts/controllers/network/util') -const ShapeshiftForm = require('../shapeshift-form') import Button from '../../ui/button' @@ -13,8 +12,6 @@ let DIRECT_DEPOSIT_ROW_TITLE let DIRECT_DEPOSIT_ROW_TEXT let WYRE_ROW_TITLE let WYRE_ROW_TEXT -let SHAPESHIFT_ROW_TITLE -let SHAPESHIFT_ROW_TEXT let FAUCET_ROW_TITLE let COINSWITCH_ROW_TITLE let COINSWITCH_ROW_TEXT @@ -56,15 +53,9 @@ function DepositEtherModal (_, context) { DIRECT_DEPOSIT_ROW_TEXT = context.t('directDepositEtherExplainer') WYRE_ROW_TITLE = context.t('buyWithWyre') WYRE_ROW_TEXT = context.t('buyWithWyreDescription') - SHAPESHIFT_ROW_TITLE = context.t('depositShapeShift') - SHAPESHIFT_ROW_TEXT = context.t('depositShapeShiftExplainer') FAUCET_ROW_TITLE = context.t('testFaucet') COINSWITCH_ROW_TITLE = context.t('buyCoinSwitch') COINSWITCH_ROW_TEXT = context.t('buyCoinSwitchExplainer') - - this.state = { - buyingWithShapeshift: false, - } } DepositEtherModal.contextTypes = { @@ -131,7 +122,6 @@ DepositEtherModal.prototype.renderRow = function ({ DepositEtherModal.prototype.render = function () { const { network, toWyre, toCoinSwitch, address, toFaucet } = this.props - const { buyingWithShapeshift } = this.state const isTestNetwork = ['3', '4', '5', '42'].find(n => n === network) const networkName = getNetworkDisplayName(network) @@ -148,7 +138,6 @@ DepositEtherModal.prototype.render = function () { h('div.page-container__header-close', { onClick: () => { - this.setState({ buyingWithShapeshift: false }) this.props.hideWarning() this.props.hideModal() }, @@ -168,7 +157,6 @@ DepositEtherModal.prototype.render = function () { text: DIRECT_DEPOSIT_ROW_TEXT, buttonLabel: this.context.t('viewAccount'), onButtonClick: () => this.goToAccountDetailsModal(), - hide: buyingWithShapeshift, }), this.renderRow({ @@ -177,7 +165,7 @@ DepositEtherModal.prototype.render = function () { text: this.facuetRowText(networkName), buttonLabel: this.context.t('getEther'), onButtonClick: () => toFaucet(network), - hide: !isTestNetwork || buyingWithShapeshift, + hide: !isTestNetwork, }), this.renderRow({ @@ -191,7 +179,7 @@ DepositEtherModal.prototype.render = function () { text: WYRE_ROW_TEXT, buttonLabel: this.context.t('continueToWyre'), onButtonClick: () => toWyre(address), - hide: isTestNetwork || buyingWithShapeshift, + hide: isTestNetwork, }), this.renderRow({ @@ -205,29 +193,9 @@ DepositEtherModal.prototype.render = function () { text: COINSWITCH_ROW_TEXT, buttonLabel: this.context.t('continueToCoinSwitch'), onButtonClick: () => toCoinSwitch(address), - hide: isTestNetwork || buyingWithShapeshift, - }), - - this.renderRow({ - logo: h('div.deposit-ether-modal__logo', { - style: { - backgroundImage: 'url(\'./images/shapeshift logo.png\')', - }, - }), - title: SHAPESHIFT_ROW_TITLE, - text: SHAPESHIFT_ROW_TEXT, - buttonLabel: this.context.t('shapeshiftBuy'), - onButtonClick: () => this.setState({ buyingWithShapeshift: true }), hide: isTestNetwork, - hideButton: buyingWithShapeshift, - hideTitle: buyingWithShapeshift, - onBackClick: () => this.setState({ buyingWithShapeshift: false }), - showBackButton: this.state.buyingWithShapeshift, - className: buyingWithShapeshift && 'deposit-ether-modal__buy-row__shapeshift-buy', }), - buyingWithShapeshift && h(ShapeshiftForm), - ]), ]), diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 717f623af..394367c46 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -12,11 +12,10 @@ const { ENVIRONMENT_TYPE_POPUP } = require('../../../../../app/scripts/lib/enums // Modal Components const BuyOptions = require('./buy-options-modal') const DepositEtherModal = require('./deposit-ether-modal') -const AccountDetailsModal = require('./account-details-modal') +import AccountDetailsModal from './account-details-modal' const EditAccountNameModal = require('./edit-account-name-modal') const ExportPrivateKeyModal = require('./export-private-key-modal') const NewAccountModal = require('./new-account-modal') -const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const NotifcationModal = require('./notification-modal') const QRScanner = require('./qr-scanner') @@ -181,13 +180,6 @@ const MODALS = { ...accountModalStyle, }, - SHAPESHIFT_DEPOSIT_TX: { - contents: [ - h(ShapeshiftDepositTxModal), - ], - ...accountModalStyle, - }, - HIDE_TOKEN_CONFIRMATION: { contents: [ h(HideTokenConfirmationModal, {}, []), diff --git a/ui/app/components/app/modals/shapeshift-deposit-tx-modal.js b/ui/app/components/app/modals/shapeshift-deposit-tx-modal.js deleted file mode 100644 index ada9430f7..000000000 --- a/ui/app/components/app/modals/shapeshift-deposit-tx-modal.js +++ /dev/null @@ -1,40 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const inherits = require('util').inherits -const connect = require('react-redux').connect -const actions = require('../../../store/actions') -const QrView = require('../../ui/qr-code') -const AccountModalContainer = require('./account-modal-container') - -function mapStateToProps (state) { - return { - Qr: state.appState.modal.modalState.props.Qr, - } -} - -function mapDispatchToProps (dispatch) { - return { - hideModal: () => { - dispatch(actions.hideModal()) - }, - } -} - -inherits(ShapeshiftDepositTxModal, Component) -function ShapeshiftDepositTxModal () { - Component.call(this) - -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftDepositTxModal) - -ShapeshiftDepositTxModal.prototype.render = function () { - const { Qr } = this.props - - return h(AccountModalContainer, { - }, [ - h('div', {}, [ - h(QrView, {key: 'qr', Qr}), - ]), - ]) -} diff --git a/ui/app/components/app/shapeshift-form.js b/ui/app/components/app/shapeshift-form.js deleted file mode 100644 index 34a6f3acd..000000000 --- a/ui/app/components/app/shapeshift-form.js +++ /dev/null @@ -1,256 +0,0 @@ -const h = require('react-hyperscript') -const inherits = require('util').inherits -const PropTypes = require('prop-types') -const Component = require('react').Component -const connect = require('react-redux').connect -const classnames = require('classnames') -const qrcode = require('qrcode-generator') -const { shapeShiftSubview, pairUpdate, buyWithShapeShift } = require('../../store/actions') -const { isValidAddress } = require('../../helpers/utils/util') -const SimpleDropdown = require('./dropdowns/simple-dropdown') - -import Button from '../ui/button' - -function mapStateToProps (state) { - const { - coinOptions, - tokenExchangeRates, - selectedAddress, - } = state.metamask - const { warning } = state.appState - - return { - coinOptions, - tokenExchangeRates, - selectedAddress, - warning, - } -} - -function mapDispatchToProps (dispatch) { - return { - shapeShiftSubview: () => dispatch(shapeShiftSubview()), - pairUpdate: coin => dispatch(pairUpdate(coin)), - buyWithShapeShift: data => dispatch(buyWithShapeShift(data)), - } -} - -ShapeshiftForm.contextTypes = { - t: PropTypes.func, -} - -module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftForm) - - -inherits(ShapeshiftForm, Component) -function ShapeshiftForm () { - Component.call(this) - - this.state = { - depositCoin: 'btc', - refundAddress: '', - showQrCode: false, - depositAddress: '', - errorMessage: '', - isLoading: false, - bought: false, - } -} - -ShapeshiftForm.prototype.getCoinPair = function () { - return `${this.state.depositCoin.toUpperCase()}_ETH` -} - -ShapeshiftForm.prototype.componentWillMount = function () { - this.props.shapeShiftSubview() -} - -ShapeshiftForm.prototype.onCoinChange = function (coin) { - this.setState({ - depositCoin: coin, - errorMessage: '', - }) - this.props.pairUpdate(coin) -} - -ShapeshiftForm.prototype.onBuyWithShapeShift = function () { - this.setState({ - isLoading: true, - showQrCode: true, - }) - - const { - buyWithShapeShift, - selectedAddress: withdrawal, - } = this.props - const { - refundAddress: returnAddress, - depositCoin, - } = this.state - const pair = `${depositCoin}_eth` - const data = { - withdrawal, - pair, - returnAddress, - // Public api key - 'apiKey': '803d1f5df2ed1b1476e4b9e6bcd089e34d8874595dda6a23b67d93c56ea9cc2445e98a6748b219b2b6ad654d9f075f1f1db139abfa93158c04e825db122c14b6', - } - - if (isValidAddress(withdrawal)) { - buyWithShapeShift(data) - .then(d => this.setState({ - showQrCode: true, - depositAddress: d.deposit, - isLoading: false, - })) - .catch(() => this.setState({ - showQrCode: false, - errorMessage: this.context.t('invalidRequest'), - isLoading: false, - })) - } -} - -ShapeshiftForm.prototype.renderMetadata = function (label, value) { - return h('div', {className: 'shapeshift-form__metadata-wrapper'}, [ - - h('div.shapeshift-form__metadata-label', {}, [ - h('span', `${label}:`), - ]), - - h('div.shapeshift-form__metadata-value', {}, [ - h('span', value), - ]), - - ]) -} - -ShapeshiftForm.prototype.renderMarketInfo = function () { - const { tokenExchangeRates } = this.props - const { - limit, - rate, - minimum, - } = tokenExchangeRates[this.getCoinPair()] || {} - - return h('div.shapeshift-form__metadata', {}, [ - - this.renderMetadata(this.context.t('status'), limit ? this.context.t('available') : this.context.t('unavailable')), - this.renderMetadata(this.context.t('limit'), limit), - this.renderMetadata(this.context.t('exchangeRate'), rate), - this.renderMetadata(this.context.t('min'), minimum), - - ]) -} - -ShapeshiftForm.prototype.renderQrCode = function () { - const { depositAddress, isLoading, depositCoin } = this.state - const qrImage = qrcode(4, 'M') - qrImage.addData(depositAddress) - qrImage.make() - - return h('div.shapeshift-form', {}, [ - - h('div.shapeshift-form__deposit-instruction', [ - this.context.t('depositCoin', [depositCoin.toUpperCase()]), - ]), - - h('div', depositAddress), - - h('div.shapeshift-form__qr-code', [ - isLoading - ? h('img', { - src: 'images/loading.svg', - style: { width: '60px'}, - }) - : h('div', { - dangerouslySetInnerHTML: { __html: qrImage.createTableTag(4) }, - }), - ]), - - this.renderMarketInfo(), - - ]) -} - - -ShapeshiftForm.prototype.render = function () { - const { coinOptions, btnClass, warning } = this.props - const { errorMessage, showQrCode, depositAddress } = this.state - const { tokenExchangeRates } = this.props - const token = tokenExchangeRates[this.getCoinPair()] - - return h('div.shapeshift-form-wrapper', [ - showQrCode - ? this.renderQrCode() - : h('div.modal-shapeshift-form', [ - h('div.shapeshift-form__selectors', [ - - h('div.shapeshift-form__selector', [ - - h('div.shapeshift-form__selector-label', this.context.t('deposit')), - - h(SimpleDropdown, { - selectedOption: this.state.depositCoin, - onSelect: (coin) => this.onCoinChange(coin), - options: Object.entries(coinOptions).map(([coin]) => ({ - value: coin.toLowerCase(), - displayValue: coin, - })), - }), - - ]), - - h('div.icon.shapeshift-form__caret', { - style: { backgroundImage: 'url(images/caret-right.svg)'}, - }), - - h('div.shapeshift-form__selector', [ - - h('div.shapeshift-form__selector-label', [ - this.context.t('receive'), - ]), - - h('div.shapeshift-form__selector-input', ['ETH']), - - ]), - - ]), - - warning && h('div.shapeshift-form__address-input-label', warning), - - !warning && h('div', { - className: classnames('shapeshift-form__address-input-wrapper', { - 'shapeshift-form__address-input-wrapper--error': errorMessage, - }), - }, [ - - h('div.shapeshift-form__address-input-label', [ - this.context.t('refundAddress'), - ]), - - h('input.shapeshift-form__address-input', { - type: 'text', - onChange: e => this.setState({ - refundAddress: e.target.value, - errorMessage: '', - }), - }), - - h('divshapeshift-form__address-input-error-message', [errorMessage]), - ]), - - !warning && this.renderMarketInfo(), - - ]), - - !depositAddress && h(Button, { - type: 'secondary', - large: true, - className: `${btnClass} shapeshift-form__shapeshift-buy-btn`, - disabled: !token, - onClick: () => this.onBuyWithShapeShift(), - }, [this.context.t('buy')]), - - ]) -} diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js index 5092d277e..a2fb5a3bf 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js @@ -30,10 +30,21 @@ export default class ImportWithSeedPhrase extends PureComponent { } parseSeedPhrase = (seedPhrase) => { - return seedPhrase - .trim() - .match(/\w+/g) - .join(' ') + if (!seedPhrase) { + return '' + } + + const trimmed = seedPhrase.trim() + if (!trimmed) { + return '' + } + + const words = trimmed.match(/\w+/g) + if (!words) { + return '' + } + + return words.join(' ') } componentWillMount () { diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js new file mode 100644 index 000000000..7960d17b2 --- /dev/null +++ b/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/tests/import-with-seed-phrase.component.test.js @@ -0,0 +1,78 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import sinon from 'sinon' +import ImportWithSeedPhrase from '../import-with-seed-phrase.component' + +function shallowRender (props = {}, context = {}) { + return shallow(<ImportWithSeedPhrase {...props} />, { + context: { + t: str => str + '_t', + metricsEvent: sinon.spy(), + ...context, + }, + }) +} + +describe('ImportWithSeedPhrase Component', () => { + it('should render without error', () => { + const root = shallowRender({ + onSubmit: sinon.spy(), + }) + const textareaCount = root.find('.first-time-flow__textarea').length + assert.equal(textareaCount, 1, 'should render 12 seed phrases') + }) + + describe('parseSeedPhrase', () => { + it('should handle a regular seed phrase', () => { + const root = shallowRender({ + onSubmit: sinon.spy(), + }) + + const {parseSeedPhrase} = root.instance() + + assert.deepEqual(parseSeedPhrase('foo bar baz'), 'foo bar baz') + }) + + it('should trim extraneous whitespace from the given seed phrase', () => { + const root = shallowRender({ + onSubmit: sinon.spy(), + }) + + const {parseSeedPhrase} = root.instance() + + assert.deepEqual(parseSeedPhrase(' foo bar baz '), 'foo bar baz') + }) + + it('should return an empty string when given a whitespace-only string', () => { + const root = shallowRender({ + onSubmit: sinon.spy(), + }) + + const {parseSeedPhrase} = root.instance() + + assert.deepEqual(parseSeedPhrase(' '), '') + }) + + it('should return an empty string when given a string with only symbols', () => { + const root = shallowRender({ + onSubmit: sinon.spy(), + }) + + const {parseSeedPhrase} = root.instance() + + assert.deepEqual(parseSeedPhrase('$'), '') + }) + + it('should return an empty string for both null and undefined', () => { + const root = shallowRender({ + onSubmit: sinon.spy(), + }) + + const {parseSeedPhrase} = root.instance() + + assert.deepEqual(parseSeedPhrase(undefined), '') + assert.deepEqual(parseSeedPhrase(null), '') + }) + }) +}) diff --git a/ui/app/pages/first-time-flow/first-time-flow.component.js b/ui/app/pages/first-time-flow/first-time-flow.component.js index bf6e80ca9..0d206bf42 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.component.js +++ b/ui/app/pages/first-time-flow/first-time-flow.component.js @@ -29,7 +29,7 @@ export default class FirstTimeFlow extends PureComponent { isInitialized: PropTypes.bool, isUnlocked: PropTypes.bool, unlockAccount: PropTypes.func, - nextRoute: PropTypes.func, + nextRoute: PropTypes.string, } state = { diff --git a/ui/app/pages/keychains/restore-vault.js b/ui/app/pages/keychains/restore-vault.js index 574949258..08164fd9f 100644 --- a/ui/app/pages/keychains/restore-vault.js +++ b/ui/app/pages/keychains/restore-vault.js @@ -123,6 +123,7 @@ class RestoreVaultPage extends Component { className="import-account__back-button" onClick={e => { e.preventDefault() + this.props.leaveImportSeedScreenState() this.props.history.goBack() }} href="#" diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index d3cc7efca..3ed82044d 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -2391,10 +2391,6 @@ function reshowQrCode (data, coin) { dispatch(actions.hideLoadingIndication()) return dispatch(actions.showQrView(data, message)) - // return dispatch(actions.showModal({ - // name: 'SHAPESHIFT_DEPOSIT_TX', - // Qr: { data, message }, - // })) }) } } |