mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Merge branch 'develop' into no-inject-ani-gamer
This commit is contained in:
commit
1d241bef76
4
.babelrc
4
.babelrc
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"presets": ["es2015", "stage-0", "react"],
|
"presets": [["env", { "debug": true }], "react", "stage-0"],
|
||||||
"plugins": ["transform-runtime", "transform-async-to-generator"]
|
"plugins": ["transform-runtime", "transform-async-to-generator", "transform-class-properties"]
|
||||||
}
|
}
|
||||||
|
@ -102,30 +102,29 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- dependency-cache-{{ checksum "package-lock.json" }}
|
- v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
# fallback to using the latest cache if no exact match is found
|
# fallback to using the latest cache if no exact match is found
|
||||||
- dependency-cache-
|
- v1.0-dependency-cache-
|
||||||
- run:
|
- run:
|
||||||
name: Install npm 6 + deps via npm
|
name: Install npm 6 + deps via npm
|
||||||
command: |
|
command: |
|
||||||
sudo npm install -g npm@6.1.0 && npm install
|
sudo npm install -g npm@6.1.0 && npm install --no-save
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
paths:
|
paths:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
prep-deps-firefox:
|
prep-deps-firefox:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:8.11.3-browsers
|
- image: circleci/node:8.11.3-browsers
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-firefox-
|
key: v1.0-dependency-cache-firefox-
|
||||||
- run:
|
- run:
|
||||||
name: Download Firefox If needed
|
name: Download Firefox If needed
|
||||||
command: ./.circleci/scripts/firefox-download.sh
|
command: ./.circleci/scripts/firefox-download.sh
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: dependency-cache-firefox-
|
key: v1.0-dependency-cache-firefox-
|
||||||
paths:
|
paths:
|
||||||
- firefox
|
- firefox
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: build:dist
|
name: build:dist
|
||||||
command: npm run dist
|
command: npm run dist
|
||||||
@ -154,7 +153,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: build:dist
|
name: build:dist
|
||||||
command: npm run doc
|
command: npm run doc
|
||||||
@ -169,7 +168,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Get Scss Cache key
|
name: Get Scss Cache key
|
||||||
# this allows us to checksum against a whole directory
|
# this allows us to checksum against a whole directory
|
||||||
@ -188,7 +187,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Test
|
name: Test
|
||||||
command: npm run lint
|
command: npm run lint
|
||||||
@ -199,7 +198,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Test
|
name: Test
|
||||||
command: npx nsp check
|
command: npx nsp check
|
||||||
@ -210,7 +209,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- run:
|
- run:
|
||||||
@ -226,12 +225,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-firefox-
|
key: v1.0-dependency-cache-firefox-
|
||||||
- run:
|
- run:
|
||||||
name: Install firefox
|
name: Install firefox
|
||||||
command: ./.circleci/scripts/firefox-install.sh
|
command: ./.circleci/scripts/firefox-install.sh
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- run:
|
- run:
|
||||||
@ -247,7 +246,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- run:
|
- run:
|
||||||
@ -263,12 +262,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-firefox-
|
key: v1.0-dependency-cache-firefox-
|
||||||
- run:
|
- run:
|
||||||
name: Install firefox
|
name: Install firefox
|
||||||
command: ./.circleci/scripts/firefox-install.sh
|
command: ./.circleci/scripts/firefox-install.sh
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- run:
|
- run:
|
||||||
@ -284,7 +283,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- run:
|
- run:
|
||||||
@ -301,7 +300,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
@ -328,7 +327,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: build-cache-{{ .Revision }}
|
key: build-cache-{{ .Revision }}
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
@ -351,7 +350,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: test:coverage
|
name: test:coverage
|
||||||
command: npm run test:coverage
|
command: npm run test:coverage
|
||||||
@ -364,12 +363,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-firefox-
|
key: v1.0-dependency-cache-firefox-
|
||||||
- run:
|
- run:
|
||||||
name: Install firefox
|
name: Install firefox
|
||||||
command: ./.circleci/scripts/firefox-install.sh
|
command: ./.circleci/scripts/firefox-install.sh
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Get Scss Cache key
|
name: Get Scss Cache key
|
||||||
# this allows us to checksum against a whole directory
|
# this allows us to checksum against a whole directory
|
||||||
@ -388,7 +387,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Get Scss Cache key
|
name: Get Scss Cache key
|
||||||
# this allows us to checksum against a whole directory
|
# this allows us to checksum against a whole directory
|
||||||
@ -407,12 +406,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-firefox-
|
key: v1.0-dependency-cache-firefox-
|
||||||
- run:
|
- run:
|
||||||
name: Install firefox
|
name: Install firefox
|
||||||
command: ./.circleci/scripts/firefox-install.sh
|
command: ./.circleci/scripts/firefox-install.sh
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Get Scss Cache key
|
name: Get Scss Cache key
|
||||||
# this allows us to checksum against a whole directory
|
# this allows us to checksum against a whole directory
|
||||||
@ -431,7 +430,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: dependency-cache-{{ checksum "package-lock.json" }}
|
key: v1.0-dependency-cache-{{ checksum "package-lock.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: Get Scss Cache key
|
name: Get Scss Cache key
|
||||||
# this allows us to checksum against a whole directory
|
# this allows us to checksum against a whole directory
|
||||||
@ -448,4 +447,4 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- run:
|
- run:
|
||||||
name: All Tests Passed
|
name: All Tests Passed
|
||||||
command: echo 'weew - everything passed!'
|
command: echo 'weew - everything passed!'
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -10,6 +10,10 @@ package
|
|||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# VIM
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
temp
|
temp
|
||||||
.tmp
|
.tmp
|
||||||
.sass-cache
|
.sass-cache
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
- Remove rejected transactions from transaction history
|
- Add new tokens auto detection
|
||||||
|
- Remove rejected transactions from transaction history
|
||||||
|
- Add Trezor Support
|
||||||
|
- Allow to remove accounts (Imported and Hardware Wallets)
|
||||||
|
- [#4840](https://github.com/MetaMask/metamask-extension/pull/4840): Now shows notifications when transactions are completed.
|
||||||
|
|
||||||
## 4.8.0 Thur Jun 14 2018
|
## 4.8.0 Thur Jun 14 2018
|
||||||
|
|
||||||
|
@ -26,10 +26,9 @@ If you're a web dapp developer, we've got two types of guides for you:
|
|||||||
|
|
||||||
## Building locally
|
## Building locally
|
||||||
|
|
||||||
- Install [Node.js](https://nodejs.org/en/) version 6.3.1 or later.
|
- Install [Node.js](https://nodejs.org/en/) version 8.11.3 and npm version 6.1.0
|
||||||
- Install dependencies:
|
- Install dependencies:
|
||||||
- For node versions up to and including 9, install local dependencies with `npm install`.
|
- If you are using nvm (recommended) running `nvm use` will automatically choose the right node version for you.
|
||||||
- For node versions 10 and later, install [Yarn](https://yarnpkg.com/lang/en/docs/install/) and use `yarn install`.
|
|
||||||
- Install gulp globally with `npm install -g gulp-cli`.
|
- Install gulp globally with `npm install -g gulp-cli`.
|
||||||
- Build the project to the `./dist/` folder with `gulp build`.
|
- Build the project to the `./dist/` folder with `gulp build`.
|
||||||
- Optionally, to rebuild on file changes, run `gulp dev`.
|
- Optionally, to rebuild on file changes, run `gulp dev`.
|
||||||
@ -81,6 +80,7 @@ To write tests that will be run in the browser using QUnit, add your test files
|
|||||||
- [How to add new networks to the Provider Menu](./docs/adding-new-networks.md)
|
- [How to add new networks to the Provider Menu](./docs/adding-new-networks.md)
|
||||||
- [How to manage notices that appear when the app starts up](./docs/notices.md)
|
- [How to manage notices that appear when the app starts up](./docs/notices.md)
|
||||||
- [How to port MetaMask to a new platform](./docs/porting_to_new_environment.md)
|
- [How to port MetaMask to a new platform](./docs/porting_to_new_environment.md)
|
||||||
|
- [How to use the TREZOR emulator](./docs/trezor-emulator.md)
|
||||||
- [How to generate a visualization of this repository's development](./docs/development-visualization.md)
|
- [How to generate a visualization of this repository's development](./docs/development-visualization.md)
|
||||||
|
|
||||||
[1]: http://www.nomnoml.com/#view/%5B%3Cactor%3Euser%5D%0A%0A%5Bmetamask-ui%7C%0A%20%20%20%5Btools%7C%0A%20%20%20%20%20react%0A%20%20%20%20%20redux%0A%20%20%20%20%20thunk%0A%20%20%20%20%20ethUtils%0A%20%20%20%20%20jazzicon%0A%20%20%20%5D%0A%20%20%20%5Bcomponents%7C%0A%20%20%20%20%20app%0A%20%20%20%20%20account-detail%0A%20%20%20%20%20accounts%0A%20%20%20%20%20locked-screen%0A%20%20%20%20%20restore-vault%0A%20%20%20%20%20identicon%0A%20%20%20%20%20config%0A%20%20%20%20%20info%0A%20%20%20%5D%0A%20%20%20%5Breducers%7C%0A%20%20%20%20%20app%0A%20%20%20%20%20metamask%0A%20%20%20%20%20identities%0A%20%20%20%5D%0A%20%20%20%5Bactions%7C%0A%20%20%20%20%20%5BaccountManager%5D%0A%20%20%20%5D%0A%20%20%20%5Bcomponents%5D%3A-%3E%5Bactions%5D%0A%20%20%20%5Bactions%5D%3A-%3E%5Breducers%5D%0A%20%20%20%5Breducers%5D%3A-%3E%5Bcomponents%5D%0A%5D%0A%0A%5Bweb%20dapp%7C%0A%20%20%5Bui%20code%5D%0A%20%20%5Bweb3%5D%0A%20%20%5Bmetamask-inpage%5D%0A%20%20%0A%20%20%5B%3Cactor%3Eui%20developer%5D%0A%20%20%5Bui%20developer%5D-%3E%5Bui%20code%5D%0A%20%20%5Bui%20code%5D%3C-%3E%5Bweb3%5D%0A%20%20%5Bweb3%5D%3C-%3E%5Bmetamask-inpage%5D%0A%5D%0A%0A%5Bmetamask-background%7C%0A%20%20%5Bprovider-engine%5D%0A%20%20%5Bhooked%20wallet%20subprovider%5D%0A%20%20%5Bid%20store%5D%0A%20%20%0A%20%20%5Bprovider-engine%5D%3C-%3E%5Bhooked%20wallet%20subprovider%5D%0A%20%20%5Bhooked%20wallet%20subprovider%5D%3C-%3E%5Bid%20store%5D%0A%20%20%5Bconfig%20manager%7C%0A%20%20%20%20%5Brpc%20configuration%5D%0A%20%20%20%20%5Bencrypted%20keys%5D%0A%20%20%20%20%5Bwallet%20nicknames%5D%0A%20%20%5D%0A%20%20%0A%20%20%5Bprovider-engine%5D%3C-%5Bconfig%20manager%5D%0A%20%20%5Bid%20store%5D%3C-%3E%5Bconfig%20manager%5D%0A%5D%0A%0A%5Buser%5D%3C-%3E%5Bmetamask-ui%5D%0A%0A%5Buser%5D%3C%3A--%3A%3E%5Bweb%20dapp%5D%0A%0A%5Bmetamask-contentscript%7C%0A%20%20%5Bplugin%20restart%20detector%5D%0A%20%20%5Brpc%20passthrough%5D%0A%5D%0A%0A%5Brpc%20%7C%0A%20%20%5Bethereum%20blockchain%20%7C%0A%20%20%20%20%5Bcontracts%5D%0A%20%20%20%20%5Baccounts%5D%0A%20%20%5D%0A%5D%0A%0A%5Bweb%20dapp%5D%3C%3A--%3A%3E%5Bmetamask-contentscript%5D%0A%5Bmetamask-contentscript%5D%3C-%3E%5Bmetamask-background%5D%0A%5Bmetamask-background%5D%3C-%3E%5Bmetamask-ui%5D%0A%5Bmetamask-background%5D%3C-%3E%5Brpc%5D%0A
|
[1]: http://www.nomnoml.com/#view/%5B%3Cactor%3Euser%5D%0A%0A%5Bmetamask-ui%7C%0A%20%20%20%5Btools%7C%0A%20%20%20%20%20react%0A%20%20%20%20%20redux%0A%20%20%20%20%20thunk%0A%20%20%20%20%20ethUtils%0A%20%20%20%20%20jazzicon%0A%20%20%20%5D%0A%20%20%20%5Bcomponents%7C%0A%20%20%20%20%20app%0A%20%20%20%20%20account-detail%0A%20%20%20%20%20accounts%0A%20%20%20%20%20locked-screen%0A%20%20%20%20%20restore-vault%0A%20%20%20%20%20identicon%0A%20%20%20%20%20config%0A%20%20%20%20%20info%0A%20%20%20%5D%0A%20%20%20%5Breducers%7C%0A%20%20%20%20%20app%0A%20%20%20%20%20metamask%0A%20%20%20%20%20identities%0A%20%20%20%5D%0A%20%20%20%5Bactions%7C%0A%20%20%20%20%20%5BaccountManager%5D%0A%20%20%20%5D%0A%20%20%20%5Bcomponents%5D%3A-%3E%5Bactions%5D%0A%20%20%20%5Bactions%5D%3A-%3E%5Breducers%5D%0A%20%20%20%5Breducers%5D%3A-%3E%5Bcomponents%5D%0A%5D%0A%0A%5Bweb%20dapp%7C%0A%20%20%5Bui%20code%5D%0A%20%20%5Bweb3%5D%0A%20%20%5Bmetamask-inpage%5D%0A%20%20%0A%20%20%5B%3Cactor%3Eui%20developer%5D%0A%20%20%5Bui%20developer%5D-%3E%5Bui%20code%5D%0A%20%20%5Bui%20code%5D%3C-%3E%5Bweb3%5D%0A%20%20%5Bweb3%5D%3C-%3E%5Bmetamask-inpage%5D%0A%5D%0A%0A%5Bmetamask-background%7C%0A%20%20%5Bprovider-engine%5D%0A%20%20%5Bhooked%20wallet%20subprovider%5D%0A%20%20%5Bid%20store%5D%0A%20%20%0A%20%20%5Bprovider-engine%5D%3C-%3E%5Bhooked%20wallet%20subprovider%5D%0A%20%20%5Bhooked%20wallet%20subprovider%5D%3C-%3E%5Bid%20store%5D%0A%20%20%5Bconfig%20manager%7C%0A%20%20%20%20%5Brpc%20configuration%5D%0A%20%20%20%20%5Bencrypted%20keys%5D%0A%20%20%20%20%5Bwallet%20nicknames%5D%0A%20%20%5D%0A%20%20%0A%20%20%5Bprovider-engine%5D%3C-%5Bconfig%20manager%5D%0A%20%20%5Bid%20store%5D%3C-%3E%5Bconfig%20manager%5D%0A%5D%0A%0A%5Buser%5D%3C-%3E%5Bmetamask-ui%5D%0A%0A%5Buser%5D%3C%3A--%3A%3E%5Bweb%20dapp%5D%0A%0A%5Bmetamask-contentscript%7C%0A%20%20%5Bplugin%20restart%20detector%5D%0A%20%20%5Brpc%20passthrough%5D%0A%5D%0A%0A%5Brpc%20%7C%0A%20%20%5Bethereum%20blockchain%20%7C%0A%20%20%20%20%5Bcontracts%5D%0A%20%20%20%20%5Baccounts%5D%0A%20%20%5D%0A%5D%0A%0A%5Bweb%20dapp%5D%3C%3A--%3A%3E%5Bmetamask-contentscript%5D%0A%5Bmetamask-contentscript%5D%3C-%3E%5Bmetamask-background%5D%0A%5Bmetamask-background%5D%3C-%3E%5Bmetamask-ui%5D%0A%5Bmetamask-background%5D%3C-%3E%5Brpc%5D%0A
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
"accountName": {
|
"accountName": {
|
||||||
"message": "Account Name"
|
"message": "Account Name"
|
||||||
},
|
},
|
||||||
|
"accountSelectionRequired": {
|
||||||
|
"message": "You need to select an account!"
|
||||||
|
},
|
||||||
"address": {
|
"address": {
|
||||||
"message": "Address"
|
"message": "Address"
|
||||||
},
|
},
|
||||||
@ -80,6 +83,9 @@
|
|||||||
"borrowDharma": {
|
"borrowDharma": {
|
||||||
"message": "Borrow With Dharma (Beta)"
|
"message": "Borrow With Dharma (Beta)"
|
||||||
},
|
},
|
||||||
|
"browserNotSupported": {
|
||||||
|
"message": "Your Browser is not supported..."
|
||||||
|
},
|
||||||
"builtInCalifornia": {
|
"builtInCalifornia": {
|
||||||
"message": "MetaMask is designed and built in California."
|
"message": "MetaMask is designed and built in California."
|
||||||
},
|
},
|
||||||
@ -110,6 +116,9 @@
|
|||||||
"close": {
|
"close": {
|
||||||
"message": "Close"
|
"message": "Close"
|
||||||
},
|
},
|
||||||
|
"chromeRequiredForTrezor":{
|
||||||
|
"message": "You need to use Metamask on Google Chrome in order to connect to your TREZOR device."
|
||||||
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"message": "Confirm"
|
"message": "Confirm"
|
||||||
},
|
},
|
||||||
@ -125,6 +134,24 @@
|
|||||||
"confirmTransaction": {
|
"confirmTransaction": {
|
||||||
"message": "Confirm Transaction"
|
"message": "Confirm Transaction"
|
||||||
},
|
},
|
||||||
|
"connectHardwareWallet": {
|
||||||
|
"message": "Connect Hardware Wallet"
|
||||||
|
},
|
||||||
|
"connect": {
|
||||||
|
"message": "Connect"
|
||||||
|
},
|
||||||
|
"connecting": {
|
||||||
|
"message": "Connecting..."
|
||||||
|
},
|
||||||
|
"connectToTrezor": {
|
||||||
|
"message": "Connect to Trezor"
|
||||||
|
},
|
||||||
|
"connectToTrezorHelp": {
|
||||||
|
"message": "Metamask is able to access your TREZOR ethereum accounts. First make sure your device is connected and unlocked."
|
||||||
|
},
|
||||||
|
"connectToTrezorTrouble": {
|
||||||
|
"message": "If you are having trouble, please make sure you are using the latest version of the TREZOR firmware."
|
||||||
|
},
|
||||||
"continue": {
|
"continue": {
|
||||||
"message": "Continue"
|
"message": "Continue"
|
||||||
},
|
},
|
||||||
@ -253,9 +280,15 @@
|
|||||||
"done": {
|
"done": {
|
||||||
"message": "Done"
|
"message": "Done"
|
||||||
},
|
},
|
||||||
|
"downloadGoogleChrome": {
|
||||||
|
"message": "Download Google Chrome"
|
||||||
|
},
|
||||||
"downloadStateLogs": {
|
"downloadStateLogs": {
|
||||||
"message": "Download State Logs"
|
"message": "Download State Logs"
|
||||||
},
|
},
|
||||||
|
"dontHaveATrezorWallet": {
|
||||||
|
"message": "Don't have a TREZOR hardware wallet?"
|
||||||
|
},
|
||||||
"dropped": {
|
"dropped": {
|
||||||
"message": "Dropped"
|
"message": "Dropped"
|
||||||
},
|
},
|
||||||
@ -321,6 +354,9 @@
|
|||||||
"followTwitter": {
|
"followTwitter": {
|
||||||
"message": "Follow us on Twitter"
|
"message": "Follow us on Twitter"
|
||||||
},
|
},
|
||||||
|
"forgetDevice": {
|
||||||
|
"message": "Forget this device"
|
||||||
|
},
|
||||||
"from": {
|
"from": {
|
||||||
"message": "From"
|
"message": "From"
|
||||||
},
|
},
|
||||||
@ -374,10 +410,28 @@
|
|||||||
"message": "Get Ether from a faucet for the $1",
|
"message": "Get Ether from a faucet for the $1",
|
||||||
"description": "Displays network name for Ether faucet"
|
"description": "Displays network name for Ether faucet"
|
||||||
},
|
},
|
||||||
|
"getHelp": {
|
||||||
|
"message": "Get Help."
|
||||||
|
},
|
||||||
"greaterThanMin": {
|
"greaterThanMin": {
|
||||||
"message": "must be greater than or equal to $1.",
|
"message": "must be greater than or equal to $1.",
|
||||||
"description": "helper for inputting hex as decimal input"
|
"description": "helper for inputting hex as decimal input"
|
||||||
},
|
},
|
||||||
|
"hardware": {
|
||||||
|
"message": "hardware"
|
||||||
|
},
|
||||||
|
"hardwareWalletConnected": {
|
||||||
|
"message": "Hardware wallet connected"
|
||||||
|
},
|
||||||
|
"hardwareSupport": {
|
||||||
|
"message": "Hardware Support"
|
||||||
|
},
|
||||||
|
"hardwareSupportMsg": {
|
||||||
|
"message": "You can now view your Hardware accounts in MetaMask! Scroll down and read how it works."
|
||||||
|
},
|
||||||
|
"havingTroubleConnecting": {
|
||||||
|
"message": "Having trouble connecting?"
|
||||||
|
},
|
||||||
"here": {
|
"here": {
|
||||||
"message": "here",
|
"message": "here",
|
||||||
"description": "as in -click here- for more information (goes with troubleTokenBalances)"
|
"description": "as in -click here- for more information (goes with troubleTokenBalances)"
|
||||||
@ -476,7 +530,7 @@
|
|||||||
"message": "Max"
|
"message": "Max"
|
||||||
},
|
},
|
||||||
"learnMore": {
|
"learnMore": {
|
||||||
"message": "Learn more."
|
"message": "Learn more"
|
||||||
},
|
},
|
||||||
"lessThanMax": {
|
"lessThanMax": {
|
||||||
"message": "must be less than or equal to $1.",
|
"message": "must be less than or equal to $1.",
|
||||||
@ -645,6 +699,9 @@
|
|||||||
"popularTokens": {
|
"popularTokens": {
|
||||||
"message": "Popular Tokens"
|
"message": "Popular Tokens"
|
||||||
},
|
},
|
||||||
|
"prev": {
|
||||||
|
"message": "Prev"
|
||||||
|
},
|
||||||
"privacyMsg": {
|
"privacyMsg": {
|
||||||
"message": "Privacy Policy"
|
"message": "Privacy Policy"
|
||||||
},
|
},
|
||||||
@ -730,6 +787,18 @@
|
|||||||
"revert": {
|
"revert": {
|
||||||
"message": "Revert"
|
"message": "Revert"
|
||||||
},
|
},
|
||||||
|
"remove": {
|
||||||
|
"message": "remove"
|
||||||
|
},
|
||||||
|
"removeAccount": {
|
||||||
|
"message": "Remove account"
|
||||||
|
},
|
||||||
|
"removeAccountDescription": {
|
||||||
|
"message": "This account will be removed from your wallet. Please make sure you have the original seed phrase or private key for this imported account before continuing. You can import or create accounts again from the account drop-down. "
|
||||||
|
},
|
||||||
|
"readyToConnect": {
|
||||||
|
"message": "Ready to Connect?"
|
||||||
|
},
|
||||||
"rinkeby": {
|
"rinkeby": {
|
||||||
"message": "Rinkeby Test Network"
|
"message": "Rinkeby Test Network"
|
||||||
},
|
},
|
||||||
@ -826,15 +895,45 @@
|
|||||||
"message": "Only send $1 to an Ethereum account address.",
|
"message": "Only send $1 to an Ethereum account address.",
|
||||||
"description": "displays token symbol"
|
"description": "displays token symbol"
|
||||||
},
|
},
|
||||||
|
"orderOneHere": {
|
||||||
|
"message": "Order one here."
|
||||||
|
},
|
||||||
"searchTokens": {
|
"searchTokens": {
|
||||||
"message": "Search Tokens"
|
"message": "Search Tokens"
|
||||||
},
|
},
|
||||||
|
"selectAnAddress": {
|
||||||
|
"message": "Select an Address"
|
||||||
|
},
|
||||||
|
"selectAnAccount": {
|
||||||
|
"message": "Select an Account"
|
||||||
|
},
|
||||||
|
"selectAnAccountHelp": {
|
||||||
|
"message": "These are the accounts available in your hardware wallet. Select the one you’d like to use in MetaMask."
|
||||||
|
},
|
||||||
"sendTokensAnywhere": {
|
"sendTokensAnywhere": {
|
||||||
"message": "Send Tokens to anyone with an Ethereum account"
|
"message": "Send Tokens to anyone with an Ethereum account"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"message": "Settings"
|
"message": "Settings"
|
||||||
},
|
},
|
||||||
|
"step1HardwareWallet": {
|
||||||
|
"message": "1. Connect Hardware Wallet"
|
||||||
|
},
|
||||||
|
"step1HardwareWalletMsg": {
|
||||||
|
"message": "Connect your hardware wallet directly to your computer."
|
||||||
|
},
|
||||||
|
"step2HardwareWallet": {
|
||||||
|
"message": "2. Select an Account"
|
||||||
|
},
|
||||||
|
"step2HardwareWalletMsg": {
|
||||||
|
"message": "Select the account you want to view. You can only choose one at a time."
|
||||||
|
},
|
||||||
|
"step3HardwareWallet": {
|
||||||
|
"message": "3. Start using dApps and more!"
|
||||||
|
},
|
||||||
|
"step3HardwareWalletMsg": {
|
||||||
|
"message": "Use your hardware account like you would with any Ethereum account. Log in to dApps, send Eth, buy and store ERC20 tokens and Non-Fungible tokens like CryptoKitties."
|
||||||
|
},
|
||||||
"info": {
|
"info": {
|
||||||
"message": "Info"
|
"message": "Info"
|
||||||
},
|
},
|
||||||
@ -950,6 +1049,9 @@
|
|||||||
"transfers": {
|
"transfers": {
|
||||||
"message": "Transfers"
|
"message": "Transfers"
|
||||||
},
|
},
|
||||||
|
"trezorHardwareWallet": {
|
||||||
|
"message": "TREZOR Hardware Wallet"
|
||||||
|
},
|
||||||
"troubleTokenBalances": {
|
"troubleTokenBalances": {
|
||||||
"message": "We had trouble loading your token balances. You can view them ",
|
"message": "We had trouble loading your token balances. You can view them ",
|
||||||
"description": "Followed by a link (here) to view token balances"
|
"description": "Followed by a link (here) to view token balances"
|
||||||
@ -984,6 +1086,9 @@
|
|||||||
"unknownNetworkId": {
|
"unknownNetworkId": {
|
||||||
"message": "Unknown network ID"
|
"message": "Unknown network ID"
|
||||||
},
|
},
|
||||||
|
"unlock": {
|
||||||
|
"message": "Unlock"
|
||||||
|
},
|
||||||
"unlockMessage": {
|
"unlockMessage": {
|
||||||
"message": "The decentralized web awaits"
|
"message": "The decentralized web awaits"
|
||||||
},
|
},
|
||||||
|
11
app/images/connect-icon.svg
Normal file
11
app/images/connect-icon.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg width="288" height="288" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
|
||||||
|
<g>
|
||||||
|
<title>background</title>
|
||||||
|
<rect fill="none" id="canvas_background" height="402" width="582" y="-1" x="-1"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<title>Layer 1</title>
|
||||||
|
<path fill="#ffffff" id="svg_1" d="m122,25l15,-21c4,-5 10,-5 14,0l16,22c4,5 2,10 -5,10l-12,0l0,118c0,3 3,3 5,1l25,-25c4,-4 6,-10 6,-16l0,-24c-7,0 -12,-5 -12,-12l0,-12c0,-6 5,-12 12,-12l12,0c7,0 12,5 12,12l0,12c0,7 -5,12 -12,12l0,24c0,10 -3,18 -10,25l-31,31c-4,4 -7,6 -7,16l0,49c12,3 21,13 21,26c0,15 -12,27 -27,27s-27,-12 -27,-27c0,-13 9,-23 21,-26l0,-13c0,-10 -3,-13 -7,-17l-31,-31c-6,-6 -10,-14 -10,-24l0,-25c-7,-2 -12,-9 -12,-17c0,-10 8,-18 18,-18s18,8 18,18c0,8 -5,15 -12,17l0,25c0,7 3,12 7,16l25,25c2,2 4,2 4,-1l0,-154l-12,0c-7,0 -9,-5 -4,-11z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 786 B |
44
app/images/hardware-wallet-step-1.svg
Normal file
44
app/images/hardware-wallet-step-1.svg
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="213px" height="78px" viewBox="0 0 213 78" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: sketchtool 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>2981A924-C7CB-4957-87AD-8C680802DAD7</title>
|
||||||
|
<desc>Created with sketchtool.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Import-account" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="hardware-connect" transform="translate(-406.000000, -602.000000)">
|
||||||
|
<g id="Group-9" transform="translate(356.000000, 522.000000)">
|
||||||
|
<g id="connect-hardware" transform="translate(51.000000, 81.000000)">
|
||||||
|
<path d="M4,9 L70,9 L70,17 L4,17 C1.790861,17 2.705415e-16,15.209139 0,13 L0,13 C-2.705415e-16,10.790861 1.790861,9 4,9 Z" id="Rectangle" fill="#D9F0FF"></path>
|
||||||
|
<g id="Group-4-Copy">
|
||||||
|
<g id="Group-2" transform="translate(91.000000, 31.000000)" stroke="#3098DC">
|
||||||
|
<polyline id="Stroke-10" points="7.33333333 0 13.4253333 5.29042105 7.33333333 10.5802632"></polyline>
|
||||||
|
<path d="M0,5.21052632 L13.5,5.21052632" id="Stroke-11"></path>
|
||||||
|
</g>
|
||||||
|
<g id="Group-3" transform="translate(109.000000, 0.000000)">
|
||||||
|
<path d="M92.535988,75.1897419 L9.16167665,75.1897419 C7.13816766,75.1897419 5.49700599,73.5434839 5.49700599,71.5123226 L5.49700599,3.67741935 C5.49700599,1.64625806 7.13816766,0 9.16167665,0 L92.535988,0 C94.5601078,0 96.2006587,1.64625806 96.2006587,3.67741935 L96.2006587,71.5123226 C96.2006587,73.5434839 94.5601078,75.1897419 92.535988,75.1897419" id="Fill-12" fill="#FEFEFE"></path>
|
||||||
|
<path d="M92.535988,75.1897419 L9.16167665,75.1897419 C7.13816766,75.1897419 5.49700599,73.5434839 5.49700599,71.5123226 L5.49700599,3.67741935 C5.49700599,1.64625806 7.13816766,0 9.16167665,0 L92.535988,0 C94.5601078,0 96.2006587,1.64625806 96.2006587,3.67741935 L96.2006587,71.5123226 C96.2006587,73.5434839 94.5601078,75.1897419 92.535988,75.1897419 Z" id="Stroke-13" stroke="#3098DC"></path>
|
||||||
|
<path d="M100.70576,75.6298065 L1.22155689,75.6298065 C0.546646707,75.6298065 0,75.0812581 0,74.404 L0,69.8709677 C0,69.1937097 0.546646707,68.6451613 1.22155689,68.6451613 L100.70576,68.6451613 C101.38006,68.6451613 101.927317,69.1937097 101.927317,69.8709677 L101.927317,74.404 C101.927317,75.0812581 101.38006,75.6298065 100.70576,75.6298065" id="Fill-14" fill="#D9F0FF"></path>
|
||||||
|
<path d="M100.70576,75.6298065 L1.22155689,75.6298065 C0.546646707,75.6298065 0,75.0812581 0,74.404 L0,69.8709677 C0,69.1937097 0.546646707,68.6451613 1.22155689,68.6451613 L100.70576,68.6451613 C101.38006,68.6451613 101.927317,69.1937097 101.927317,69.8709677 L101.927317,74.404 C101.927317,75.0812581 101.38006,75.6298065 100.70576,75.6298065 Z" id="Stroke-15" stroke="#3098DC"></path>
|
||||||
|
<polygon id="Fill-16" fill="#FEFEFE" points="9.77245509 63.6953548 92.1554731 63.6953548 92.1554731 4.90322581 9.77245509 4.90322581"></polygon>
|
||||||
|
<polygon id="Stroke-17" stroke="#3098DC" points="9.77245509 63.6953548 92.1554731 63.6953548 92.1554731 4.90322581 9.77245509 4.90322581"></polygon>
|
||||||
|
<path d="M53.4327111,51.4764454 L48.3815734,51.4764454 C48.2930105,51.4764454 48.2081123,51.4494776 48.1354296,51.3986067 L45.1462799,49.3073809 L43.8318847,48.2207035 L36.536747,50.2488002 C36.3101482,50.3113164 36.0719446,50.1770906 36.0059805,49.9490906 L33.8908548,42.6077357 C33.8664237,42.523768 33.8676452,42.4361228 33.8939087,42.352768 L36.1409626,35.2823164 L34.7923638,33.6826389 C34.7141841,33.5900906 34.6775374,33.4675099 34.6921961,33.346768 C34.7068548,33.226026 34.7709865,33.1157035 34.8693219,33.0446067 L35.1105793,32.8693164 L34.4368907,32.2484454 C34.3428308,32.1608002 34.2915255,32.0376067 34.2958009,31.9095099 C34.3006871,31.7808002 34.3611542,31.6612841 34.4607111,31.5822196 L34.8406153,31.2806712 L34.2218967,30.8044454 C34.1150105,30.7223164 34.0508787,30.5905422 34.0521003,30.4544776 C34.0533219,30.3178002 34.1180644,30.1872518 34.2273937,30.1057357 L34.6818129,29.7655744 L33.6019566,24.5289293 C33.5860763,24.4541551 33.5909626,24.3744776 33.6160045,24.3003164 L35.2620524,19.299026 C35.2993099,19.1862518 35.3805434,19.0930906 35.4862081,19.0428325 C35.5918728,18.9919615 35.7140284,18.9864454 35.8233578,19.0275099 L46.4826632,23.0506067 L55.3316213,23.0506067 L65.9903159,19.0275099 C66.0996452,18.9858325 66.2224117,18.9919615 66.3280763,19.0428325 C66.4343518,19.0937035 66.5155853,19.1868647 66.552232,19.299026 L68.1988907,24.3021551 C68.2227111,24.3732518 68.2275973,24.4517035 68.2123278,24.5277035 L67.1440763,29.7674131 L67.5911662,30.1081873 C67.6998847,30.1909293 67.7621841,30.3178002 67.7627949,30.4550906 C67.7634057,30.5905422 67.6998847,30.7210906 67.5936093,30.8038325 L66.9742799,31.2806712 L67.3535734,31.5822196 C67.453741,31.661897 67.5135973,31.7814131 67.5178728,31.9095099 C67.522759,32.0382196 67.4714536,32.1614131 67.3773937,32.2478325 L66.7037051,32.8693164 L66.9455734,33.0452196 C67.0432979,33.1157035 67.1074296,33.226026 67.1220883,33.3473809 C67.136747,33.4681228 67.0994895,33.5907035 67.0213099,33.6832518 L65.6739326,35.2817035 L67.9332021,42.3515422 C67.9600763,42.4336712 67.9612979,42.5225422 67.9374775,42.6071228 L65.8076931,49.9497035 C65.7423398,50.1770906 65.5035255,50.3100906 65.2775374,50.2488002 L57.9823997,48.2207035 L56.6283039,49.3368002 L53.6788548,51.3986067 C53.6061722,51.4494776 53.5206632,51.4764454 53.4327111,51.4764454" id="Fill-18" fill="#FEFEFE"></path>
|
||||||
|
<path d="M53.4327111,51.4764454 L48.3815734,51.4764454 C48.2930105,51.4764454 48.2081123,51.4494776 48.1354296,51.3986067 L45.1462799,49.3073809 L43.8318847,48.2207035 L36.536747,50.2488002 C36.3101482,50.3113164 36.0719446,50.1770906 36.0059805,49.9490906 L33.8908548,42.6077357 C33.8664237,42.523768 33.8676452,42.4361228 33.8939087,42.352768 L36.1409626,35.2823164 L34.7923638,33.6826389 C34.7141841,33.5900906 34.6775374,33.4675099 34.6921961,33.346768 C34.7068548,33.226026 34.7709865,33.1157035 34.8693219,33.0446067 L35.1105793,32.8693164 L34.4368907,32.2484454 C34.3428308,32.1608002 34.2915255,32.0376067 34.2958009,31.9095099 C34.3006871,31.7808002 34.3611542,31.6612841 34.4607111,31.5822196 L34.8406153,31.2806712 L34.2218967,30.8044454 C34.1150105,30.7223164 34.0508787,30.5905422 34.0521003,30.4544776 C34.0533219,30.3178002 34.1180644,30.1872518 34.2273937,30.1057357 L34.6818129,29.7655744 L33.6019566,24.5289293 C33.5860763,24.4541551 33.5909626,24.3744776 33.6160045,24.3003164 L35.2620524,19.299026 C35.2993099,19.1862518 35.3805434,19.0930906 35.4862081,19.0428325 C35.5918728,18.9919615 35.7140284,18.9864454 35.8233578,19.0275099 L46.4826632,23.0506067 L55.3316213,23.0506067 L65.9903159,19.0275099 C66.0996452,18.9858325 66.2224117,18.9919615 66.3280763,19.0428325 C66.4343518,19.0937035 66.5155853,19.1868647 66.552232,19.299026 L68.1988907,24.3021551 C68.2227111,24.3732518 68.2275973,24.4517035 68.2123278,24.5277035 L67.1440763,29.7674131 L67.5911662,30.1081873 C67.6998847,30.1909293 67.7621841,30.3178002 67.7627949,30.4550906 C67.7634057,30.5905422 67.6998847,30.7210906 67.5936093,30.8038325 L66.9742799,31.2806712 L67.3535734,31.5822196 C67.453741,31.661897 67.5135973,31.7814131 67.5178728,31.9095099 C67.522759,32.0382196 67.4714536,32.1614131 67.3773937,32.2478325 L66.7037051,32.8693164 L66.9455734,33.0452196 C67.0432979,33.1157035 67.1074296,33.226026 67.1220883,33.3473809 C67.136747,33.4681228 67.0994895,33.5907035 67.0213099,33.6832518 L65.6739326,35.2817035 L67.9332021,42.3515422 C67.9600763,42.4336712 67.9612979,42.5225422 67.9374775,42.6071228 L65.8076931,49.9497035 C65.7423398,50.1770906 65.5035255,50.3100906 65.2775374,50.2488002 L57.9823997,48.2207035 L56.6283039,49.3368002 L53.6788548,51.3986067 C53.6061722,51.4494776 53.5206632,51.4764454 53.4327111,51.4764454 Z" id="Stroke-19" stroke="#3098DC"></path>
|
||||||
|
<polygon id="Fill-20" fill="#3098DC" points="52.0480958 46.5806452 49.4779401 46.5806452 49.0320719 46.9355161 48.8622754 49.0745484 52.6637605 49.0745484 52.4933533 46.9355161"></polygon>
|
||||||
|
<path d="M54.8341371,38.1394234 L53.7713826,40.485617 C53.6852628,40.675617 53.8562808,40.8809396 54.0505083,40.8208751 L57.6742569,39.7017138 C57.8807,39.6379718 57.9014664,39.3425525 57.7054066,39.2493912 L55.1444125,38.0223589 C55.0277539,37.9665847 54.8891072,38.0186815 54.8341371,38.1394234" id="Fill-21" fill="#3098DC"></path>
|
||||||
|
<path d="M46.6690624,38.0223713 L44.1117331,39.2487906 C43.916284,39.3425648 43.9364397,39.6373713 44.1434936,39.7017261 L47.7666313,40.8208874 C47.9608589,40.8809519 48.1318768,40.6750164 48.0457571,40.4850164 L46.9793379,38.1388229 C46.9243678,38.0186939 46.7857211,37.9665971 46.6690624,38.0223713" id="Fill-22" fill="#3098DC"></path>
|
||||||
|
</g>
|
||||||
|
<g id="Group" transform="translate(0.000000, 9.000000)">
|
||||||
|
<path d="M66.9571429,59 L3.68571429,59 C1.65058571,59 0,57.3318526 0,55.2736842 L0,3.72631579 C0,1.66876842 1.65058571,0 3.68571429,0 L66.9571429,0 C68.9922714,0 70.6428571,1.66876842 70.6428571,3.72631579 L70.6428571,55.2736842 C70.6428571,57.3318526 68.9922714,59 66.9571429,59 Z" id="Stroke-1" stroke="#3098DC"></path>
|
||||||
|
<path d="M66.9571429,7.45263158 L3.68571429,7.45263158 C1.65058571,7.45263158 0,5.78448421 0,3.72631579 C0,1.66876842 1.65058571,0 3.68571429,0 L66.9571429,0 C68.9922714,0 70.6428571,1.66876842 70.6428571,3.72631579" id="Stroke-3" stroke="#3098DC"></path>
|
||||||
|
<path d="M66.9571429,7.45263158 C68.9922714,7.45263158 70.6428571,9.1214 70.6428571,11.1789474" id="Stroke-5" stroke="#3098DC"></path>
|
||||||
|
<polygon id="Stroke-7" stroke="#3098DC" points="70.6428571 23.5987579 85.5319143 23.5987579 85.5319143 19.8736842 70.6428571 19.8736842"></polygon>
|
||||||
|
<polygon id="Stroke-9" stroke="#3098DC" points="70.6428571 38.6530737 85.5319143 38.6530737 85.5319143 23.6 70.6428571 23.6"></polygon>
|
||||||
|
<path d="M35.2784286,22.3578947 L28.9666429,32.8356737 L35.2784286,36.5682 L41.5902143,32.8387789 L35.2784286,22.3578947 Z M35.1832143,37.7631053 L28.8714286,34.0336842 L35.1832143,42.9321263 L41.4986857,34.0336842 L35.1819857,37.7631053 L35.1832143,37.7631053 Z" id="Fill-23" fill="#3098DC"></path>
|
||||||
|
<path d="M50.4672571,32.9642316 C50.4672571,24.3626526 43.5700571,17.3894737 35.0622,17.3894737 C26.5543429,17.3894737 19.6571429,24.3626526 19.6571429,32.9642316 C19.6571429,41.5664316 26.5543429,48.5389895 35.0622,48.5389895 C43.5700571,48.5389895 50.4672571,41.5664316 50.4672571,32.9642316 Z" id="Stroke-24" stroke="#3098DC"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 11 KiB |
81
app/images/hardware-wallet-step-2.svg
Normal file
81
app/images/hardware-wallet-step-2.svg
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="302px" height="98px" viewBox="0 0 302 98" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: sketchtool 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>27B850D0-B3BA-4F98-8BB4-B542D8BFDE3B</title>
|
||||||
|
<desc>Created with sketchtool.</desc>
|
||||||
|
<defs>
|
||||||
|
<rect id="path-1" x="0" y="0" width="294" height="32"></rect>
|
||||||
|
<filter x="-2.4%" y="-15.6%" width="104.8%" height="143.8%" filterUnits="objectBoundingBox" id="filter-2">
|
||||||
|
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
|
<feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
|
<feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1"></feComposite>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.123075181 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g id="Import-account" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="hardware-connect" transform="translate(-361.000000, -797.000000)">
|
||||||
|
<g id="Group-10" transform="translate(356.000000, 717.000000)">
|
||||||
|
<g id="accounts" transform="translate(9.000000, 80.000000)">
|
||||||
|
<g id="Group-5" transform="translate(21.000000, 0.000000)">
|
||||||
|
<g id="Group-7" transform="translate(0.000000, 45.000000)">
|
||||||
|
<rect id="Rectangle-6-Copy" stroke="#AFDFFF" fill="#FFFFFF" x="0.5" y="0.5" width="250" height="26"></rect>
|
||||||
|
<text id="3" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="31" y="19">3</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="OXz3…T3A4" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="50" y="19">OXz3…T3A4</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="0.020000-ETH" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="142" y="19">0.020000 ETH</tspan>
|
||||||
|
</text>
|
||||||
|
<circle id="Oval-Copy" stroke="#AFDFFF" stroke-width="2" cx="16.5" cy="14.5" r="6.5"></circle>
|
||||||
|
</g>
|
||||||
|
<g id="Group-7-Copy">
|
||||||
|
<rect id="Rectangle-6-Copy" stroke="#AFDFFF" fill="#FFFFFF" x="0.5" y="0.5" width="250" height="26"></rect>
|
||||||
|
<text id="1" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="31" y="19">1</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="OXa4…s0a2" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="50" y="19">OXa4…s0a2</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="0.01500-ETH" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="142" y="19">0.01500 ETH</tspan>
|
||||||
|
</text>
|
||||||
|
<circle id="Oval-Copy" stroke="#AFDFFF" stroke-width="2" cx="16.5" cy="14.5" r="6.5"></circle>
|
||||||
|
</g>
|
||||||
|
<g id="Group-8" transform="translate(0.000000, 71.000000)">
|
||||||
|
<rect id="Rectangle-6-Copy-2" stroke="#AFDFFF" fill="#FFFFFF" x="0.5" y="0.5" width="250" height="26"></rect>
|
||||||
|
<text id="4" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="31" y="18">4</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="OXd2…D0V4" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="50" y="18">OXd2…D0V4</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="0.030000-ETH" font-family="Roboto-Regular, Roboto" font-size="12" font-weight="normal" fill="#ABB4BB">
|
||||||
|
<tspan x="142" y="18">0.030000 ETH</tspan>
|
||||||
|
</text>
|
||||||
|
<circle id="Oval-Copy-2" stroke="#AFDFFF" stroke-width="2" cx="16.5" cy="13.5" r="6.5"></circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group-4" transform="translate(0.000000, 21.000000)">
|
||||||
|
<g id="Rectangle-6">
|
||||||
|
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
|
||||||
|
<rect stroke="#3098DC" stroke-width="1" stroke-linejoin="square" fill="#D9F0FF" fill-rule="evenodd" x="0.5" y="0.5" width="293" height="31"></rect>
|
||||||
|
</g>
|
||||||
|
<text id="2" font-family="Roboto-Regular, Roboto" font-size="16" font-weight="normal" fill="#4A4A4A">
|
||||||
|
<tspan x="36" y="22">2</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="OXe7…B0a1" font-family="Roboto-Regular, Roboto" font-size="16" font-weight="normal" fill="#4A4A4A">
|
||||||
|
<tspan x="58" y="22">OXe7…B0a1</tspan>
|
||||||
|
</text>
|
||||||
|
<text id="0.041000-ETH" font-family="Roboto-Regular, Roboto" font-size="16" font-weight="normal" fill="#4A4A4A">
|
||||||
|
<tspan x="166" y="22">0.041000 ETH</tspan>
|
||||||
|
</text>
|
||||||
|
<circle id="Oval" stroke="#3098DC" stroke-width="2" cx="19.5" cy="16.5" r="7.5"></circle>
|
||||||
|
<polyline id="Path-5" stroke="#3098DC" stroke-width="2" points="15 17 17.5495098 19.5495098 24 13.9042921"></polyline>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
42
app/images/hardware-wallet-step-3.svg
Normal file
42
app/images/hardware-wallet-step-3.svg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="108px" height="85px" viewBox="0 0 108 85" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: sketchtool 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>CEB55C41-7BCE-405E-83CD-834B388B495F</title>
|
||||||
|
<desc>Created with sketchtool.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Import-account" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="hardware-connect" transform="translate(-457.000000, -1057.000000)">
|
||||||
|
<g id="Group-11" transform="translate(356.000000, 929.000000)">
|
||||||
|
<g id="use-dapps" transform="translate(102.000000, 129.000000)">
|
||||||
|
<g id="Group-3">
|
||||||
|
<path d="M96.2021481,83 L9.79785192,83 C7.70080469,83 6,81.2922121 6,79.1851351 L6,8.81486493 C6,6.70778787 7.70080469,5 9.79785192,5 L96.2021481,5 C98.2998283,5 100,6.70778787 100,8.81486493 L100,79.1851351 C100,81.2922121 98.2998283,83 96.2021481,83" id="Fill-12" fill="#FEFEFE"></path>
|
||||||
|
<path d="M96.2021481,83 L9.79785192,83 C7.70080469,83 6,81.2922121 6,79.1851351 L6,8.81486493 C6,6.70778787 7.70080469,5 9.79785192,5 L96.2021481,5 C98.2998283,5 100,6.70778787 100,8.81486493 L100,79.1851351 C100,81.2922121 98.2998283,83 96.2021481,83 Z" id="Stroke-13" stroke="#3098DC"></path>
|
||||||
|
<path d="M104.729634,83 L1.27036631,83 C0.568488923,83 0,82.4502457 0,81.7714988 L0,77.2285012 C0,76.5497543 0.568488923,76 1.27036631,76 L104.729634,76 C105.430876,76 106,76.5497543 106,77.2285012 L106,81.7714988 C106,82.4502457 105.430876,83 104.729634,83" id="Fill-14" fill="#D9F0FF"></path>
|
||||||
|
<path d="M104.729634,83 L1.27036631,83 C0.568488923,83 0,82.4502457 0,81.7714988 L0,77.2285012 C0,76.5497543 0.568488923,76 1.27036631,76 L104.729634,76 C105.430876,76 106,76.5497543 106,77.2285012 L106,81.7714988 C106,82.4502457 105.430876,83 104.729634,83 Z" id="Stroke-15" stroke="#3098DC"></path>
|
||||||
|
<polygon id="Fill-16" fill="#FEFEFE" points="10 71 96 71 96 10 10 10"></polygon>
|
||||||
|
<polygon id="Stroke-17" stroke="#3098DC" points="10 71 96 71 96 10 10 10"></polygon>
|
||||||
|
<rect id="Rectangle-2" stroke="#3098DC" fill="#FFFFFF" x="14.5" y="14.5" width="77" height="53" rx="2"></rect>
|
||||||
|
<path d="M14.5,21.5 L91.5,21.5 L91.5,16 C91.5,15.1715729 90.8284271,14.5 90,14.5 L16,14.5 C15.1715729,14.5 14.5,15.1715729 14.5,16 L14.5,21.5 Z" id="Rectangle-3" stroke="#3098DC" fill="#FFFFFF"></path>
|
||||||
|
<g id="Group-6" transform="translate(17.000000, 17.000000)" fill="#D9F0FF" stroke="#3098DC">
|
||||||
|
<circle id="Oval-2" cx="1" cy="1" r="1"></circle>
|
||||||
|
<circle id="Oval-2" cx="5.76923077" cy="1" r="1"></circle>
|
||||||
|
<circle id="Oval-2" cx="10.5384615" cy="1" r="1"></circle>
|
||||||
|
</g>
|
||||||
|
<g id="metamask-outline" transform="translate(73.000000, 0.000000)">
|
||||||
|
<g id="Group-6">
|
||||||
|
<path d="M19.2986136,29.0578722 L14.6471457,29.0578722 C14.5655903,29.0578722 14.4874097,29.0337432 14.420478,28.988227 L11.6678439,27.1171303 L10.4574498,26.1448399 L3.73953772,27.9594528 C3.53086848,28.0153883 3.31151268,27.8952915 3.250768,27.6912915 L1.30300094,21.1227109 C1.28050291,21.0475819 1.28162782,20.9691625 1.3058132,20.8945819 L3.37506962,14.5683883 L2.1331783,13.137098 C2.0611846,13.0542915 2.02743755,12.9446141 2.04093637,12.8365819 C2.05443519,12.7285496 2.11349252,12.6298399 2.20404709,12.566227 L2.42621515,12.4093883 L1.80583194,11.8538722 C1.71921452,11.7754528 1.67196866,11.665227 1.67590581,11.5506141 C1.68040542,11.4354528 1.73608805,11.3285174 1.82776752,11.2577754 L2.17761191,10.987969 L1.60784927,10.5618722 C1.50942038,10.4883883 1.45036305,10.3704851 1.45148795,10.2487432 C1.45261285,10.1264528 1.51223264,10.0096464 1.61291132,9.9367109 L2.0313747,9.63235606 L1.03696173,4.94693671 C1.02233801,4.88003348 1.02683761,4.80874316 1.04989809,4.74238832 L2.56570295,0.267549611 C2.60001244,0.166646385 2.6748184,0.0832915464 2.77212238,0.0383238044 C2.86942637,-0.00719232461 2.98191652,-0.0121278085 3.08259521,0.024614127 L12.8984862,3.62422703 L21.0472731,3.62422703 L30.8626017,0.024614127 C30.9632804,-0.0126761956 31.076333,-0.00719232461 31.173637,0.0383238044 C31.2715034,0.0838399335 31.3463093,0.167194772 31.3800564,0.267549611 L32.8964237,4.74403348 C32.9183593,4.80764639 32.9228589,4.87783993 32.9087976,4.94583993 L31.9250712,9.63400122 L32.3367852,9.93890445 C32.4369014,10.0129367 32.4942714,10.1264528 32.4948338,10.2492915 C32.4953963,10.3704851 32.4369014,10.4872915 32.339035,10.5613238 L31.7687099,10.987969 L32.1179918,11.2577754 C32.2102337,11.3290657 32.2653539,11.4360012 32.2692911,11.5506141 C32.2737907,11.6657754 32.2265448,11.7760012 32.1399274,11.8533238 L31.5195442,12.4093883 L31.7422747,12.5667754 C31.8322668,12.6298399 31.8913241,12.7285496 31.904823,12.8371303 C31.9183218,12.9451625 31.8840123,13.0548399 31.8120186,13.1376464 L30.5712522,14.5678399 L32.6517576,20.8934851 C32.6765054,20.966969 32.6776303,21.0464851 32.6556948,21.1221625 L30.6944289,27.6918399 C30.6342467,27.8952915 30.4143284,28.0142915 30.2062216,27.9594528 L23.4883095,26.1448399 L22.2413561,27.1434528 L19.5252813,28.988227 C19.4583497,29.0337432 19.3796066,29.0578722 19.2986136,29.0578722 Z" id="Stroke-19" stroke="#3098DC" fill="#FFFFFF"></path>
|
||||||
|
<polygon id="Fill-20" fill="#3098DC" points="18.0235556 24.6774194 15.6567628 24.6774194 15.2461737 24.9949355 15.0898124 26.9088065 18.590506 26.9088065 18.4335823 24.9949355"></polygon>
|
||||||
|
<path d="M20.5891522,17.1247473 L19.6104879,19.2239731 C19.5311823,19.3939731 19.6886685,19.5776828 19.8675279,19.5239408 L23.2045484,18.522586 C23.3946567,18.4655537 23.4137801,18.2012312 23.2332334,18.1178763 L20.8748772,17.0200054 C20.7674491,16.9701021 20.6397728,17.016715 20.5891522,17.1247473" id="Fill-21" fill="#3098DC"></path>
|
||||||
|
<path d="M13.0701367,17.0200164 L10.7151553,18.117339 C10.535171,18.2012422 10.5537319,18.4650164 10.7444027,18.5225971 L14.0808608,19.5239519 C14.2597201,19.5776938 14.4172063,19.3934358 14.3379008,19.2234358 L13.3558617,17.12421 C13.3052411,17.0167261 13.1775648,16.9701132 13.0701367,17.0200164" id="Fill-22" fill="#3098DC"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<text id="LOGIN-WITH-METAMASK" font-family="RobotoMono-Bold, Roboto Mono" font-size="10" font-weight="bold" fill="#3098DC">
|
||||||
|
<tspan x="24.4951172" y="43">LOGIN WITH </tspan>
|
||||||
|
<tspan x="30.4960938" y="56">METAMASK</tspan>
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.8 KiB |
@ -62,7 +62,9 @@
|
|||||||
"https://*.infura.io/",
|
"https://*.infura.io/",
|
||||||
"activeTab",
|
"activeTab",
|
||||||
"webRequest",
|
"webRequest",
|
||||||
"*://*.eth/"
|
"*://*.eth/",
|
||||||
|
"*://*.test/",
|
||||||
|
"notifications"
|
||||||
],
|
],
|
||||||
"web_accessible_resources": [
|
"web_accessible_resources": [
|
||||||
"inpage.js"
|
"inpage.js"
|
||||||
|
@ -44,8 +44,8 @@ const notificationManager = new NotificationManager()
|
|||||||
global.METAMASK_NOTIFIER = notificationManager
|
global.METAMASK_NOTIFIER = notificationManager
|
||||||
|
|
||||||
// setup sentry error reporting
|
// setup sentry error reporting
|
||||||
const release = platform.getVersion()
|
const releaseVersion = platform.getVersion()
|
||||||
const raven = setupRaven({ release })
|
const raven = setupRaven({ releaseVersion })
|
||||||
|
|
||||||
// browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
|
// browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
|
||||||
// Internet Explorer 6-11
|
// Internet Explorer 6-11
|
||||||
@ -53,6 +53,7 @@ const isIE = !!document.documentMode
|
|||||||
// Edge 20+
|
// Edge 20+
|
||||||
const isEdge = !isIE && !!window.StyleMedia
|
const isEdge = !isIE && !!window.StyleMedia
|
||||||
|
|
||||||
|
let ipfsHandle
|
||||||
let popupIsOpen = false
|
let popupIsOpen = false
|
||||||
let notificationIsOpen = false
|
let notificationIsOpen = false
|
||||||
const openMetamaskTabsIDs = {}
|
const openMetamaskTabsIDs = {}
|
||||||
@ -158,7 +159,7 @@ async function initialize () {
|
|||||||
const initLangCode = await getFirstPreferredLangCode()
|
const initLangCode = await getFirstPreferredLangCode()
|
||||||
await setupController(initState, initLangCode)
|
await setupController(initState, initLangCode)
|
||||||
log.debug('MetaMask initialization complete.')
|
log.debug('MetaMask initialization complete.')
|
||||||
ipfsContent(initState.NetworkController.provider)
|
ipfsHandle = ipfsContent(initState.NetworkController.provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -262,6 +263,10 @@ function setupController (initState, initLangCode) {
|
|||||||
})
|
})
|
||||||
global.metamaskController = controller
|
global.metamaskController = controller
|
||||||
|
|
||||||
|
controller.networkController.on('networkDidChange', () => {
|
||||||
|
ipfsHandle && ipfsHandle.remove()
|
||||||
|
ipfsHandle = ipfsContent(controller.networkController.providerStore.getState())
|
||||||
|
})
|
||||||
|
|
||||||
// report failed transactions to Sentry
|
// report failed transactions to Sentry
|
||||||
controller.txController.on(`tx:status-update`, (txId, status) => {
|
controller.txController.on(`tx:status-update`, (txId, status) => {
|
||||||
|
@ -179,6 +179,7 @@ function blacklistedDomainCheck () {
|
|||||||
'gravityforms.com',
|
'gravityforms.com',
|
||||||
'harbourair.com',
|
'harbourair.com',
|
||||||
'ani.gamer.com.tw',
|
'ani.gamer.com.tw',
|
||||||
|
'blueskybooking.com',
|
||||||
]
|
]
|
||||||
var currentUrl = window.location.href
|
var currentUrl = window.location.href
|
||||||
var currentRegex
|
var currentRegex
|
||||||
|
130
app/scripts/controllers/detect-tokens.js
Normal file
130
app/scripts/controllers/detect-tokens.js
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
const Web3 = require('web3')
|
||||||
|
const contracts = require('eth-contract-metadata')
|
||||||
|
const { warn } = require('loglevel')
|
||||||
|
const { MAINNET } = require('./network/enums')
|
||||||
|
// By default, poll every 3 minutes
|
||||||
|
const DEFAULT_INTERVAL = 180 * 1000
|
||||||
|
const ERC20_ABI = [{'constant': true, 'inputs': [{'name': '_owner', 'type': 'address'}], 'name': 'balanceOf', 'outputs': [{'name': 'balance', 'type': 'uint256'}], 'payable': false, 'type': 'function'}]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A controller that polls for token exchange
|
||||||
|
* rates based on a user's current token list
|
||||||
|
*/
|
||||||
|
class DetectTokensController {
|
||||||
|
/**
|
||||||
|
* Creates a DetectTokensController
|
||||||
|
*
|
||||||
|
* @param {Object} [config] - Options to configure controller
|
||||||
|
*/
|
||||||
|
constructor ({ interval = DEFAULT_INTERVAL, preferences, network, keyringMemStore } = {}) {
|
||||||
|
this.preferences = preferences
|
||||||
|
this.interval = interval
|
||||||
|
this.network = network
|
||||||
|
this.keyringMemStore = keyringMemStore
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each token in eth-contract-metada, find check selectedAddress balance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
async detectNewTokens () {
|
||||||
|
if (!this.isActive) { return }
|
||||||
|
if (this._network.store.getState().provider.type !== MAINNET) { return }
|
||||||
|
this.web3.setProvider(this._network._provider)
|
||||||
|
for (const contractAddress in contracts) {
|
||||||
|
if (contracts[contractAddress].erc20 && !(this.tokenAddresses.includes(contractAddress.toLowerCase()))) {
|
||||||
|
this.detectTokenBalance(contractAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find if selectedAddress has tokens with contract in contractAddress.
|
||||||
|
*
|
||||||
|
* @param {string} contractAddress Hex address of the token contract to explore.
|
||||||
|
* @returns {boolean} If balance is detected, token is added.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
async detectTokenBalance (contractAddress) {
|
||||||
|
const ethContract = this.web3.eth.contract(ERC20_ABI).at(contractAddress)
|
||||||
|
ethContract.balanceOf(this.selectedAddress, (error, result) => {
|
||||||
|
if (!error) {
|
||||||
|
if (!result.isZero()) {
|
||||||
|
this._preferences.addToken(contractAddress, contracts[contractAddress].symbol, contracts[contractAddress].decimals)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn(`MetaMask - DetectTokensController balance fetch failed for ${contractAddress}.`, error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restart token detection polling period and call detectNewTokens
|
||||||
|
* in case of address change or user session initialization.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
restartTokenDetection () {
|
||||||
|
if (!(this.isActive && this.selectedAddress)) { return }
|
||||||
|
this.detectNewTokens()
|
||||||
|
this.interval = DEFAULT_INTERVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Number}
|
||||||
|
*/
|
||||||
|
set interval (interval) {
|
||||||
|
this._handle && clearInterval(this._handle)
|
||||||
|
if (!interval) { return }
|
||||||
|
this._handle = setInterval(() => { this.detectNewTokens() }, interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In setter when selectedAddress is changed, detectNewTokens and restart polling
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
set preferences (preferences) {
|
||||||
|
if (!preferences) { return }
|
||||||
|
this._preferences = preferences
|
||||||
|
preferences.store.subscribe(({ tokens }) => { this.tokenAddresses = tokens.map((obj) => { return obj.address }) })
|
||||||
|
preferences.store.subscribe(({ selectedAddress }) => {
|
||||||
|
if (this.selectedAddress !== selectedAddress) {
|
||||||
|
this.selectedAddress = selectedAddress
|
||||||
|
this.restartTokenDetection()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
set network (network) {
|
||||||
|
if (!network) { return }
|
||||||
|
this._network = network
|
||||||
|
this.web3 = new Web3(network._provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In setter when isUnlocked is updated to true, detectNewTokens and restart polling
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
set keyringMemStore (keyringMemStore) {
|
||||||
|
if (!keyringMemStore) { return }
|
||||||
|
this._keyringMemStore = keyringMemStore
|
||||||
|
this._keyringMemStore.subscribe(({ isUnlocked }) => {
|
||||||
|
if (this.isUnlocked !== isUnlocked) {
|
||||||
|
this.isUnlocked = isUnlocked
|
||||||
|
if (isUnlocked) { this.restartTokenDetection() }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal isActive state
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
get isActive () {
|
||||||
|
return this.isOpen && this.isUnlocked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DetectTokensController
|
@ -85,6 +85,30 @@ class PreferencesController {
|
|||||||
this.store.updateState({ identities })
|
this.store.updateState({ identities })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an address from state
|
||||||
|
*
|
||||||
|
* @param {string} address A hex address
|
||||||
|
* @returns {string} the address that was removed
|
||||||
|
*/
|
||||||
|
removeAddress (address) {
|
||||||
|
const identities = this.store.getState().identities
|
||||||
|
if (!identities[address]) {
|
||||||
|
throw new Error(`${address} can't be deleted cause it was not found`)
|
||||||
|
}
|
||||||
|
delete identities[address]
|
||||||
|
this.store.updateState({ identities })
|
||||||
|
|
||||||
|
// If the selected account is no longer valid,
|
||||||
|
// select an arbitrary other account:
|
||||||
|
if (address === this.getSelectedAddress()) {
|
||||||
|
const selected = Object.keys(identities)[0]
|
||||||
|
this.setSelectedAddress(selected)
|
||||||
|
}
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds addresses to the identities object without removing identities
|
* Adds addresses to the identities object without removing identities
|
||||||
*
|
*
|
||||||
|
@ -2,39 +2,43 @@ const extension = require('extensionizer')
|
|||||||
const resolver = require('./resolver.js')
|
const resolver = require('./resolver.js')
|
||||||
|
|
||||||
module.exports = function (provider) {
|
module.exports = function (provider) {
|
||||||
extension.webRequest.onBeforeRequest.addListener(details => {
|
function ipfsContent (details) {
|
||||||
const urlhttpreplace = details.url.replace(/\w+?:\/\//, '')
|
const name = details.url.substring(7, details.url.length - 1)
|
||||||
const url = urlhttpreplace.replace(/[\\/].*/g, '') // eslint-disable-line no-useless-escape
|
let clearTime = null
|
||||||
let domainhtml = urlhttpreplace.match(/[\\/].*/g) // eslint-disable-line no-useless-escape
|
extension.tabs.getSelected(null, tab => {
|
||||||
let clearTime = null
|
extension.tabs.update(tab.id, { url: 'loading.html' })
|
||||||
const name = url.replace(/\/$/g, '')
|
|
||||||
if (domainhtml === null) domainhtml = ['']
|
|
||||||
extension.tabs.getSelected(null, tab => {
|
|
||||||
extension.tabs.update(tab.id, { url: 'loading.html' })
|
|
||||||
|
|
||||||
clearTime = setTimeout(() => {
|
clearTime = setTimeout(() => {
|
||||||
return extension.tabs.update(tab.id, { url: '404.html' })
|
return extension.tabs.update(tab.id, { url: '404.html' })
|
||||||
}, 60000)
|
}, 60000)
|
||||||
|
|
||||||
resolver.resolve(name, provider).then(ipfsHash => {
|
resolver.resolve(name, provider).then(ipfsHash => {
|
||||||
clearTimeout(clearTime)
|
clearTimeout(clearTime)
|
||||||
let url = 'https://ipfs.infura.io/ipfs/' + ipfsHash + domainhtml[0]
|
let url = 'https://ipfs.infura.io/ipfs/' + ipfsHash
|
||||||
return fetch(url, { method: 'HEAD' }).then(response => response.status).then(statusCode => {
|
return fetch(url, { method: 'HEAD' }).then(response => response.status).then(statusCode => {
|
||||||
if (statusCode !== 200) return extension.tabs.update(tab.id, { url: '404.html' })
|
if (statusCode !== 200) return extension.tabs.update(tab.id, { url: '404.html' })
|
||||||
extension.tabs.update(tab.id, { url: url })
|
extension.tabs.update(tab.id, { url: url })
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
url = 'https://ipfs.infura.io/ipfs/' + ipfsHash + domainhtml[0]
|
url = 'https://ipfs.infura.io/ipfs/' + ipfsHash
|
||||||
extension.tabs.update(tab.id, {url: url})
|
extension.tabs.update(tab.id, {url: url})
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
clearTimeout(clearTime)
|
clearTimeout(clearTime)
|
||||||
const url = err === 'unsupport' ? 'unsupport' : 'error'
|
const url = err === 'unsupport' ? 'unsupport' : 'error'
|
||||||
extension.tabs.update(tab.id, {url: `${url}.html?name=${name}`})
|
extension.tabs.update(tab.id, {url: `${url}.html?name=${name}`})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return { cancel: true }
|
return { cancel: true }
|
||||||
}, {urls: ['*://*.eth/', '*://*.eth/*']})
|
}
|
||||||
|
|
||||||
|
extension.webRequest.onBeforeRequest.addListener(ipfsContent, {urls: ['*://*.eth/', '*://*.test/']})
|
||||||
|
|
||||||
|
return {
|
||||||
|
remove () {
|
||||||
|
extension.webRequest.onBeforeRequest.removeListener(ipfsContent)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ function getRegistrar (type) {
|
|||||||
|
|
||||||
module.exports.resolve = function (name, provider) {
|
module.exports.resolve = function (name, provider) {
|
||||||
const path = name.split('.')
|
const path = name.split('.')
|
||||||
const tld = path[path.length - 1]
|
const topLevelDomain = path[path.length - 1]
|
||||||
if (tld === 'eth') {
|
if (topLevelDomain === 'eth' || topLevelDomain === 'test') {
|
||||||
return ens(name, provider)
|
return ens(name, provider)
|
||||||
} else {
|
} else {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -8,8 +8,10 @@ module.exports = setupRaven
|
|||||||
|
|
||||||
// Setup raven / sentry remote error reporting
|
// Setup raven / sentry remote error reporting
|
||||||
function setupRaven (opts) {
|
function setupRaven (opts) {
|
||||||
const { release } = opts
|
const { releaseVersion } = opts
|
||||||
let ravenTarget
|
let ravenTarget
|
||||||
|
// detect brave
|
||||||
|
const isBrave = Boolean(window.chrome.ipcRenderer)
|
||||||
|
|
||||||
if (METAMASK_DEBUG) {
|
if (METAMASK_DEBUG) {
|
||||||
console.log('Setting up Sentry Remote Error Reporting: DEV')
|
console.log('Setting up Sentry Remote Error Reporting: DEV')
|
||||||
@ -20,9 +22,11 @@ function setupRaven (opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const client = Raven.config(ravenTarget, {
|
const client = Raven.config(ravenTarget, {
|
||||||
release,
|
releaseVersion,
|
||||||
transport: function (opts) {
|
transport: function (opts) {
|
||||||
|
opts.data.extra.isBrave = isBrave
|
||||||
const report = opts.data
|
const report = opts.data
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// handle error-like non-error exceptions
|
// handle error-like non-error exceptions
|
||||||
rewriteErrorLikeExceptions(report)
|
rewriteErrorLikeExceptions(report)
|
||||||
|
@ -28,7 +28,7 @@ function getStack () {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const getEnvironmentType = (url = window.location.href) => {
|
const getEnvironmentType = (url = window.location.href) => {
|
||||||
if (url.match(/popup.html(?:\?.+)*$/)) {
|
if (url.match(/popup.html(?:#.*)*$/)) {
|
||||||
return ENVIRONMENT_TYPE_POPUP
|
return ENVIRONMENT_TYPE_POPUP
|
||||||
} else if (url.match(/home.html(?:\?.+)*$/) || url.match(/home.html(?:#.*)*$/)) {
|
} else if (url.match(/home.html(?:\?.+)*$/) || url.match(/home.html(?:#.*)*$/)) {
|
||||||
return ENVIRONMENT_TYPE_FULLSCREEN
|
return ENVIRONMENT_TYPE_FULLSCREEN
|
||||||
|
@ -35,6 +35,7 @@ const TypedMessageManager = require('./lib/typed-message-manager')
|
|||||||
const TransactionController = require('./controllers/transactions')
|
const TransactionController = require('./controllers/transactions')
|
||||||
const BalancesController = require('./controllers/computed-balances')
|
const BalancesController = require('./controllers/computed-balances')
|
||||||
const TokenRatesController = require('./controllers/token-rates')
|
const TokenRatesController = require('./controllers/token-rates')
|
||||||
|
const DetectTokensController = require('./controllers/detect-tokens')
|
||||||
const ConfigManager = require('./lib/config-manager')
|
const ConfigManager = require('./lib/config-manager')
|
||||||
const nodeify = require('./lib/nodeify')
|
const nodeify = require('./lib/nodeify')
|
||||||
const accountImporter = require('./account-import-strategies')
|
const accountImporter = require('./account-import-strategies')
|
||||||
@ -47,6 +48,7 @@ const percentile = require('percentile')
|
|||||||
const seedPhraseVerifier = require('./lib/seed-phrase-verifier')
|
const seedPhraseVerifier = require('./lib/seed-phrase-verifier')
|
||||||
const cleanErrorStack = require('./lib/cleanErrorStack')
|
const cleanErrorStack = require('./lib/cleanErrorStack')
|
||||||
const log = require('loglevel')
|
const log = require('loglevel')
|
||||||
|
const TrezorKeyring = require('eth-trezor-keyring')
|
||||||
|
|
||||||
module.exports = class MetamaskController extends EventEmitter {
|
module.exports = class MetamaskController extends EventEmitter {
|
||||||
|
|
||||||
@ -124,7 +126,9 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// key mgmt
|
// key mgmt
|
||||||
|
const additionalKeyrings = [TrezorKeyring]
|
||||||
this.keyringController = new KeyringController({
|
this.keyringController = new KeyringController({
|
||||||
|
keyringTypes: additionalKeyrings,
|
||||||
initState: initState.KeyringController,
|
initState: initState.KeyringController,
|
||||||
getNetwork: this.networkController.getNetworkState.bind(this.networkController),
|
getNetwork: this.networkController.getNetworkState.bind(this.networkController),
|
||||||
encryptor: opts.encryptor || undefined,
|
encryptor: opts.encryptor || undefined,
|
||||||
@ -144,6 +148,13 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
this.accountTracker.syncWithAddresses(addresses)
|
this.accountTracker.syncWithAddresses(addresses)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// detect tokens controller
|
||||||
|
this.detectTokensController = new DetectTokensController({
|
||||||
|
preferences: this.preferencesController,
|
||||||
|
network: this.networkController,
|
||||||
|
keyringMemStore: this.keyringController.memStore,
|
||||||
|
})
|
||||||
|
|
||||||
// address book controller
|
// address book controller
|
||||||
this.addressBookController = new AddressBookController({
|
this.addressBookController = new AddressBookController({
|
||||||
initState: initState.AddressBookController,
|
initState: initState.AddressBookController,
|
||||||
@ -164,6 +175,13 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
})
|
})
|
||||||
this.txController.on('newUnapprovedTx', opts.showUnapprovedTx.bind(opts))
|
this.txController.on('newUnapprovedTx', opts.showUnapprovedTx.bind(opts))
|
||||||
|
|
||||||
|
this.txController.on(`tx:status-update`, (txId, status) => {
|
||||||
|
if (status === 'confirmed' || status === 'failed') {
|
||||||
|
const txMeta = this.txController.txStateManager.getTx(txId)
|
||||||
|
this.platform.showTransactionNotification(txMeta)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// computed balances (accounting for pending transactions)
|
// computed balances (accounting for pending transactions)
|
||||||
this.balancesController = new BalancesController({
|
this.balancesController = new BalancesController({
|
||||||
accountTracker: this.accountTracker,
|
accountTracker: this.accountTracker,
|
||||||
@ -351,8 +369,17 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
verifySeedPhrase: nodeify(this.verifySeedPhrase, this),
|
verifySeedPhrase: nodeify(this.verifySeedPhrase, this),
|
||||||
clearSeedWordCache: this.clearSeedWordCache.bind(this),
|
clearSeedWordCache: this.clearSeedWordCache.bind(this),
|
||||||
resetAccount: nodeify(this.resetAccount, this),
|
resetAccount: nodeify(this.resetAccount, this),
|
||||||
|
removeAccount: nodeify(this.removeAccount, this),
|
||||||
importAccountWithStrategy: nodeify(this.importAccountWithStrategy, this),
|
importAccountWithStrategy: nodeify(this.importAccountWithStrategy, this),
|
||||||
|
|
||||||
|
// hardware wallets
|
||||||
|
connectHardware: nodeify(this.connectHardware, this),
|
||||||
|
forgetDevice: nodeify(this.forgetDevice, this),
|
||||||
|
checkHardwareStatus: nodeify(this.checkHardwareStatus, this),
|
||||||
|
|
||||||
|
// TREZOR
|
||||||
|
unlockTrezorAccount: nodeify(this.unlockTrezorAccount, this),
|
||||||
|
|
||||||
// vault management
|
// vault management
|
||||||
submitPassword: nodeify(this.submitPassword, this),
|
submitPassword: nodeify(this.submitPassword, this),
|
||||||
|
|
||||||
@ -508,6 +535,127 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
this.preferencesController.setSelectedAddress(address)
|
this.preferencesController.setSelectedAddress(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Hardware
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch account list from a trezor device.
|
||||||
|
*
|
||||||
|
* @returns [] accounts
|
||||||
|
*/
|
||||||
|
async connectHardware (deviceName, page) {
|
||||||
|
|
||||||
|
switch (deviceName) {
|
||||||
|
case 'trezor':
|
||||||
|
const keyringController = this.keyringController
|
||||||
|
const oldAccounts = await keyringController.getAccounts()
|
||||||
|
let keyring = await keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)[0]
|
||||||
|
if (!keyring) {
|
||||||
|
keyring = await this.keyringController.addNewKeyring('Trezor Hardware')
|
||||||
|
}
|
||||||
|
let accounts = []
|
||||||
|
|
||||||
|
switch (page) {
|
||||||
|
case -1:
|
||||||
|
accounts = await keyring.getPreviousPage()
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
accounts = await keyring.getNextPage()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
accounts = await keyring.getFirstPage()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge with existing accounts
|
||||||
|
// and make sure addresses are not repeated
|
||||||
|
const accountsToTrack = [...new Set(oldAccounts.concat(accounts.map(a => a.address.toLowerCase())))]
|
||||||
|
this.accountTracker.syncWithAddresses(accountsToTrack)
|
||||||
|
return accounts
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error('MetamaskController:connectHardware - Unknown device')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the device is unlocked
|
||||||
|
*
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async checkHardwareStatus (deviceName) {
|
||||||
|
|
||||||
|
switch (deviceName) {
|
||||||
|
case 'trezor':
|
||||||
|
const keyringController = this.keyringController
|
||||||
|
const keyring = await keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)[0]
|
||||||
|
if (!keyring) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return keyring.isUnlocked()
|
||||||
|
default:
|
||||||
|
throw new Error('MetamaskController:checkHardwareStatus - Unknown device')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear
|
||||||
|
*
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async forgetDevice (deviceName) {
|
||||||
|
|
||||||
|
switch (deviceName) {
|
||||||
|
case 'trezor':
|
||||||
|
const keyringController = this.keyringController
|
||||||
|
const keyring = await keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)[0]
|
||||||
|
if (!keyring) {
|
||||||
|
throw new Error('MetamaskController:forgetDevice - Trezor Hardware keyring not found')
|
||||||
|
}
|
||||||
|
keyring.forgetDevice()
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
throw new Error('MetamaskController:forgetDevice - Unknown device')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports an account from a trezor device.
|
||||||
|
*
|
||||||
|
* @returns {} keyState
|
||||||
|
*/
|
||||||
|
async unlockTrezorAccount (index) {
|
||||||
|
const keyringController = this.keyringController
|
||||||
|
const keyring = await keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)[0]
|
||||||
|
if (!keyring) {
|
||||||
|
throw new Error('MetamaskController - No Trezor Hardware Keyring found')
|
||||||
|
}
|
||||||
|
|
||||||
|
keyring.setAccountToUnlock(index)
|
||||||
|
const oldAccounts = await keyringController.getAccounts()
|
||||||
|
const keyState = await keyringController.addNewAccount(keyring)
|
||||||
|
const newAccounts = await keyringController.getAccounts()
|
||||||
|
this.preferencesController.setAddresses(newAccounts)
|
||||||
|
newAccounts.forEach(address => {
|
||||||
|
if (!oldAccounts.includes(address)) {
|
||||||
|
this.preferencesController.setAccountLabel(address, `TREZOR #${parseInt(index, 10) + 1}`)
|
||||||
|
this.preferencesController.setSelectedAddress(address)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { identities } = this.preferencesController.store.getState()
|
||||||
|
return { ...keyState, identities }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Account Management
|
// Account Management
|
||||||
//
|
//
|
||||||
@ -620,6 +768,23 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
return selectedAddress
|
return selectedAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an account from state / storage.
|
||||||
|
*
|
||||||
|
* @param {string[]} address A hex address
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
async removeAccount (address) {
|
||||||
|
// Remove account from the preferences controller
|
||||||
|
this.preferencesController.removeAddress(address)
|
||||||
|
// Remove account from the account tracker controller
|
||||||
|
this.accountTracker.removeAccount(address)
|
||||||
|
// Remove account from the keyring
|
||||||
|
await this.keyringController.removeAccount(address)
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports an account with the specified import strategy.
|
* Imports an account with the specified import strategy.
|
||||||
* These are defined in app/scripts/account-import-strategies
|
* These are defined in app/scripts/account-import-strategies
|
||||||
@ -1267,10 +1432,12 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
set isClientOpen (open) {
|
set isClientOpen (open) {
|
||||||
this._isClientOpen = open
|
this._isClientOpen = open
|
||||||
this.isClientOpenAndUnlocked = this.getState().isUnlocked && open
|
this.isClientOpenAndUnlocked = this.getState().isUnlocked && open
|
||||||
|
this.detectTokensController.isOpen = open
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method for activating the retrieval of price data, which should only be fetched when the UI is visible.
|
* A method for activating the retrieval of price data and auto detect tokens,
|
||||||
|
* which should only be fetched when the UI is visible.
|
||||||
* @private
|
* @private
|
||||||
* @param {boolean} active - True if price data should be getting fetched.
|
* @param {boolean} active - True if price data should be getting fetched.
|
||||||
*/
|
*/
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const extension = require('extensionizer')
|
const extension = require('extensionizer')
|
||||||
|
const explorerLink = require('etherscan-link').createExplorerLink
|
||||||
|
|
||||||
class ExtensionPlatform {
|
class ExtensionPlatform {
|
||||||
|
|
||||||
@ -13,12 +14,21 @@ class ExtensionPlatform {
|
|||||||
extension.tabs.create({ url })
|
extension.tabs.create({ url })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeCurrentWindow () {
|
||||||
|
return extension.windows.getCurrent((windowDetails) => {
|
||||||
|
return extension.windows.remove(windowDetails.id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
getVersion () {
|
getVersion () {
|
||||||
return extension.runtime.getManifest().version
|
return extension.runtime.getManifest().version
|
||||||
}
|
}
|
||||||
|
|
||||||
openExtensionInBrowser () {
|
openExtensionInBrowser (route = null) {
|
||||||
const extensionURL = extension.runtime.getURL('home.html')
|
let extensionURL = extension.runtime.getURL('home.html')
|
||||||
|
if (route) {
|
||||||
|
extensionURL += `#${route}`
|
||||||
|
}
|
||||||
this.openWindow({ url: extensionURL })
|
this.openWindow({ url: extensionURL })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +41,59 @@ class ExtensionPlatform {
|
|||||||
cb(e)
|
cb(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showTransactionNotification (txMeta) {
|
||||||
|
|
||||||
|
const status = txMeta.status
|
||||||
|
if (status === 'confirmed') {
|
||||||
|
this._showConfirmedTransaction(txMeta)
|
||||||
|
} else if (status === 'failed') {
|
||||||
|
this._showFailedTransaction(txMeta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_showConfirmedTransaction (txMeta) {
|
||||||
|
|
||||||
|
this._subscribeToNotificationClicked()
|
||||||
|
|
||||||
|
const url = explorerLink(txMeta.hash, parseInt(txMeta.metamaskNetworkId))
|
||||||
|
const nonce = parseInt(txMeta.txParams.nonce, 16)
|
||||||
|
|
||||||
|
const title = 'Confirmed transaction'
|
||||||
|
const message = `Transaction ${nonce} confirmed! View on EtherScan`
|
||||||
|
this._showNotification(title, message, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
_showFailedTransaction (txMeta) {
|
||||||
|
|
||||||
|
const nonce = parseInt(txMeta.txParams.nonce, 16)
|
||||||
|
const title = 'Failed transaction'
|
||||||
|
const message = `Transaction ${nonce} failed! ${txMeta.err.message}`
|
||||||
|
this._showNotification(title, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
_showNotification (title, message, url) {
|
||||||
|
extension.notifications.create(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'type': 'basic',
|
||||||
|
'title': title,
|
||||||
|
'iconUrl': extension.extension.getURL('../../images/icon-64.png'),
|
||||||
|
'message': message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_subscribeToNotificationClicked () {
|
||||||
|
if (!extension.notifications.onClicked.hasListener(this._viewOnEtherScan)) {
|
||||||
|
extension.notifications.onClicked.addListener(this._viewOnEtherScan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_viewOnEtherScan (txId) {
|
||||||
|
if (txId.startsWith('http://')) {
|
||||||
|
global.metamaskController.platform.openWindow({ url: txId })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ExtensionPlatform
|
module.exports = ExtensionPlatform
|
||||||
|
@ -64,7 +64,6 @@ async function start () {
|
|||||||
css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss()
|
css = betaUIState ? NewMetaMaskUiCss() : OldMetaMaskUiCss()
|
||||||
deleteInjectedCss = injectCss(css)
|
deleteInjectedCss = injectCss(css)
|
||||||
}
|
}
|
||||||
if (state.appState.shouldClose) notificationManager.closePopup()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
25
docs/trezor-emulator.md
Normal file
25
docs/trezor-emulator.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Using the TREZOR simulator
|
||||||
|
|
||||||
|
You can install the TREZOR emulator and use it with Metamask.
|
||||||
|
Here is how:
|
||||||
|
|
||||||
|
## 1 - Install the TREZOR Bridge
|
||||||
|
|
||||||
|
Download the corresponding bridge for your platform from [this url](https://wallet.trezor.io/data/bridge/latest/index.html)
|
||||||
|
|
||||||
|
## 2 - Download and build the simulator
|
||||||
|
|
||||||
|
Follow this instructions: https://github.com/trezor/trezor-core/blob/master/docs/build.md
|
||||||
|
|
||||||
|
## 3 - Restart the bridge with emulator support (Mac OSx instructions)
|
||||||
|
|
||||||
|
`
|
||||||
|
# stop any existing instance of trezord
|
||||||
|
killall trezord
|
||||||
|
|
||||||
|
# start the bridge for the simulator
|
||||||
|
/Applications/Utilities/TREZOR\ Bridge/trezord -e 21324 >> /dev/null 2>&1 &
|
||||||
|
|
||||||
|
# launch the emulator
|
||||||
|
~/trezor-core/emu.sh
|
||||||
|
`
|
508
package-lock.json
generated
508
package-lock.json
generated
@ -3618,9 +3618,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"babel-preset-env": {
|
"babel-preset-env": {
|
||||||
"version": "1.6.1",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
|
||||||
"integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==",
|
"integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-plugin-check-es2015-constants": "^6.22.0",
|
"babel-plugin-check-es2015-constants": "^6.22.0",
|
||||||
"babel-plugin-syntax-trailing-function-commas": "^6.22.0",
|
"babel-plugin-syntax-trailing-function-commas": "^6.22.0",
|
||||||
@ -3649,7 +3649,7 @@
|
|||||||
"babel-plugin-transform-es2015-unicode-regex": "^6.22.0",
|
"babel-plugin-transform-es2015-unicode-regex": "^6.22.0",
|
||||||
"babel-plugin-transform-exponentiation-operator": "^6.22.0",
|
"babel-plugin-transform-exponentiation-operator": "^6.22.0",
|
||||||
"babel-plugin-transform-regenerator": "^6.22.0",
|
"babel-plugin-transform-regenerator": "^6.22.0",
|
||||||
"browserslist": "^2.1.2",
|
"browserslist": "^3.2.6",
|
||||||
"invariant": "^2.2.2",
|
"invariant": "^2.2.2",
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
}
|
}
|
||||||
@ -4224,6 +4224,7 @@
|
|||||||
"version": "2.10.1",
|
"version": "2.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
||||||
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
|
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"hoek": "2.x.x"
|
"hoek": "2.x.x"
|
||||||
},
|
},
|
||||||
@ -4231,7 +4232,8 @@
|
|||||||
"hoek": {
|
"hoek": {
|
||||||
"version": "2.16.3",
|
"version": "2.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4662,12 +4664,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"version": "2.11.0",
|
"version": "3.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
|
||||||
"integrity": "sha512-mNYp0RNeu1xueGuJFSXkU+K0nH+dBE/gcjtyhtNKfU8hwdrVIfoA7i5iFSjOmzkGdL2QaO7YX9ExiVPE7AY9JA==",
|
"integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"caniuse-lite": "^1.0.30000784",
|
"caniuse-lite": "^1.0.30000844",
|
||||||
"electron-to-chromium": "^1.3.30"
|
"electron-to-chromium": "^1.3.47"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"electron-to-chromium": {
|
||||||
|
"version": "1.3.52",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz",
|
||||||
|
"integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bs58": {
|
"bs58": {
|
||||||
@ -4994,9 +5003,9 @@
|
|||||||
"integrity": "sha1-MN/YMAnVcE8C3/s3clBo7RKjZrs="
|
"integrity": "sha1-MN/YMAnVcE8C3/s3clBo7RKjZrs="
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30000786",
|
"version": "1.0.30000865",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000786.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz",
|
||||||
"integrity": "sha1-G0Jc2FaNgFvFY4veSQXNhjVod0Y="
|
"integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw=="
|
||||||
},
|
},
|
||||||
"capture-stack-trace": {
|
"capture-stack-trace": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -6154,6 +6163,8 @@
|
|||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
|
||||||
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
|
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"boom": "2.x.x"
|
"boom": "2.x.x"
|
||||||
}
|
}
|
||||||
@ -6852,9 +6863,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"yauzl": {
|
"yauzl": {
|
||||||
"version": "2.9.2",
|
"version": "2.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||||
"integrity": "sha1-T7G8euH8L1cDe1SvasyP4QMcW3c=",
|
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"buffer-crc32": "~0.2.3",
|
"buffer-crc32": "~0.2.3",
|
||||||
@ -8368,22 +8379,41 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eth-hd-keyring": {
|
"eth-hd-keyring": {
|
||||||
"version": "1.2.2",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eth-hd-keyring/-/eth-hd-keyring-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/eth-hd-keyring/-/eth-hd-keyring-2.0.0.tgz",
|
||||||
"integrity": "sha1-rV9HkHRDapO0ObC5XHkJXCh5GII=",
|
"integrity": "sha512-lTeANNPNj/j08sWU7LUQZTsx9NUJaUsiOdVxeP0UI5kke7L+Sd7zJWBmCShudEVG8PkqKLE1KJo08o430sl6rw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bip39": "^2.2.0",
|
"bip39": "^2.2.0",
|
||||||
"eth-sig-util": "^1.4.2",
|
"eth-sig-util": "^2.0.1",
|
||||||
|
"ethereumjs-abi": "^0.6.5",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
"ethereumjs-wallet": "^0.6.0",
|
"ethereumjs-wallet": "^0.6.0",
|
||||||
"events": "^1.1.1",
|
"events": "^1.1.1",
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"eth-sig-util": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-lxHZOQspexk3DaGj4RBbWy4C/qNOWRnxpaJzNnYD3WEmC8shcJ4tHs7Xv878rzvILfJnSFSCCiKQhng1m80oBQ==",
|
||||||
|
"requires": {
|
||||||
|
"ethereumjs-util": "^5.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ethereumjs-abi": {
|
||||||
|
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
||||||
|
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
||||||
|
"requires": {
|
||||||
|
"bn.js": "^4.10.0",
|
||||||
|
"ethereumjs-util": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ethereumjs-util": {
|
"ethereumjs-util": {
|
||||||
"version": "5.1.4",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||||
"integrity": "sha512-wbeTc5prEzIWFSQUcEsCAZbqubtJKy6yS+oZMY1cGG6GLYzLjm4YhC2RNrWIg8hRYnclWpnZmx2zkiufQkmd3w==",
|
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.11.0",
|
"bn.js": "^4.11.0",
|
||||||
"create-hash": "^1.1.2",
|
"create-hash": "^1.1.2",
|
||||||
@ -8454,17 +8484,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eth-keyring-controller": {
|
"eth-keyring-controller": {
|
||||||
"version": "3.1.4",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-3.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-4.0.0.tgz",
|
||||||
"integrity": "sha512-NNlVB/TBc8p9CblwECjPlUR+7MNQKiBa7tEFxIzZ9MjjNCEYPWDXTm0vJZzuDtVmFxYwIA53UD0QEn0QNxWNEQ==",
|
"integrity": "sha512-D3Uj0b97vzEl/zXvrwYjFUYsz5gB4tnl/iMWqOm8jsvaREuHHbxRkm3iU/LG4fT8NGwS+fG8sLRPNBPu2/wRsA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bip39": "^2.4.0",
|
"bip39": "^2.4.0",
|
||||||
"bluebird": "^3.5.0",
|
"bluebird": "^3.5.0",
|
||||||
"browser-passworder": "^2.0.3",
|
"browser-passworder": "^2.0.3",
|
||||||
"eth-hd-keyring": "^1.2.2",
|
"eth-hd-keyring": "^2.0.0",
|
||||||
"eth-sig-util": "^1.4.0",
|
"eth-sig-util": "^1.4.0",
|
||||||
"eth-simple-keyring": "^1.2.2",
|
"eth-simple-keyring": "^2.0.0",
|
||||||
"ethereumjs-util": "^5.1.2",
|
"ethereumjs-util": "^5.1.2",
|
||||||
"loglevel": "^1.5.0",
|
"loglevel": "^1.5.0",
|
||||||
"obs-store": "^2.4.1",
|
"obs-store": "^2.4.1",
|
||||||
@ -8650,13 +8680,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz",
|
||||||
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
|
"integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
|
||||||
"ethereumjs-util": "^5.1.1"
|
"ethereumjs-util": "^5.1.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ethereumjs-abi": {
|
"ethereumjs-abi": {
|
||||||
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
||||||
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git",
|
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.10.0",
|
"bn.js": "^4.10.0",
|
||||||
"ethereumjs-util": "^5.0.0"
|
"ethereumjs-util": "^5.0.0"
|
||||||
@ -8679,23 +8708,42 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eth-simple-keyring": {
|
"eth-simple-keyring": {
|
||||||
"version": "1.2.2",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eth-simple-keyring/-/eth-simple-keyring-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/eth-simple-keyring/-/eth-simple-keyring-2.0.0.tgz",
|
||||||
"integrity": "sha512-uQVBYshHUOaXVoat1BpLA/QNMCr4hgdFBgwIB7rRmQ+m3vQQAseUsOM+biPDYzq6end+6LjcccElLpQaIZe6dg==",
|
"integrity": "sha512-4dMbkIy2k1qotDTjWINvXG+7tBmofp0YUhlXgcG0+I3w684V46+MAHEkBtD2Y09iEeIB07RDXrezKP9WxOpynA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"eth-sig-util": "^1.4.2",
|
"eth-sig-util": "^2.0.1",
|
||||||
|
"ethereumjs-abi": "^0.6.5",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
"ethereumjs-wallet": "^0.6.0",
|
"ethereumjs-wallet": "^0.6.0",
|
||||||
"events": "^1.1.1",
|
"events": "^1.1.1",
|
||||||
"xtend": "^4.0.1"
|
"xtend": "^4.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"eth-sig-util": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-lxHZOQspexk3DaGj4RBbWy4C/qNOWRnxpaJzNnYD3WEmC8shcJ4tHs7Xv878rzvILfJnSFSCCiKQhng1m80oBQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ethereumjs-util": "^5.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ethereumjs-abi": {
|
||||||
|
"version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
||||||
|
"from": "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7",
|
||||||
|
"requires": {
|
||||||
|
"bn.js": "^4.10.0",
|
||||||
|
"ethereumjs-util": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ethereumjs-util": {
|
"ethereumjs-util": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.11.0",
|
"bn.js": "^4.11.0",
|
||||||
"create-hash": "^1.1.2",
|
"create-hash": "^1.1.2",
|
||||||
@ -8877,6 +8925,63 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eth-trezor-keyring": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eth-trezor-keyring/-/eth-trezor-keyring-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-7ynDXiXGQOh9CslksJSmGGK726lV9fTnIp2QQnjbZJgR4zJIoSUYQYKvT2wXcxLhVrTUl2hLjwKN9QGqDCMVwA==",
|
||||||
|
"requires": {
|
||||||
|
"eth-sig-util": "^1.4.2",
|
||||||
|
"ethereumjs-tx": "^1.3.4",
|
||||||
|
"ethereumjs-util": "^5.1.5",
|
||||||
|
"events": "^2.0.0",
|
||||||
|
"hdkey": "0.8.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ethereum-common": {
|
||||||
|
"version": "0.0.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz",
|
||||||
|
"integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8="
|
||||||
|
},
|
||||||
|
"ethereumjs-tx": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-wzsEs0mCSLqdDjqSDg6AWh1hyL8H3R/pyZxehkcCXq5MJEFXWz+eJ2jSv+3yEaLy6tXrNP7dmqS3Kyb3zAONkg==",
|
||||||
|
"requires": {
|
||||||
|
"ethereum-common": "^0.0.18",
|
||||||
|
"ethereumjs-util": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg=="
|
||||||
|
},
|
||||||
|
"hdkey": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.8.0.tgz",
|
||||||
|
"integrity": "sha512-oYsdlK22eobT68N5faWI3776f6tOLyqxLLYwxMx+TP0rkWzuCs0oiOm2VbLWcxdpHFP4LtiRR8udaIX8VkEaZQ==",
|
||||||
|
"requires": {
|
||||||
|
"coinstring": "^2.0.0",
|
||||||
|
"safe-buffer": "^5.1.1",
|
||||||
|
"secp256k1": "^3.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"eth-tx-summary": {
|
"eth-tx-summary": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.1.tgz",
|
||||||
@ -11795,9 +11900,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ganache-core": {
|
"ganache-core": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.1.5.tgz",
|
||||||
"integrity": "sha512-fHDXzzcaB+jZC4q3HnQdcSj/otcVnQ6ddyqmtFtcyv29ET/44nXL5++3MmYBmAn3iLxV8PUgL+meUpm1aim9kg==",
|
"integrity": "sha512-PuHUfISgrQknb7JpspxSzhpoYfqBWoOdTBHQj/81gu6YypRUHzD2Z6gZmFDxDzG30MFElEHp8JtexaGdgq9iYw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"abstract-leveldown": "^3.0.0",
|
"abstract-leveldown": "^3.0.0",
|
||||||
@ -11809,7 +11914,7 @@
|
|||||||
"clone": "^2.1.1",
|
"clone": "^2.1.1",
|
||||||
"ethereumjs-account": "~2.0.4",
|
"ethereumjs-account": "~2.0.4",
|
||||||
"ethereumjs-block": "~1.2.2",
|
"ethereumjs-block": "~1.2.2",
|
||||||
"ethereumjs-tx": "^1.3.0",
|
"ethereumjs-tx": "1.3.4",
|
||||||
"ethereumjs-util": "^5.2.0",
|
"ethereumjs-util": "^5.2.0",
|
||||||
"ethereumjs-vm": "2.3.5",
|
"ethereumjs-vm": "2.3.5",
|
||||||
"ethereumjs-wallet": "~0.6.0",
|
"ethereumjs-wallet": "~0.6.0",
|
||||||
@ -11966,6 +12071,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ethereumjs-tx": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.4.tgz",
|
||||||
|
"integrity": "sha512-kOgUd5jC+0tgV7t52UDECMMz9Uf+Lro+6fSpCvzWemtXfMEcwI3EOxf5mVPMRbTFkMMhuERokNNVF3jItAjidg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ethereum-common": "^0.0.18",
|
||||||
|
"ethereumjs-util": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ethereum-common": {
|
||||||
|
"version": "0.0.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz",
|
||||||
|
"integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ethereumjs-util": {
|
"ethereumjs-util": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||||
@ -12130,9 +12253,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
|
||||||
"integrity": "sha512-2NkHdPKjDBj3CHdnAGNpmlliryKqF+n9MYXX7/wsVC4yqYocKreKNjydPDvT3wShAZnndlM0RytEfTALCDvz7A==",
|
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
@ -12307,12 +12430,16 @@
|
|||||||
"generate-function": {
|
"generate-function": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
|
||||||
"integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ="
|
"integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"generate-object-property": {
|
"generate-object-property": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
|
||||||
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
|
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-property": "^1.0.0"
|
"is-property": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -13298,21 +13425,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
||||||
"integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
|
"integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
|
||||||
},
|
},
|
||||||
"assert-plus": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
|
|
||||||
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
|
|
||||||
},
|
|
||||||
"aws-sign2": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
|
|
||||||
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
|
|
||||||
},
|
|
||||||
"caseless": {
|
|
||||||
"version": "0.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
|
|
||||||
"integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c="
|
|
||||||
},
|
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
|
||||||
@ -13341,79 +13453,16 @@
|
|||||||
"is-extendable": "^1.0.1"
|
"is-extendable": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"form-data": {
|
|
||||||
"version": "2.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
|
|
||||||
"integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
|
|
||||||
"requires": {
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"combined-stream": "^1.0.5",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"get-stdin": {
|
"get-stdin": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
||||||
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
|
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
|
||||||
},
|
},
|
||||||
"har-validator": {
|
|
||||||
"version": "2.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
|
|
||||||
"integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
|
|
||||||
"requires": {
|
|
||||||
"chalk": "^1.1.1",
|
|
||||||
"commander": "^2.9.0",
|
|
||||||
"is-my-json-valid": "^2.12.4",
|
|
||||||
"pinkie-promise": "^2.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
|
||||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
|
||||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^2.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.2",
|
|
||||||
"has-ansi": "^2.0.0",
|
|
||||||
"strip-ansi": "^3.0.0",
|
|
||||||
"supports-color": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has-flag": {
|
"has-flag": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||||
},
|
},
|
||||||
"http-signature": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
|
|
||||||
"requires": {
|
|
||||||
"assert-plus": "^0.2.0",
|
|
||||||
"jsprim": "^1.2.2",
|
|
||||||
"sshpk": "^1.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-extendable": {
|
"is-extendable": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
|
||||||
@ -13428,9 +13477,9 @@
|
|||||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="
|
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="
|
||||||
},
|
},
|
||||||
"node-sass": {
|
"node-sass": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.2.tgz",
|
||||||
"integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==",
|
"integrity": "sha512-LdxoJLZutx0aQXHtWIYwJKMj+9pTjneTcLWJgzf2XbGu0q5pRNqW5QvFCEdm3mc5rJOdru/mzln5d0EZLacf6g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-foreach": "^0.1.3",
|
"async-foreach": "^0.1.3",
|
||||||
"chalk": "^1.1.1",
|
"chalk": "^1.1.1",
|
||||||
@ -13447,7 +13496,7 @@
|
|||||||
"nan": "^2.10.0",
|
"nan": "^2.10.0",
|
||||||
"node-gyp": "^3.3.1",
|
"node-gyp": "^3.3.1",
|
||||||
"npmlog": "^4.0.0",
|
"npmlog": "^4.0.0",
|
||||||
"request": "~2.79.0",
|
"request": "2.87.0",
|
||||||
"sass-graph": "^2.2.4",
|
"sass-graph": "^2.2.4",
|
||||||
"stdout-stream": "^1.4.0",
|
"stdout-stream": "^1.4.0",
|
||||||
"true-case-path": "^1.0.2"
|
"true-case-path": "^1.0.2"
|
||||||
@ -13496,38 +13545,6 @@
|
|||||||
"extend-shallow": "^3.0.2"
|
"extend-shallow": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"qs": {
|
|
||||||
"version": "6.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
|
|
||||||
"integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw="
|
|
||||||
},
|
|
||||||
"request": {
|
|
||||||
"version": "2.79.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
|
|
||||||
"integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
|
|
||||||
"requires": {
|
|
||||||
"aws-sign2": "~0.6.0",
|
|
||||||
"aws4": "^1.2.1",
|
|
||||||
"caseless": "~0.11.0",
|
|
||||||
"combined-stream": "~1.0.5",
|
|
||||||
"extend": "~3.0.0",
|
|
||||||
"forever-agent": "~0.6.1",
|
|
||||||
"form-data": "~2.1.1",
|
|
||||||
"har-validator": "~2.0.6",
|
|
||||||
"hawk": "~3.1.3",
|
|
||||||
"http-signature": "~1.1.0",
|
|
||||||
"is-typedarray": "~1.0.0",
|
|
||||||
"isstream": "~0.1.2",
|
|
||||||
"json-stringify-safe": "~5.0.1",
|
|
||||||
"mime-types": "~2.1.7",
|
|
||||||
"oauth-sign": "~0.8.1",
|
|
||||||
"qs": "~6.3.0",
|
|
||||||
"stringstream": "~0.0.4",
|
|
||||||
"tough-cookie": "~2.3.0",
|
|
||||||
"tunnel-agent": "~0.4.1",
|
|
||||||
"uuid": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||||
@ -13550,16 +13567,6 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"has-flag": "^3.0.0"
|
"has-flag": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"tunnel-agent": {
|
|
||||||
"version": "0.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
|
|
||||||
"integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"version": "3.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
|
|
||||||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -14541,6 +14548,8 @@
|
|||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
|
||||||
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
|
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"boom": "2.x.x",
|
"boom": "2.x.x",
|
||||||
"cryptiles": "2.x.x",
|
"cryptiles": "2.x.x",
|
||||||
@ -14551,7 +14560,9 @@
|
|||||||
"hoek": {
|
"hoek": {
|
||||||
"version": "2.16.3",
|
"version": "2.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -15848,12 +15859,16 @@
|
|||||||
"is-my-ip-valid": {
|
"is-my-ip-valid": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
|
||||||
"integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ=="
|
"integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"is-my-json-valid": {
|
"is-my-json-valid": {
|
||||||
"version": "2.17.2",
|
"version": "2.17.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz",
|
||||||
"integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==",
|
"integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"generate-function": "^2.0.0",
|
"generate-function": "^2.0.0",
|
||||||
"generate-object-property": "^1.1.0",
|
"generate-object-property": "^1.1.0",
|
||||||
@ -15977,7 +15992,9 @@
|
|||||||
"is-property": {
|
"is-property": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"is-redirect": {
|
"is-redirect": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -16945,7 +16962,9 @@
|
|||||||
"jsonpointer": {
|
"jsonpointer": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
|
||||||
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk="
|
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"jsprim": {
|
"jsprim": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
@ -17855,9 +17874,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"level-sublevel": {
|
"level-sublevel": {
|
||||||
"version": "6.6.2",
|
"version": "6.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.5.tgz",
|
||||||
"integrity": "sha512-+hptqmFYPKFju9QG4F6scvx3ZXkhrSmmhYui+hPzRn/jiC3DJ6VNZRKsIhGMpeajVBWfRV7XiysUThrJ/7PgXQ==",
|
"integrity": "sha512-SBSR60x+dghhwGUxPKS+BvV1xNqnwsEUBKmnFepPaHJ6VkBXyPK9SImGc3K2BkwBfpxlt7GKkBNlCnrdufsejA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bytewise": "~1.1.0",
|
"bytewise": "~1.1.0",
|
||||||
@ -18690,9 +18709,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"log4js": {
|
"log4js": {
|
||||||
"version": "2.10.0",
|
"version": "2.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/log4js/-/log4js-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz",
|
||||||
"integrity": "sha512-NnhN9PjFF9zhxinAjlmDYvkqqrIW+yA3LLJAoTJ3fs6d1zru86OqQHfsxiUcc1kRq3z+faGR4DeyXUfiNbVxKQ==",
|
"integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"amqplib": "^0.5.2",
|
"amqplib": "^0.5.2",
|
||||||
@ -18711,9 +18730,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"circular-json": {
|
"circular-json": {
|
||||||
"version": "0.5.4",
|
"version": "0.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz",
|
||||||
"integrity": "sha512-vnJA8KS0BfOihugYEUkLRcnmq21FbuivbxgzDLXNs3zIk4KllV4Mx4UuTzBXht9F00C7QfD1YqMXg1zP6EXpig==",
|
"integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
@ -20641,9 +20660,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-sass": {
|
"node-sass": {
|
||||||
"version": "4.9.0",
|
"version": "4.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.2.tgz",
|
||||||
"integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==",
|
"integrity": "sha512-LdxoJLZutx0aQXHtWIYwJKMj+9pTjneTcLWJgzf2XbGu0q5pRNqW5QvFCEdm3mc5rJOdru/mzln5d0EZLacf6g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"async-foreach": "^0.1.3",
|
"async-foreach": "^0.1.3",
|
||||||
@ -20661,30 +20680,12 @@
|
|||||||
"nan": "^2.10.0",
|
"nan": "^2.10.0",
|
||||||
"node-gyp": "^3.3.1",
|
"node-gyp": "^3.3.1",
|
||||||
"npmlog": "^4.0.0",
|
"npmlog": "^4.0.0",
|
||||||
"request": "~2.79.0",
|
"request": "2.87.0",
|
||||||
"sass-graph": "^2.2.4",
|
"sass-graph": "^2.2.4",
|
||||||
"stdout-stream": "^1.4.0",
|
"stdout-stream": "^1.4.0",
|
||||||
"true-case-path": "^1.0.2"
|
"true-case-path": "^1.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"assert-plus": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
|
|
||||||
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"aws-sign2": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
|
|
||||||
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"caseless": {
|
|
||||||
"version": "0.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
|
|
||||||
"integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
|
||||||
@ -20695,97 +20696,17 @@
|
|||||||
"which": "^1.2.9"
|
"which": "^1.2.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"form-data": {
|
|
||||||
"version": "2.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
|
|
||||||
"integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"combined-stream": "^1.0.5",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"get-stdin": {
|
"get-stdin": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
||||||
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
|
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"har-validator": {
|
|
||||||
"version": "2.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
|
|
||||||
"integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"chalk": "^1.1.1",
|
|
||||||
"commander": "^2.9.0",
|
|
||||||
"is-my-json-valid": "^2.12.4",
|
|
||||||
"pinkie-promise": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"http-signature": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"assert-plus": "^0.2.0",
|
|
||||||
"jsprim": "^1.2.2",
|
|
||||||
"sshpk": "^1.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.10.0",
|
"version": "2.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
|
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
|
||||||
"qs": {
|
|
||||||
"version": "6.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
|
|
||||||
"integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"request": {
|
|
||||||
"version": "2.79.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
|
|
||||||
"integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"aws-sign2": "~0.6.0",
|
|
||||||
"aws4": "^1.2.1",
|
|
||||||
"caseless": "~0.11.0",
|
|
||||||
"combined-stream": "~1.0.5",
|
|
||||||
"extend": "~3.0.0",
|
|
||||||
"forever-agent": "~0.6.1",
|
|
||||||
"form-data": "~2.1.1",
|
|
||||||
"har-validator": "~2.0.6",
|
|
||||||
"hawk": "~3.1.3",
|
|
||||||
"http-signature": "~1.1.0",
|
|
||||||
"is-typedarray": "~1.0.0",
|
|
||||||
"isstream": "~0.1.2",
|
|
||||||
"json-stringify-safe": "~5.0.1",
|
|
||||||
"mime-types": "~2.1.7",
|
|
||||||
"oauth-sign": "~0.8.1",
|
|
||||||
"qs": "~6.3.0",
|
|
||||||
"stringstream": "~0.0.4",
|
|
||||||
"tough-cookie": "~2.3.0",
|
|
||||||
"tunnel-agent": "~0.4.1",
|
|
||||||
"uuid": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tunnel-agent": {
|
|
||||||
"version": "0.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
|
|
||||||
"integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"version": "3.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
|
|
||||||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
|
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -28232,6 +28153,8 @@
|
|||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
|
||||||
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
|
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"hoek": "2.x.x"
|
"hoek": "2.x.x"
|
||||||
},
|
},
|
||||||
@ -28239,7 +28162,9 @@
|
|||||||
"hoek": {
|
"hoek": {
|
||||||
"version": "2.16.3",
|
"version": "2.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -29005,7 +28930,9 @@
|
|||||||
"stringstream": {
|
"stringstream": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
|
||||||
"integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA=="
|
"integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@ -30764,7 +30691,6 @@
|
|||||||
"version": "3.1.5",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-typedarray": "^1.0.0"
|
"is-typedarray": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -31788,7 +31714,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/web3/-/web3-0.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/web3/-/web3-0.20.3.tgz",
|
||||||
"integrity": "sha1-yqRDc9yIFayHZ73ba6cwc5ZMqos=",
|
"integrity": "sha1-yqRDc9yIFayHZ73ba6cwc5ZMqos=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
|
|
||||||
"crypto-js": "^3.1.4",
|
"crypto-js": "^3.1.4",
|
||||||
"utf8": "^2.1.1",
|
"utf8": "^2.1.1",
|
||||||
"xhr2": "*",
|
"xhr2": "*",
|
||||||
@ -31797,7 +31722,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bignumber.js": {
|
"bignumber.js": {
|
||||||
"version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
|
"version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
|
||||||
"from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git"
|
"from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -32296,8 +32221,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"underscore": "1.8.3",
|
"underscore": "1.8.3",
|
||||||
"web3-core-helpers": "1.0.0-beta.34",
|
"web3-core-helpers": "1.0.0-beta.34"
|
||||||
"websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"underscore": {
|
"underscore": {
|
||||||
@ -32308,8 +32232,7 @@
|
|||||||
},
|
},
|
||||||
"websocket": {
|
"websocket": {
|
||||||
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
|
"version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
|
||||||
"from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
|
"from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^2.2.0",
|
"debug": "^2.2.0",
|
||||||
"nan": "^2.3.3",
|
"nan": "^2.3.3",
|
||||||
@ -33665,8 +33588,7 @@
|
|||||||
"yaeti": {
|
"yaeti": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||||
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=",
|
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
|
31
package.json
31
package.json
@ -54,9 +54,19 @@
|
|||||||
"babelify",
|
"babelify",
|
||||||
{
|
{
|
||||||
"presets": [
|
"presets": [
|
||||||
"es2015",
|
[
|
||||||
|
"env",
|
||||||
|
{
|
||||||
|
"debug": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"stage-0"
|
"stage-0"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"transform-class-properties"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"reactify",
|
"reactify",
|
||||||
@ -94,7 +104,8 @@
|
|||||||
"eslint-plugin-react": "^7.4.0",
|
"eslint-plugin-react": "^7.4.0",
|
||||||
"eth-bin-to-ops": "^1.0.1",
|
"eth-bin-to-ops": "^1.0.1",
|
||||||
"eth-contract-metadata": "github:MetaMask/eth-contract-metadata#master",
|
"eth-contract-metadata": "github:MetaMask/eth-contract-metadata#master",
|
||||||
"eth-hd-keyring": "^1.2.1",
|
"eth-ens-namehash": "^2.0.8",
|
||||||
|
"eth-hd-keyring": "^2.0.0",
|
||||||
"eth-json-rpc-filters": "^1.2.6",
|
"eth-json-rpc-filters": "^1.2.6",
|
||||||
"eth-json-rpc-infura": "^3.0.0",
|
"eth-json-rpc-infura": "^3.0.0",
|
||||||
"eth-method-registry": "^1.0.0",
|
"eth-method-registry": "^1.0.0",
|
||||||
@ -102,6 +113,7 @@
|
|||||||
"eth-query": "^2.1.2",
|
"eth-query": "^2.1.2",
|
||||||
"eth-sig-util": "^1.4.2",
|
"eth-sig-util": "^1.4.2",
|
||||||
"eth-token-tracker": "^1.1.4",
|
"eth-token-tracker": "^1.1.4",
|
||||||
|
"eth-trezor-keyring": "^0.1.0",
|
||||||
"ethereumjs-abi": "^0.6.4",
|
"ethereumjs-abi": "^0.6.4",
|
||||||
"ethereumjs-tx": "^1.3.0",
|
"ethereumjs-tx": "^1.3.0",
|
||||||
"ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
"ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
|
||||||
@ -141,6 +153,7 @@
|
|||||||
"metamascara": "^2.0.0",
|
"metamascara": "^2.0.0",
|
||||||
"metamask-logo": "^2.1.4",
|
"metamask-logo": "^2.1.4",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
|
"multihashes": "^0.4.12",
|
||||||
"multiplex": "^6.7.0",
|
"multiplex": "^6.7.0",
|
||||||
"number-to-bn": "^1.7.0",
|
"number-to-bn": "^1.7.0",
|
||||||
"obj-multiplex": "^1.0.0",
|
"obj-multiplex": "^1.0.0",
|
||||||
@ -194,9 +207,7 @@
|
|||||||
"web3": "^0.20.1",
|
"web3": "^0.20.1",
|
||||||
"web3-provider-engine": "^14.0.5",
|
"web3-provider-engine": "^14.0.5",
|
||||||
"web3-stream-provider": "^3.0.1",
|
"web3-stream-provider": "^3.0.1",
|
||||||
"xtend": "^4.0.1",
|
"xtend": "^4.0.1"
|
||||||
"multihashes": "^0.4.12",
|
|
||||||
"eth-ens-namehash": "^2.0.8"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sentry/cli": "^1.30.3",
|
"@sentry/cli": "^1.30.3",
|
||||||
@ -208,6 +219,7 @@
|
|||||||
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
"babel-polyfill": "^6.23.0",
|
"babel-polyfill": "^6.23.0",
|
||||||
|
"babel-preset-env": "^1.7.0",
|
||||||
"babel-preset-react": "^6.24.1",
|
"babel-preset-react": "^6.24.1",
|
||||||
"babel-preset-stage-0": "^6.24.1",
|
"babel-preset-stage-0": "^6.24.1",
|
||||||
"babel-register": "^6.7.2",
|
"babel-register": "^6.7.2",
|
||||||
@ -233,11 +245,11 @@
|
|||||||
"eslint-plugin-mocha": "^5.0.0",
|
"eslint-plugin-mocha": "^5.0.0",
|
||||||
"eslint-plugin-react": "^7.4.0",
|
"eslint-plugin-react": "^7.4.0",
|
||||||
"eth-json-rpc-middleware": "^1.6.0",
|
"eth-json-rpc-middleware": "^1.6.0",
|
||||||
"eth-keyring-controller": "^3.1.4",
|
"eth-keyring-controller": "^4.0.0",
|
||||||
"file-loader": "^1.1.11",
|
"file-loader": "^1.1.11",
|
||||||
"fs-promise": "^2.0.3",
|
"fs-promise": "^2.0.3",
|
||||||
"ganache-cli": "^6.1.0",
|
"ganache-cli": "^6.1.0",
|
||||||
"ganache-core": "^2.1.3",
|
"ganache-core": "^2.1.5",
|
||||||
"geckodriver": "^1.11.0",
|
"geckodriver": "^1.11.0",
|
||||||
"gh-pages": "^1.2.0",
|
"gh-pages": "^1.2.0",
|
||||||
"gifencoder": "^1.1.0",
|
"gifencoder": "^1.1.0",
|
||||||
@ -273,7 +285,7 @@
|
|||||||
"mocha-jsdom": "^1.1.0",
|
"mocha-jsdom": "^1.1.0",
|
||||||
"mocha-sinon": "^2.0.0",
|
"mocha-sinon": "^2.0.0",
|
||||||
"nock": "^9.0.14",
|
"nock": "^9.0.14",
|
||||||
"node-sass": "^4.9.0",
|
"node-sass": "^4.9.2",
|
||||||
"nsp": "^3.2.1",
|
"nsp": "^3.2.1",
|
||||||
"nyc": "^13.0.0",
|
"nyc": "^13.0.0",
|
||||||
"open": "0.0.5",
|
"open": "0.0.5",
|
||||||
@ -306,6 +318,7 @@
|
|||||||
"watchify": "^3.11.0"
|
"watchify": "^3.11.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.0.0"
|
"node": "8.11.3",
|
||||||
|
"npm": "^6.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,4 +321,51 @@ describe('Using MetaMask with an existing account', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Connects to a Hardware wallet', () => {
|
||||||
|
it('choose Connect Hardware Wallet from the account menu', async () => {
|
||||||
|
await driver.findElement(By.css('.account-menu__icon')).click()
|
||||||
|
await delay(regularDelayMs)
|
||||||
|
|
||||||
|
const [connectAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Connect Hardware Wallet')]`))
|
||||||
|
await connectAccount.click()
|
||||||
|
await delay(regularDelayMs)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should open the TREZOR Connect popup', async () => {
|
||||||
|
const connectButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Connect to Trezor')]`))
|
||||||
|
await connectButtons[0].click()
|
||||||
|
await delay(regularDelayMs)
|
||||||
|
const allWindows = await driver.getAllWindowHandles()
|
||||||
|
switch (process.env.SELENIUM_BROWSER) {
|
||||||
|
case 'chrome':
|
||||||
|
assert.equal(allWindows.length, 2)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
assert.equal(allWindows.length, 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should show the "Browser not supported" screen for non Chrome browsers', async () => {
|
||||||
|
if (process.env.SELENIUM_BROWSER !== 'chrome') {
|
||||||
|
const title = await findElements(driver, By.xpath(`//h3[contains(text(), 'Your Browser is not supported...')]`))
|
||||||
|
assert.equal(title.length, 1)
|
||||||
|
|
||||||
|
const downloadChromeButtons = await findElements(driver, By.xpath(`//button[contains(text(), 'Download Google Chrome')]`))
|
||||||
|
assert.equal(downloadChromeButtons.length, 1)
|
||||||
|
|
||||||
|
await downloadChromeButtons[0].click()
|
||||||
|
await delay(regularDelayMs)
|
||||||
|
|
||||||
|
const [newUITab, downloadChromeTab] = await driver.getAllWindowHandles()
|
||||||
|
|
||||||
|
await driver.switchTo().window(downloadChromeTab)
|
||||||
|
await delay(regularDelayMs)
|
||||||
|
const tabUrl = await driver.getCurrentUrl()
|
||||||
|
assert.equal(tabUrl, 'https://www.google.com/chrome/')
|
||||||
|
await driver.close()
|
||||||
|
await delay(regularDelayMs)
|
||||||
|
await driver.switchTo().window(newUITab)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -472,7 +472,7 @@ describe('MetaMask', function () {
|
|||||||
await confirmButton.click()
|
await confirmButton.click()
|
||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
|
|
||||||
await closeAllWindowHandlesExcept(driver, [extension, dapp])
|
await waitUntilXWindowHandles(driver, 2)
|
||||||
await driver.switchTo().window(extension)
|
await driver.switchTo().window(extension)
|
||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
})
|
})
|
||||||
|
141
test/unit/app/controllers/detect-tokens-test.js
Normal file
141
test/unit/app/controllers/detect-tokens-test.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
const assert = require('assert')
|
||||||
|
const sinon = require('sinon')
|
||||||
|
const ObservableStore = require('obs-store')
|
||||||
|
const DetectTokensController = require('../../../../app/scripts/controllers/detect-tokens')
|
||||||
|
const NetworkController = require('../../../../app/scripts/controllers/network/network')
|
||||||
|
const PreferencesController = require('../../../../app/scripts/controllers/preferences')
|
||||||
|
|
||||||
|
describe('DetectTokensController', () => {
|
||||||
|
const sandbox = sinon.createSandbox()
|
||||||
|
let clock
|
||||||
|
let keyringMemStore
|
||||||
|
before(async () => {
|
||||||
|
keyringMemStore = new ObservableStore({ isUnlocked: false})
|
||||||
|
})
|
||||||
|
after(() => {
|
||||||
|
sandbox.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should poll on correct interval', async () => {
|
||||||
|
const stub = sinon.stub(global, 'setInterval')
|
||||||
|
new DetectTokensController({ interval: 1337 }) // eslint-disable-line no-new
|
||||||
|
assert.strictEqual(stub.getCall(0).args[1], 1337)
|
||||||
|
stub.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be called on every polling period', async () => {
|
||||||
|
clock = sandbox.useFakeTimers()
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('mainnet')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.isUnlocked = true
|
||||||
|
|
||||||
|
var stub = sandbox.stub(controller, 'detectNewTokens')
|
||||||
|
|
||||||
|
clock.tick(1)
|
||||||
|
sandbox.assert.notCalled(stub)
|
||||||
|
clock.tick(180000)
|
||||||
|
sandbox.assert.called(stub)
|
||||||
|
clock.tick(180000)
|
||||||
|
sandbox.assert.calledTwice(stub)
|
||||||
|
clock.tick(180000)
|
||||||
|
sandbox.assert.calledThrice(stub)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not check tokens while in test network', async () => {
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('rinkeby')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.isUnlocked = true
|
||||||
|
|
||||||
|
var stub = sandbox.stub(controller, 'detectTokenBalance')
|
||||||
|
.withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4').returns(true)
|
||||||
|
.withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388').returns(true)
|
||||||
|
|
||||||
|
await controller.detectNewTokens()
|
||||||
|
sandbox.assert.notCalled(stub)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should only check and add tokens while in main network', async () => {
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('mainnet')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.isUnlocked = true
|
||||||
|
|
||||||
|
sandbox.stub(controller, 'detectTokenBalance')
|
||||||
|
.withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4')
|
||||||
|
.returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8))
|
||||||
|
.withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388')
|
||||||
|
.returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18))
|
||||||
|
|
||||||
|
await controller.detectNewTokens()
|
||||||
|
assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'},
|
||||||
|
{address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not detect same token while in main network', async () => {
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('mainnet')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.isUnlocked = true
|
||||||
|
|
||||||
|
sandbox.stub(controller, 'detectTokenBalance')
|
||||||
|
.withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4')
|
||||||
|
.returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8))
|
||||||
|
.withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388')
|
||||||
|
.returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18))
|
||||||
|
|
||||||
|
await controller.detectNewTokens()
|
||||||
|
assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'},
|
||||||
|
{address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger detect new tokens when change address', async () => {
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('mainnet')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.isUnlocked = true
|
||||||
|
var stub = sandbox.stub(controller, 'detectNewTokens')
|
||||||
|
await preferences.setSelectedAddress('0xbc86727e770de68b1060c91f6bb6945c73e10388')
|
||||||
|
sandbox.assert.called(stub)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should trigger detect new tokens when submit password', async () => {
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('mainnet')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.selectedAddress = '0x0'
|
||||||
|
var stub = sandbox.stub(controller, 'detectNewTokens')
|
||||||
|
await controller._keyringMemStore.updateState({ isUnlocked: true })
|
||||||
|
sandbox.assert.called(stub)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not trigger detect new tokens when not open or not unlocked', async () => {
|
||||||
|
const network = new NetworkController()
|
||||||
|
network.setProviderType('mainnet')
|
||||||
|
const preferences = new PreferencesController()
|
||||||
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
|
controller.isOpen = true
|
||||||
|
controller.isUnlocked = false
|
||||||
|
var stub = sandbox.stub(controller, 'detectTokenBalance')
|
||||||
|
clock.tick(180000)
|
||||||
|
sandbox.assert.notCalled(stub)
|
||||||
|
controller.isOpen = false
|
||||||
|
controller.isUnlocked = true
|
||||||
|
clock.tick(180000)
|
||||||
|
sandbox.assert.notCalled(stub)
|
||||||
|
})
|
||||||
|
})
|
@ -222,6 +222,129 @@ describe('MetaMaskController', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('connectHardware', function () {
|
||||||
|
|
||||||
|
it('should throw if it receives an unknown device name', async function () {
|
||||||
|
try {
|
||||||
|
await metamaskController.connectHardware('Some random device name', 0)
|
||||||
|
} catch (e) {
|
||||||
|
assert.equal(e, 'Error: MetamaskController:connectHardware - Unknown device')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should add the Trezor Hardware keyring', async function () {
|
||||||
|
sinon.spy(metamaskController.keyringController, 'addNewKeyring')
|
||||||
|
await metamaskController.connectHardware('trezor', 0).catch((e) => null)
|
||||||
|
const keyrings = await metamaskController.keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)
|
||||||
|
assert.equal(metamaskController.keyringController.addNewKeyring.getCall(0).args, 'Trezor Hardware')
|
||||||
|
assert.equal(keyrings.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('checkHardwareStatus', function () {
|
||||||
|
it('should throw if it receives an unknown device name', async function () {
|
||||||
|
try {
|
||||||
|
await metamaskController.checkHardwareStatus('Some random device name')
|
||||||
|
} catch (e) {
|
||||||
|
assert.equal(e, 'Error: MetamaskController:checkHardwareStatus - Unknown device')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be locked by default', async function () {
|
||||||
|
await metamaskController.connectHardware('trezor', 0).catch((e) => null)
|
||||||
|
const status = await metamaskController.checkHardwareStatus('trezor')
|
||||||
|
assert.equal(status, false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('forgetDevice', function () {
|
||||||
|
it('should throw if it receives an unknown device name', async function () {
|
||||||
|
try {
|
||||||
|
await metamaskController.forgetDevice('Some random device name')
|
||||||
|
} catch (e) {
|
||||||
|
assert.equal(e, 'Error: MetamaskController:forgetDevice - Unknown device')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should wipe all the keyring info', async function () {
|
||||||
|
await metamaskController.connectHardware('trezor', 0).catch((e) => null)
|
||||||
|
await metamaskController.forgetDevice('trezor')
|
||||||
|
const keyrings = await metamaskController.keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.deepEqual(keyrings[0].accounts, [])
|
||||||
|
assert.deepEqual(keyrings[0].page, 0)
|
||||||
|
assert.deepEqual(keyrings[0].isUnlocked(), false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('unlockTrezorAccount', function () {
|
||||||
|
let accountToUnlock
|
||||||
|
let windowOpenStub
|
||||||
|
let addNewAccountStub
|
||||||
|
let getAccountsStub
|
||||||
|
beforeEach(async function () {
|
||||||
|
accountToUnlock = 10
|
||||||
|
windowOpenStub = sinon.stub(window, 'open')
|
||||||
|
windowOpenStub.returns(noop)
|
||||||
|
|
||||||
|
addNewAccountStub = sinon.stub(metamaskController.keyringController, 'addNewAccount')
|
||||||
|
addNewAccountStub.returns({})
|
||||||
|
|
||||||
|
getAccountsStub = sinon.stub(metamaskController.keyringController, 'getAccounts')
|
||||||
|
// Need to return different address to mock the behavior of
|
||||||
|
// adding a new account from the keyring
|
||||||
|
getAccountsStub.onCall(0).returns(Promise.resolve(['0x1']))
|
||||||
|
getAccountsStub.onCall(1).returns(Promise.resolve(['0x2']))
|
||||||
|
getAccountsStub.onCall(2).returns(Promise.resolve(['0x3']))
|
||||||
|
getAccountsStub.onCall(3).returns(Promise.resolve(['0x4']))
|
||||||
|
sinon.spy(metamaskController.preferencesController, 'setAddresses')
|
||||||
|
sinon.spy(metamaskController.preferencesController, 'setSelectedAddress')
|
||||||
|
sinon.spy(metamaskController.preferencesController, 'setAccountLabel')
|
||||||
|
await metamaskController.connectHardware('trezor', 0).catch((e) => null)
|
||||||
|
await metamaskController.unlockTrezorAccount(accountToUnlock).catch((e) => null)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
metamaskController.keyringController.addNewAccount.restore()
|
||||||
|
window.open.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should set accountToUnlock in the keyring', async function () {
|
||||||
|
const keyrings = await metamaskController.keyringController.getKeyringsByType(
|
||||||
|
'Trezor Hardware'
|
||||||
|
)
|
||||||
|
assert.equal(keyrings[0].unlockedAccount, accountToUnlock)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
it('should call keyringController.addNewAccount', async function () {
|
||||||
|
assert(metamaskController.keyringController.addNewAccount.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call keyringController.getAccounts ', async function () {
|
||||||
|
assert(metamaskController.keyringController.getAccounts.called)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call preferencesController.setAddresses', async function () {
|
||||||
|
assert(metamaskController.preferencesController.setAddresses.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call preferencesController.setSelectedAddress', async function () {
|
||||||
|
assert(metamaskController.preferencesController.setSelectedAddress.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call preferencesController.setAccountLabel', async function () {
|
||||||
|
assert(metamaskController.preferencesController.setAccountLabel.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
describe('#setCustomRpc', function () {
|
describe('#setCustomRpc', function () {
|
||||||
const customRPC = 'https://custom.rpc/'
|
const customRPC = 'https://custom.rpc/'
|
||||||
let rpcTarget
|
let rpcTarget
|
||||||
@ -362,6 +485,39 @@ describe('MetaMaskController', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('#removeAccount', function () {
|
||||||
|
let ret
|
||||||
|
const addressToRemove = '0x1'
|
||||||
|
|
||||||
|
beforeEach(async function () {
|
||||||
|
sinon.stub(metamaskController.preferencesController, 'removeAddress')
|
||||||
|
sinon.stub(metamaskController.accountTracker, 'removeAccount')
|
||||||
|
sinon.stub(metamaskController.keyringController, 'removeAccount')
|
||||||
|
|
||||||
|
ret = await metamaskController.removeAccount(addressToRemove)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
metamaskController.keyringController.removeAccount.restore()
|
||||||
|
metamaskController.accountTracker.removeAccount.restore()
|
||||||
|
metamaskController.preferencesController.removeAddress.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call preferencesController.removeAddress', async function () {
|
||||||
|
assert(metamaskController.preferencesController.removeAddress.calledWith(addressToRemove))
|
||||||
|
})
|
||||||
|
it('should call accountTracker.removeAccount', async function () {
|
||||||
|
assert(metamaskController.accountTracker.removeAccount.calledWith(addressToRemove))
|
||||||
|
})
|
||||||
|
it('should call keyringController.removeAccount', async function () {
|
||||||
|
assert(metamaskController.keyringController.removeAccount.calledWith(addressToRemove))
|
||||||
|
})
|
||||||
|
it('should return address', async function () {
|
||||||
|
assert.equal(ret, '0x1')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('#clearSeedWordCache', function () {
|
describe('#clearSeedWordCache', function () {
|
||||||
|
|
||||||
it('should have set seed words', function () {
|
it('should have set seed words', function () {
|
||||||
|
@ -52,6 +52,31 @@ describe('preferences controller', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('removeAddress', function () {
|
||||||
|
it('should remove an address from state', function () {
|
||||||
|
preferencesController.setAddresses([
|
||||||
|
'0xda22le',
|
||||||
|
'0x7e57e2',
|
||||||
|
])
|
||||||
|
|
||||||
|
preferencesController.removeAddress('0xda22le')
|
||||||
|
|
||||||
|
assert.equal(preferencesController.store.getState().identities['0xda22le'], undefined)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should switch accounts if the selected address is removed', function () {
|
||||||
|
preferencesController.setAddresses([
|
||||||
|
'0xda22le',
|
||||||
|
'0x7e57e2',
|
||||||
|
])
|
||||||
|
|
||||||
|
preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
preferencesController.removeAddress('0x7e57e2')
|
||||||
|
|
||||||
|
assert.equal(preferencesController.getSelectedAddress(), '0xda22le')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('setAccountLabel', function () {
|
describe('setAccountLabel', function () {
|
||||||
it('should update a label for the given account', function () {
|
it('should update a label for the given account', function () {
|
||||||
preferencesController.setAddresses([
|
preferencesController.setAddresses([
|
||||||
|
@ -10,6 +10,8 @@ const {
|
|||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const { fetchLocale } = require('../i18n-helper')
|
const { fetchLocale } = require('../i18n-helper')
|
||||||
const log = require('loglevel')
|
const log = require('loglevel')
|
||||||
|
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../app/scripts/lib/enums')
|
||||||
|
const { hasUnconfirmedTransactions } = require('./helpers/confirm-transaction/util')
|
||||||
|
|
||||||
var actions = {
|
var actions = {
|
||||||
_setBackgroundConnection: _setBackgroundConnection,
|
_setBackgroundConnection: _setBackgroundConnection,
|
||||||
@ -26,6 +28,11 @@ var actions = {
|
|||||||
SIDEBAR_CLOSE: 'UI_SIDEBAR_CLOSE',
|
SIDEBAR_CLOSE: 'UI_SIDEBAR_CLOSE',
|
||||||
showSidebar: showSidebar,
|
showSidebar: showSidebar,
|
||||||
hideSidebar: hideSidebar,
|
hideSidebar: hideSidebar,
|
||||||
|
// sidebar state
|
||||||
|
ALERT_OPEN: 'UI_ALERT_OPEN',
|
||||||
|
ALERT_CLOSE: 'UI_ALERT_CLOSE',
|
||||||
|
showAlert: showAlert,
|
||||||
|
hideAlert: hideAlert,
|
||||||
// network dropdown open
|
// network dropdown open
|
||||||
NETWORK_DROPDOWN_OPEN: 'UI_NETWORK_DROPDOWN_OPEN',
|
NETWORK_DROPDOWN_OPEN: 'UI_NETWORK_DROPDOWN_OPEN',
|
||||||
NETWORK_DROPDOWN_CLOSE: 'UI_NETWORK_DROPDOWN_CLOSE',
|
NETWORK_DROPDOWN_CLOSE: 'UI_NETWORK_DROPDOWN_CLOSE',
|
||||||
@ -78,9 +85,14 @@ var actions = {
|
|||||||
addNewKeyring,
|
addNewKeyring,
|
||||||
importNewAccount,
|
importNewAccount,
|
||||||
addNewAccount,
|
addNewAccount,
|
||||||
|
connectHardware,
|
||||||
|
checkHardwareStatus,
|
||||||
|
forgetDevice,
|
||||||
|
unlockTrezorAccount,
|
||||||
NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN',
|
NEW_ACCOUNT_SCREEN: 'NEW_ACCOUNT_SCREEN',
|
||||||
navigateToNewAccountScreen,
|
navigateToNewAccountScreen,
|
||||||
resetAccount,
|
resetAccount,
|
||||||
|
removeAccount,
|
||||||
showNewVaultSeed: showNewVaultSeed,
|
showNewVaultSeed: showNewVaultSeed,
|
||||||
showInfoPage: showInfoPage,
|
showInfoPage: showInfoPage,
|
||||||
CLOSE_WELCOME_SCREEN: 'CLOSE_WELCOME_SCREEN',
|
CLOSE_WELCOME_SCREEN: 'CLOSE_WELCOME_SCREEN',
|
||||||
@ -535,6 +547,26 @@ function resetAccount () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeAccount (address) {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.removeAccount(address, (err, account) => {
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
if (err) {
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info('Account removed: ' + account)
|
||||||
|
dispatch(actions.showAccountsPage())
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function addNewKeyring (type, opts) {
|
function addNewKeyring (type, opts) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
@ -601,6 +633,88 @@ function addNewAccount () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkHardwareStatus (deviceName) {
|
||||||
|
log.debug(`background.checkHardwareStatus`, deviceName)
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.checkHardwareStatus(deviceName, (err, unlocked) => {
|
||||||
|
if (err) {
|
||||||
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
forceUpdateMetamaskState(dispatch)
|
||||||
|
return resolve(unlocked)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function forgetDevice (deviceName) {
|
||||||
|
log.debug(`background.forgetDevice`, deviceName)
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.forgetDevice(deviceName, (err, response) => {
|
||||||
|
if (err) {
|
||||||
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
forceUpdateMetamaskState(dispatch)
|
||||||
|
return resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectHardware (deviceName, page) {
|
||||||
|
log.debug(`background.connectHardware`, deviceName, page)
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.connectHardware(deviceName, page, (err, accounts) => {
|
||||||
|
if (err) {
|
||||||
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
forceUpdateMetamaskState(dispatch)
|
||||||
|
return resolve(accounts)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unlockTrezorAccount (index) {
|
||||||
|
log.debug(`background.unlockTrezorAccount`, index)
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
background.unlockTrezorAccount(index, (err, accounts) => {
|
||||||
|
if (err) {
|
||||||
|
log.error(err)
|
||||||
|
dispatch(actions.displayWarning(err.message))
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
return resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showInfoPage () {
|
function showInfoPage () {
|
||||||
return {
|
return {
|
||||||
type: actions.SHOW_INFO_PAGE,
|
type: actions.SHOW_INFO_PAGE,
|
||||||
@ -631,7 +745,7 @@ function setCurrentCurrency (currencyCode) {
|
|||||||
|
|
||||||
function signMsg (msgData) {
|
function signMsg (msgData) {
|
||||||
log.debug('action - signMsg')
|
log.debug('action - signMsg')
|
||||||
return (dispatch) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -648,6 +762,12 @@ function signMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.metamaskId))
|
dispatch(actions.completedTx(msgData.metamaskId))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(msgData)
|
return resolve(msgData)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -656,7 +776,7 @@ function signMsg (msgData) {
|
|||||||
|
|
||||||
function signPersonalMsg (msgData) {
|
function signPersonalMsg (msgData) {
|
||||||
log.debug('action - signPersonalMsg')
|
log.debug('action - signPersonalMsg')
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -673,6 +793,12 @@ function signPersonalMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.metamaskId))
|
dispatch(actions.completedTx(msgData.metamaskId))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(msgData)
|
return resolve(msgData)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -681,7 +807,7 @@ function signPersonalMsg (msgData) {
|
|||||||
|
|
||||||
function signTypedMsg (msgData) {
|
function signTypedMsg (msgData) {
|
||||||
log.debug('action - signTypedMsg')
|
log.debug('action - signTypedMsg')
|
||||||
return (dispatch) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -698,6 +824,12 @@ function signTypedMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.metamaskId))
|
dispatch(actions.completedTx(msgData.metamaskId))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(msgData)
|
return resolve(msgData)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -891,7 +1023,7 @@ function clearSend () {
|
|||||||
|
|
||||||
function sendTx (txData) {
|
function sendTx (txData) {
|
||||||
log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`)
|
log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`)
|
||||||
return (dispatch) => {
|
return (dispatch, getState) => {
|
||||||
log.debug(`actions calling background.approveTransaction`)
|
log.debug(`actions calling background.approveTransaction`)
|
||||||
background.approveTransaction(txData.id, (err) => {
|
background.approveTransaction(txData.id, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -899,6 +1031,11 @@ function sendTx (txData) {
|
|||||||
return log.error(err.message)
|
return log.error(err.message)
|
||||||
}
|
}
|
||||||
dispatch(actions.completedTx(txData.id))
|
dispatch(actions.completedTx(txData.id))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,7 +1084,7 @@ function updateTransaction (txData) {
|
|||||||
|
|
||||||
function updateAndApproveTx (txData) {
|
function updateAndApproveTx (txData) {
|
||||||
log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData))
|
log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData))
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
log.debug(`actions calling background.updateAndApproveTx`)
|
log.debug(`actions calling background.updateAndApproveTx`)
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
@ -972,6 +1109,12 @@ function updateAndApproveTx (txData) {
|
|||||||
dispatch(actions.clearSend())
|
dispatch(actions.clearSend())
|
||||||
dispatch(actions.completedTx(txData.id))
|
dispatch(actions.completedTx(txData.id))
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return txData
|
return txData
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1000,7 +1143,7 @@ function txError (err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelMsg (msgData) {
|
function cancelMsg (msgData) {
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -1014,6 +1157,12 @@ function cancelMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(msgData.id))
|
dispatch(actions.completedTx(msgData.id))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(msgData)
|
return resolve(msgData)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1021,7 +1170,7 @@ function cancelMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelPersonalMsg (msgData) {
|
function cancelPersonalMsg (msgData) {
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -1035,6 +1184,12 @@ function cancelPersonalMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(id))
|
dispatch(actions.completedTx(id))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(msgData)
|
return resolve(msgData)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1042,7 +1197,7 @@ function cancelPersonalMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelTypedMsg (msgData) {
|
function cancelTypedMsg (msgData) {
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -1056,6 +1211,12 @@ function cancelTypedMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(actions.completedTx(id))
|
dispatch(actions.completedTx(id))
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return resolve(msgData)
|
return resolve(msgData)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1063,7 +1224,7 @@ function cancelTypedMsg (msgData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelTx (txData) {
|
function cancelTx (txData) {
|
||||||
return dispatch => {
|
return (dispatch, getState) => {
|
||||||
log.debug(`background.cancelTransaction`)
|
log.debug(`background.cancelTransaction`)
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
|
|
||||||
@ -1082,6 +1243,12 @@ function cancelTx (txData) {
|
|||||||
dispatch(actions.clearSend())
|
dispatch(actions.clearSend())
|
||||||
dispatch(actions.completedTx(txData.id))
|
dispatch(actions.completedTx(txData.id))
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
|
||||||
|
if (global.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION &&
|
||||||
|
!hasUnconfirmedTransactions(getState())) {
|
||||||
|
return global.platform.closeCurrentWindow()
|
||||||
|
}
|
||||||
|
|
||||||
return txData
|
return txData
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1626,6 +1793,19 @@ function hideSidebar () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showAlert (msg) {
|
||||||
|
return {
|
||||||
|
type: actions.ALERT_OPEN,
|
||||||
|
value: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideAlert () {
|
||||||
|
return {
|
||||||
|
type: actions.ALERT_CLOSE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function showLoadingIndication (message) {
|
function showLoadingIndication (message) {
|
||||||
return {
|
return {
|
||||||
|
@ -36,6 +36,8 @@ const AccountMenu = require('./components/account-menu')
|
|||||||
|
|
||||||
// Global Modals
|
// Global Modals
|
||||||
const Modal = require('./components/modals/index').Modal
|
const Modal = require('./components/modals/index').Modal
|
||||||
|
// Global Alert
|
||||||
|
const Alert = require('./components/alert')
|
||||||
|
|
||||||
const AppHeader = require('./components/app-header')
|
const AppHeader = require('./components/app-header')
|
||||||
|
|
||||||
@ -93,6 +95,7 @@ class App extends Component {
|
|||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
isLoading,
|
isLoading,
|
||||||
|
alertMessage,
|
||||||
loadingMessage,
|
loadingMessage,
|
||||||
network,
|
network,
|
||||||
isMouseUser,
|
isMouseUser,
|
||||||
@ -126,6 +129,9 @@ class App extends Component {
|
|||||||
// global modal
|
// global modal
|
||||||
h(Modal, {}, []),
|
h(Modal, {}, []),
|
||||||
|
|
||||||
|
// global alert
|
||||||
|
h(Alert, {visible: this.props.alertOpen, msg: alertMessage}),
|
||||||
|
|
||||||
h(AppHeader),
|
h(AppHeader),
|
||||||
|
|
||||||
// sidebar
|
// sidebar
|
||||||
@ -149,14 +155,6 @@ class App extends Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderGlobalModal () {
|
|
||||||
return h(Modal, {
|
|
||||||
ref: 'modalRef',
|
|
||||||
}, [
|
|
||||||
// h(BuyOptions, {}, []),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSidebar () {
|
renderSidebar () {
|
||||||
return h('div', [
|
return h('div', [
|
||||||
h('style', `
|
h('style', `
|
||||||
@ -265,11 +263,13 @@ App.propTypes = {
|
|||||||
setCurrentCurrencyToUSD: PropTypes.func,
|
setCurrentCurrencyToUSD: PropTypes.func,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
loadingMessage: PropTypes.string,
|
loadingMessage: PropTypes.string,
|
||||||
|
alertMessage: PropTypes.string,
|
||||||
network: PropTypes.string,
|
network: PropTypes.string,
|
||||||
provider: PropTypes.object,
|
provider: PropTypes.object,
|
||||||
frequentRpcList: PropTypes.array,
|
frequentRpcList: PropTypes.array,
|
||||||
currentView: PropTypes.object,
|
currentView: PropTypes.object,
|
||||||
sidebarOpen: PropTypes.bool,
|
sidebarOpen: PropTypes.bool,
|
||||||
|
alertOpen: PropTypes.bool,
|
||||||
hideSidebar: PropTypes.func,
|
hideSidebar: PropTypes.func,
|
||||||
isMascara: PropTypes.bool,
|
isMascara: PropTypes.bool,
|
||||||
isOnboarding: PropTypes.bool,
|
isOnboarding: PropTypes.bool,
|
||||||
@ -305,6 +305,8 @@ function mapStateToProps (state) {
|
|||||||
const {
|
const {
|
||||||
networkDropdownOpen,
|
networkDropdownOpen,
|
||||||
sidebarOpen,
|
sidebarOpen,
|
||||||
|
alertOpen,
|
||||||
|
alertMessage,
|
||||||
isLoading,
|
isLoading,
|
||||||
loadingMessage,
|
loadingMessage,
|
||||||
} = appState
|
} = appState
|
||||||
@ -330,6 +332,8 @@ function mapStateToProps (state) {
|
|||||||
// state from plugin
|
// state from plugin
|
||||||
networkDropdownOpen,
|
networkDropdownOpen,
|
||||||
sidebarOpen,
|
sidebarOpen,
|
||||||
|
alertOpen,
|
||||||
|
alertMessage,
|
||||||
isLoading,
|
isLoading,
|
||||||
loadingMessage,
|
loadingMessage,
|
||||||
noActiveNotices,
|
noActiveNotices,
|
||||||
|
@ -9,11 +9,17 @@ const actions = require('../../actions')
|
|||||||
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
|
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
|
||||||
const Identicon = require('../identicon')
|
const Identicon = require('../identicon')
|
||||||
const { formatBalance } = require('../../util')
|
const { formatBalance } = require('../../util')
|
||||||
|
const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
|
||||||
|
const { getEnvironmentType } = require('../../../../app/scripts/lib/util')
|
||||||
|
const Tooltip = require('../tooltip')
|
||||||
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
SETTINGS_ROUTE,
|
SETTINGS_ROUTE,
|
||||||
INFO_ROUTE,
|
INFO_ROUTE,
|
||||||
NEW_ACCOUNT_ROUTE,
|
NEW_ACCOUNT_ROUTE,
|
||||||
IMPORT_ACCOUNT_ROUTE,
|
IMPORT_ACCOUNT_ROUTE,
|
||||||
|
CONNECT_HARDWARE_ROUTE,
|
||||||
DEFAULT_ROUTE,
|
DEFAULT_ROUTE,
|
||||||
} = require('../../routes')
|
} = require('../../routes')
|
||||||
|
|
||||||
@ -63,6 +69,9 @@ function mapDispatchToProps (dispatch) {
|
|||||||
dispatch(actions.hideSidebar())
|
dispatch(actions.hideSidebar())
|
||||||
dispatch(actions.toggleAccountMenu())
|
dispatch(actions.toggleAccountMenu())
|
||||||
},
|
},
|
||||||
|
showRemoveAccountConfirmationModal: (identity) => {
|
||||||
|
return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity }))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +115,18 @@ AccountMenu.prototype.render = function () {
|
|||||||
icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }),
|
icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }),
|
||||||
text: this.context.t('importAccount'),
|
text: this.context.t('importAccount'),
|
||||||
}),
|
}),
|
||||||
|
h(Item, {
|
||||||
|
onClick: () => {
|
||||||
|
toggleAccountMenu()
|
||||||
|
if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
|
||||||
|
global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE)
|
||||||
|
} else {
|
||||||
|
history.push(CONNECT_HARDWARE_ROUTE)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: h('img.account-menu__item-icon', { src: 'images/connect-icon.svg' }),
|
||||||
|
text: this.context.t('connectHardwareWallet'),
|
||||||
|
}),
|
||||||
h(Divider),
|
h(Divider),
|
||||||
h(Item, {
|
h(Item, {
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@ -136,7 +157,8 @@ AccountMenu.prototype.renderAccounts = function () {
|
|||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), [])
|
const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), [])
|
||||||
return accountOrder.map((address) => {
|
return accountOrder.filter(address => !!identities[address]).map((address) => {
|
||||||
|
|
||||||
const identity = identities[address]
|
const identity = identities[address]
|
||||||
const isSelected = identity.address === selectedAddress
|
const isSelected = identity.address === selectedAddress
|
||||||
|
|
||||||
@ -170,16 +192,53 @@ AccountMenu.prototype.renderAccounts = function () {
|
|||||||
h('div.account-menu__balance', formattedBalance),
|
h('div.account-menu__balance', formattedBalance),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
this.indicateIfLoose(keyring),
|
this.renderKeyringType(keyring),
|
||||||
|
this.renderRemoveAccount(keyring, identity),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountMenu.prototype.indicateIfLoose = function (keyring) {
|
AccountMenu.prototype.renderRemoveAccount = function (keyring, identity) {
|
||||||
|
// Any account that's not from the HD wallet Keyring can be removed
|
||||||
|
const type = keyring.type
|
||||||
|
const isRemovable = type !== 'HD Key Tree'
|
||||||
|
if (isRemovable) {
|
||||||
|
return h(Tooltip, {
|
||||||
|
title: this.context.t('removeAccount'),
|
||||||
|
position: 'bottom',
|
||||||
|
}, [
|
||||||
|
h('a.remove-account-icon', {
|
||||||
|
onClick: (e) => this.removeAccount(e, identity),
|
||||||
|
}, ''),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountMenu.prototype.removeAccount = function (e, identity) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const { showRemoveAccountConfirmationModal } = this.props
|
||||||
|
showRemoveAccountConfirmationModal(identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountMenu.prototype.renderKeyringType = function (keyring) {
|
||||||
try { // Sometimes keyrings aren't loaded yet:
|
try { // Sometimes keyrings aren't loaded yet:
|
||||||
const type = keyring.type
|
const type = keyring.type
|
||||||
const isLoose = type !== 'HD Key Tree'
|
let label
|
||||||
return isLoose ? h('.keyring-label.allcaps', this.context.t('imported')) : null
|
switch (type) {
|
||||||
|
case 'Trezor Hardware':
|
||||||
|
label = this.context.t('hardware')
|
||||||
|
break
|
||||||
|
case 'Simple Key Pair':
|
||||||
|
label = this.context.t('imported')
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
label = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return label !== '' ? h('.keyring-label.allcaps', label) : null
|
||||||
|
|
||||||
} catch (e) { return }
|
} catch (e) { return }
|
||||||
}
|
}
|
||||||
|
62
ui/app/components/alert/index.js
Normal file
62
ui/app/components/alert/index.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
|
||||||
|
class Alert extends Component {
|
||||||
|
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
visble: false,
|
||||||
|
msg: false,
|
||||||
|
className: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps (nextProps) {
|
||||||
|
if (!this.props.visible && nextProps.visible) {
|
||||||
|
this.animateIn(nextProps)
|
||||||
|
} else if (this.props.visible && !nextProps.visible) {
|
||||||
|
this.animateOut(nextProps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animateIn (props) {
|
||||||
|
this.setState({
|
||||||
|
msg: props.msg,
|
||||||
|
visible: true,
|
||||||
|
className: '.visible',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
animateOut (props) {
|
||||||
|
this.setState({
|
||||||
|
msg: null,
|
||||||
|
className: '.hidden',
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
this.setState({visible: false})
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
if (this.state.visible) {
|
||||||
|
return (
|
||||||
|
h(`div.global-alert${this.state.className}`, {},
|
||||||
|
h('a.msg', {}, this.state.msg)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Alert.propTypes = {
|
||||||
|
visible: PropTypes.bool.isRequired,
|
||||||
|
msg: PropTypes.string,
|
||||||
|
}
|
||||||
|
module.exports = Alert
|
||||||
|
|
@ -0,0 +1,93 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import Button from '../../button'
|
||||||
|
import { addressSummary } from '../../../util'
|
||||||
|
import Identicon from '../../identicon'
|
||||||
|
import genAccountLink from '../../../../lib/account-link'
|
||||||
|
|
||||||
|
class ConfirmRemoveAccount extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
hideModal: PropTypes.func.isRequired,
|
||||||
|
removeAccount: PropTypes.func.isRequired,
|
||||||
|
identity: PropTypes.object.isRequired,
|
||||||
|
network: PropTypes.string.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRemove () {
|
||||||
|
this.props.removeAccount(this.props.identity.address)
|
||||||
|
.then(() => this.props.hideModal())
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSelectedAccount () {
|
||||||
|
const { identity } = this.props
|
||||||
|
return (
|
||||||
|
<div className="modal-container__account">
|
||||||
|
<div className="modal-container__account__identicon">
|
||||||
|
<Identicon
|
||||||
|
address={identity.address}
|
||||||
|
diameter={32}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="modal-container__account__name">
|
||||||
|
<span className="modal-container__account__label">Name</span>
|
||||||
|
<span className="account_value">{identity.name}</span>
|
||||||
|
</div>
|
||||||
|
<div className="modal-container__account__address">
|
||||||
|
<span className="modal-container__account__label">Public Address</span>
|
||||||
|
<span className="account_value">{ addressSummary(identity.address, 4, 4) }</span>
|
||||||
|
</div>
|
||||||
|
<div className="modal-container__account__link">
|
||||||
|
<a
|
||||||
|
className=""
|
||||||
|
href={genAccountLink(identity.address, this.props.network)}
|
||||||
|
target={'_blank'}
|
||||||
|
title={this.context.t('etherscanView')}
|
||||||
|
>
|
||||||
|
<img src="images/popout.svg" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { t } = this.context
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="modal-container">
|
||||||
|
<div className="modal-container__content">
|
||||||
|
<div className="modal-container__title">
|
||||||
|
{ `${t('removeAccount')}` }?
|
||||||
|
</div>
|
||||||
|
{ this.renderSelectedAccount() }
|
||||||
|
<div className="modal-container__description">
|
||||||
|
{ t('removeAccountDescription') }
|
||||||
|
<a className="modal-container__link" rel="noopener noreferrer" target="_blank" href="https://consensys.zendesk.com/hc/en-us/articles/360004180111-What-are-imported-accounts-New-UI-">{ t('learnMore') }</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-container__footer">
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
className="modal-container__footer-button"
|
||||||
|
onClick={() => this.props.hideModal()}
|
||||||
|
>
|
||||||
|
{ t('nevermind') }
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="secondary"
|
||||||
|
className="modal-container__footer-button"
|
||||||
|
onClick={() => this.handleRemove()}
|
||||||
|
>
|
||||||
|
{ t('remove') }
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConfirmRemoveAccount
|
@ -0,0 +1,20 @@
|
|||||||
|
import { connect } from 'react-redux'
|
||||||
|
import ConfirmRemoveAccount from './confirm-remove-account.component'
|
||||||
|
|
||||||
|
const { hideModal, removeAccount } = require('../../../actions')
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
identity: state.appState.modal.modalState.props.identity,
|
||||||
|
network: state.metamask.network,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
hideModal: () => dispatch(hideModal()),
|
||||||
|
removeAccount: (address) => dispatch(removeAccount(address)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ConfirmRemoveAccount)
|
2
ui/app/components/modals/confirm-remove-account/index.js
Normal file
2
ui/app/components/modals/confirm-remove-account/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import ConfirmRemoveAccount from './confirm-remove-account.container'
|
||||||
|
module.exports = ConfirmRemoveAccount
|
@ -20,6 +20,58 @@
|
|||||||
font-size: .875rem;
|
font-size: .875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__account {
|
||||||
|
border: 1px solid #b7b7b7;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__identicon {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name,
|
||||||
|
&__address {
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
width: 100px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 11px;
|
||||||
|
display: block;
|
||||||
|
color: #9b9b9b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
margin-top: 14px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 575px) {
|
||||||
|
&__name {
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
color: #2f9ae0;
|
||||||
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -20,6 +20,7 @@ const HideTokenConfirmationModal = require('./hide-token-confirmation-modal')
|
|||||||
const CustomizeGasModal = require('../customize-gas-modal')
|
const CustomizeGasModal = require('../customize-gas-modal')
|
||||||
const NotifcationModal = require('./notification-modal')
|
const NotifcationModal = require('./notification-modal')
|
||||||
const ConfirmResetAccount = require('./confirm-reset-account')
|
const ConfirmResetAccount = require('./confirm-reset-account')
|
||||||
|
const ConfirmRemoveAccount = require('./confirm-remove-account')
|
||||||
const TransactionConfirmed = require('./transaction-confirmed')
|
const TransactionConfirmed = require('./transaction-confirmed')
|
||||||
const WelcomeBeta = require('./welcome-beta')
|
const WelcomeBeta = require('./welcome-beta')
|
||||||
const Notification = require('./notification')
|
const Notification = require('./notification')
|
||||||
@ -243,6 +244,19 @@ const MODALS = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
CONFIRM_REMOVE_ACCOUNT: {
|
||||||
|
contents: h(ConfirmRemoveAccount),
|
||||||
|
mobileModalStyle: {
|
||||||
|
...modalContainerMobileStyle,
|
||||||
|
},
|
||||||
|
laptopModalStyle: {
|
||||||
|
...modalContainerLaptopStyle,
|
||||||
|
},
|
||||||
|
contentStyle: {
|
||||||
|
borderRadius: '8px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
NEW_ACCOUNT: {
|
NEW_ACCOUNT: {
|
||||||
contents: [
|
contents: [
|
||||||
h(NewAccountModal, {}, []),
|
h(NewAccountModal, {}, []),
|
||||||
|
@ -2,6 +2,7 @@ import { connect } from 'react-redux'
|
|||||||
import { compose } from 'recompose'
|
import { compose } from 'recompose'
|
||||||
import { withRouter } from 'react-router-dom'
|
import { withRouter } from 'react-router-dom'
|
||||||
import R from 'ramda'
|
import R from 'ramda'
|
||||||
|
import contractMap from 'eth-contract-metadata'
|
||||||
import ConfirmTransactionBase from './confirm-transaction-base.component'
|
import ConfirmTransactionBase from './confirm-transaction-base.component'
|
||||||
import {
|
import {
|
||||||
clearConfirmTransaction,
|
clearConfirmTransaction,
|
||||||
@ -16,6 +17,14 @@ import { getHexGasTotal } from '../../../helpers/confirm-transaction/util'
|
|||||||
import { isBalanceSufficient } from '../../send/send.utils'
|
import { isBalanceSufficient } from '../../send/send.utils'
|
||||||
import { conversionGreaterThan } from '../../../conversion-util'
|
import { conversionGreaterThan } from '../../../conversion-util'
|
||||||
import { MIN_GAS_LIMIT_DEC } from '../../send/send.constants'
|
import { MIN_GAS_LIMIT_DEC } from '../../send/send.constants'
|
||||||
|
import { addressSlicer } from '../../../util'
|
||||||
|
|
||||||
|
const casedContractMap = Object.keys(contractMap).reduce((acc, base) => {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[base.toLowerCase()]: contractMap[base],
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
|
|
||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const { toAddress: propsToAddress } = props
|
const { toAddress: propsToAddress } = props
|
||||||
@ -48,7 +57,10 @@ const mapStateToProps = (state, props) => {
|
|||||||
const { balance } = accounts[selectedAddress]
|
const { balance } = accounts[selectedAddress]
|
||||||
const { name: fromName } = identities[selectedAddress]
|
const { name: fromName } = identities[selectedAddress]
|
||||||
const toAddress = propsToAddress || txParamsToAddress
|
const toAddress = propsToAddress || txParamsToAddress
|
||||||
const toName = identities[toAddress] && identities[toAddress].name
|
const toName = identities[toAddress]
|
||||||
|
? identities[toAddress].name
|
||||||
|
: casedContractMap[toAddress] ? casedContractMap[toAddress].name : addressSlicer(toAddress)
|
||||||
|
|
||||||
const isTxReprice = Boolean(lastGasPrice)
|
const isTxReprice = Boolean(lastGasPrice)
|
||||||
|
|
||||||
const transaction = R.find(({ id }) => id === transactionId)(selectedAddressTxList)
|
const transaction = R.find(({ id }) => id === transactionId)(selectedAddressTxList)
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const genAccountLink = require('../../../../../lib/account-link.js')
|
||||||
|
|
||||||
|
class AccountList extends Component {
|
||||||
|
constructor (props, context) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHeader () {
|
||||||
|
return (
|
||||||
|
h('div.hw-connect', [
|
||||||
|
h('h3.hw-connect__title', {}, this.context.t('selectAnAccount')),
|
||||||
|
h('p.hw-connect__msg', {}, this.context.t('selectAnAccountHelp')),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderAccounts () {
|
||||||
|
return h('div.hw-account-list', [
|
||||||
|
this.props.accounts.map((a, i) => {
|
||||||
|
|
||||||
|
return h('div.hw-account-list__item', { key: a.address }, [
|
||||||
|
h('div.hw-account-list__item__radio', [
|
||||||
|
h('input', {
|
||||||
|
type: 'radio',
|
||||||
|
name: 'selectedAccount',
|
||||||
|
id: `address-${i}`,
|
||||||
|
value: a.index,
|
||||||
|
onChange: (e) => this.props.onAccountChange(e.target.value),
|
||||||
|
checked: this.props.selectedAccount === a.index.toString(),
|
||||||
|
}),
|
||||||
|
h(
|
||||||
|
'label.hw-account-list__item__label',
|
||||||
|
{
|
||||||
|
htmlFor: `address-${i}`,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('span.hw-account-list__item__index', a.index + 1),
|
||||||
|
`${a.address.slice(0, 4)}...${a.address.slice(-4)}`,
|
||||||
|
h('span.hw-account-list__item__balance', `${a.balance}`),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
h(
|
||||||
|
'a.hw-account-list__item__link',
|
||||||
|
{
|
||||||
|
href: genAccountLink(a.address, this.props.network),
|
||||||
|
target: '_blank',
|
||||||
|
title: this.context.t('etherscanView'),
|
||||||
|
},
|
||||||
|
h('img', { src: 'images/popout.svg' })
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPagination () {
|
||||||
|
return h('div.hw-list-pagination', [
|
||||||
|
h(
|
||||||
|
'button.hw-list-pagination__button',
|
||||||
|
{
|
||||||
|
onClick: () => this.props.getPage(-1),
|
||||||
|
},
|
||||||
|
`< ${this.context.t('prev')}`
|
||||||
|
),
|
||||||
|
|
||||||
|
h(
|
||||||
|
'button.hw-list-pagination__button',
|
||||||
|
{
|
||||||
|
onClick: () => this.props.getPage(1),
|
||||||
|
},
|
||||||
|
`${this.context.t('next')} >`
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
renderButtons () {
|
||||||
|
const disabled = this.props.selectedAccount === null
|
||||||
|
const buttonProps = {}
|
||||||
|
if (disabled) {
|
||||||
|
buttonProps.disabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return h('div.new-account-connect-form__buttons', {}, [
|
||||||
|
h(
|
||||||
|
'button.btn-default.btn--large.new-account-connect-form__button',
|
||||||
|
{
|
||||||
|
onClick: this.props.onCancel.bind(this),
|
||||||
|
},
|
||||||
|
[this.context.t('cancel')]
|
||||||
|
),
|
||||||
|
|
||||||
|
h(
|
||||||
|
`button.btn-primary.btn--large.new-account-connect-form__button.unlock ${disabled ? '.btn-primary--disabled' : ''}`,
|
||||||
|
{
|
||||||
|
onClick: this.props.onUnlockAccount.bind(this),
|
||||||
|
...buttonProps,
|
||||||
|
},
|
||||||
|
[this.context.t('unlock')]
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
renderForgetDevice () {
|
||||||
|
return h('div.hw-forget-device-container', {}, [
|
||||||
|
h('a', {
|
||||||
|
onClick: this.props.onForgetDevice.bind(this),
|
||||||
|
}, this.context.t('forgetDevice')),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return h('div.new-account-connect-form.account-list', {}, [
|
||||||
|
this.renderHeader(),
|
||||||
|
this.renderAccounts(),
|
||||||
|
this.renderPagination(),
|
||||||
|
this.renderButtons(),
|
||||||
|
this.renderForgetDevice(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AccountList.propTypes = {
|
||||||
|
accounts: PropTypes.array.isRequired,
|
||||||
|
onAccountChange: PropTypes.func.isRequired,
|
||||||
|
onForgetDevice: PropTypes.func.isRequired,
|
||||||
|
getPage: PropTypes.func.isRequired,
|
||||||
|
network: PropTypes.string,
|
||||||
|
selectedAccount: PropTypes.string,
|
||||||
|
history: PropTypes.object,
|
||||||
|
onUnlockAccount: PropTypes.func,
|
||||||
|
onCancel: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountList.contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AccountList
|
@ -0,0 +1,149 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
|
||||||
|
class ConnectScreen extends Component {
|
||||||
|
constructor (props, context) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUnsupportedBrowser () {
|
||||||
|
return (
|
||||||
|
h('div.new-account-connect-form.unsupported-browser', {}, [
|
||||||
|
h('div.hw-connect', [
|
||||||
|
h('h3.hw-connect__title', {}, this.context.t('browserNotSupported')),
|
||||||
|
h('p.hw-connect__msg', {}, this.context.t('chromeRequiredForTrezor')),
|
||||||
|
]),
|
||||||
|
h(
|
||||||
|
'button.btn-primary.btn--large',
|
||||||
|
{
|
||||||
|
onClick: () => global.platform.openWindow({
|
||||||
|
url: 'https://google.com/chrome',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
this.context.t('downloadGoogleChrome')
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHeader () {
|
||||||
|
return (
|
||||||
|
h('div.hw-connect__header', {}, [
|
||||||
|
h('h3.hw-connect__header__title', {}, this.context.t(`hardwareSupport`)),
|
||||||
|
h('p.hw-connect__header__msg', {}, this.context.t(`hardwareSupportMsg`)),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTrezorAffiliateLink () {
|
||||||
|
return h('div.hw-connect__get-trezor', {}, [
|
||||||
|
h('p.hw-connect__get-trezor__msg', {}, this.context.t(`dontHaveATrezorWallet`)),
|
||||||
|
h('a.hw-connect__get-trezor__link', {
|
||||||
|
href: 'https://shop.trezor.io/?a=metamask',
|
||||||
|
target: '_blank',
|
||||||
|
}, this.context.t('orderOneHere')),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
renderConnectToTrezorButton () {
|
||||||
|
return h(
|
||||||
|
'button.btn-primary.btn--large',
|
||||||
|
{ onClick: this.props.connectToTrezor.bind(this) },
|
||||||
|
this.props.btnText
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollToTutorial = (e) => {
|
||||||
|
if (this.referenceNode) this.referenceNode.scrollIntoView({behavior: 'smooth'})
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLearnMore () {
|
||||||
|
return (
|
||||||
|
h('p.hw-connect__learn-more', {
|
||||||
|
onClick: this.scrollToTutorial,
|
||||||
|
}, [
|
||||||
|
this.context.t('learnMore'),
|
||||||
|
h('img.hw-connect__learn-more__arrow', { src: 'images/caret-right.svg'}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTutorialSteps () {
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
asset: 'hardware-wallet-step-1',
|
||||||
|
dimensions: {width: '225px', height: '75px'},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
asset: 'hardware-wallet-step-2',
|
||||||
|
dimensions: {width: '300px', height: '100px'},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
asset: 'hardware-wallet-step-3',
|
||||||
|
dimensions: {width: '120px', height: '90px'},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return h('.hw-tutorial', {
|
||||||
|
ref: node => { this.referenceNode = node },
|
||||||
|
},
|
||||||
|
steps.map((step, i) => (
|
||||||
|
h('div.hw-connect', {}, [
|
||||||
|
h('h3.hw-connect__title', {}, this.context.t(`step${i + 1}HardwareWallet`)),
|
||||||
|
h('p.hw-connect__msg', {}, this.context.t(`step${i + 1}HardwareWalletMsg`)),
|
||||||
|
h('img.hw-connect__step-asset', { src: `images/${step.asset}.svg`, ...step.dimensions }),
|
||||||
|
])
|
||||||
|
))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFooter () {
|
||||||
|
return (
|
||||||
|
h('div.hw-connect__footer', {}, [
|
||||||
|
h('h3.hw-connect__footer__title', {}, this.context.t(`readyToConnect`)),
|
||||||
|
this.renderConnectToTrezorButton(),
|
||||||
|
h('p.hw-connect__footer__msg', {}, [
|
||||||
|
this.context.t(`havingTroubleConnecting`),
|
||||||
|
h('a.hw-connect__footer__link', {
|
||||||
|
href: 'https://support.metamask.io/',
|
||||||
|
target: '_blank',
|
||||||
|
}, this.context.t('getHelp')),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderConnectScreen () {
|
||||||
|
return (
|
||||||
|
h('div.new-account-connect-form', {}, [
|
||||||
|
this.renderHeader(),
|
||||||
|
this.renderTrezorAffiliateLink(),
|
||||||
|
this.renderConnectToTrezorButton(),
|
||||||
|
this.renderLearnMore(),
|
||||||
|
this.renderTutorialSteps(),
|
||||||
|
this.renderFooter(),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
if (this.props.browserSupported) {
|
||||||
|
return this.renderConnectScreen()
|
||||||
|
}
|
||||||
|
return this.renderUnsupportedBrowser()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectScreen.propTypes = {
|
||||||
|
connectToTrezor: PropTypes.func.isRequired,
|
||||||
|
btnText: PropTypes.string.isRequired,
|
||||||
|
browserSupported: PropTypes.bool.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectScreen.contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ConnectScreen
|
||||||
|
|
241
ui/app/components/pages/create-account/connect-hardware/index.js
Normal file
241
ui/app/components/pages/create-account/connect-hardware/index.js
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
const { Component } = require('react')
|
||||||
|
const PropTypes = require('prop-types')
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const actions = require('../../../../actions')
|
||||||
|
const ConnectScreen = require('./connect-screen')
|
||||||
|
const AccountList = require('./account-list')
|
||||||
|
const { DEFAULT_ROUTE } = require('../../../../routes')
|
||||||
|
const { formatBalance } = require('../../../../util')
|
||||||
|
|
||||||
|
class ConnectHardwareForm extends Component {
|
||||||
|
constructor (props, context) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
error: null,
|
||||||
|
btnText: context.t('connectToTrezor'),
|
||||||
|
selectedAccount: null,
|
||||||
|
accounts: [],
|
||||||
|
browserSupported: true,
|
||||||
|
unlocked: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps (nextProps) {
|
||||||
|
const { accounts } = nextProps
|
||||||
|
const newAccounts = this.state.accounts.map(a => {
|
||||||
|
const normalizedAddress = a.address.toLowerCase()
|
||||||
|
const balanceValue = accounts[normalizedAddress] && accounts[normalizedAddress].balance || null
|
||||||
|
a.balance = balanceValue ? formatBalance(balanceValue, 6) : '...'
|
||||||
|
return a
|
||||||
|
})
|
||||||
|
this.setState({accounts: newAccounts})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.checkIfUnlocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkIfUnlocked () {
|
||||||
|
const unlocked = await this.props.checkHardwareStatus('trezor')
|
||||||
|
if (unlocked) {
|
||||||
|
this.setState({unlocked: true})
|
||||||
|
this.getPage(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connectToTrezor = () => {
|
||||||
|
if (this.state.accounts.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
this.setState({ btnText: this.context.t('connecting')})
|
||||||
|
this.getPage(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
onAccountChange = (account) => {
|
||||||
|
this.setState({selectedAccount: account.toString(), error: null})
|
||||||
|
}
|
||||||
|
|
||||||
|
showTemporaryAlert () {
|
||||||
|
this.props.showAlert(this.context.t('hardwareWalletConnected'))
|
||||||
|
// Autohide the alert after 5 seconds
|
||||||
|
setTimeout(_ => {
|
||||||
|
this.props.hideAlert()
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
|
getPage = (page) => {
|
||||||
|
this.props
|
||||||
|
.connectHardware('trezor', page)
|
||||||
|
.then(accounts => {
|
||||||
|
if (accounts.length) {
|
||||||
|
|
||||||
|
// If we just loaded the accounts for the first time
|
||||||
|
// (device previously locked) show the global alert
|
||||||
|
if (this.state.accounts.length === 0 && !this.state.unlocked) {
|
||||||
|
this.showTemporaryAlert()
|
||||||
|
}
|
||||||
|
|
||||||
|
const newState = { unlocked: true }
|
||||||
|
// Default to the first account
|
||||||
|
if (this.state.selectedAccount === null) {
|
||||||
|
accounts.forEach((a, i) => {
|
||||||
|
if (a.address.toLowerCase() === this.props.address) {
|
||||||
|
newState.selectedAccount = a.index.toString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// If the page doesn't contain the selected account, let's deselect it
|
||||||
|
} else if (!accounts.filter(a => a.index.toString() === this.state.selectedAccount).length) {
|
||||||
|
newState.selectedAccount = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Map accounts with balances
|
||||||
|
newState.accounts = accounts.map(account => {
|
||||||
|
const normalizedAddress = account.address.toLowerCase()
|
||||||
|
const balanceValue = this.props.accounts[normalizedAddress] && this.props.accounts[normalizedAddress].balance || null
|
||||||
|
account.balance = balanceValue ? formatBalance(balanceValue, 6) : '...'
|
||||||
|
return account
|
||||||
|
})
|
||||||
|
|
||||||
|
this.setState(newState)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
if (e === 'Window blocked') {
|
||||||
|
this.setState({ browserSupported: false })
|
||||||
|
}
|
||||||
|
this.setState({ btnText: this.context.t('connectToTrezor') })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onForgetDevice = () => {
|
||||||
|
this.props.forgetDevice('trezor')
|
||||||
|
.then(_ => {
|
||||||
|
this.setState({
|
||||||
|
error: null,
|
||||||
|
btnText: this.context.t('connectToTrezor'),
|
||||||
|
selectedAccount: null,
|
||||||
|
accounts: [],
|
||||||
|
unlocked: false,
|
||||||
|
})
|
||||||
|
}).catch(e => {
|
||||||
|
this.setState({ error: e.toString() })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnlockAccount = () => {
|
||||||
|
|
||||||
|
if (this.state.selectedAccount === null) {
|
||||||
|
this.setState({ error: this.context.t('accountSelectionRequired') })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.unlockTrezorAccount(this.state.selectedAccount)
|
||||||
|
.then(_ => {
|
||||||
|
this.props.history.push(DEFAULT_ROUTE)
|
||||||
|
}).catch(e => {
|
||||||
|
this.setState({ error: e.toString() })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel = () => {
|
||||||
|
this.props.history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError () {
|
||||||
|
return this.state.error
|
||||||
|
? h('span.error', { style: { marginBottom: 40 } }, this.state.error)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContent () {
|
||||||
|
if (!this.state.accounts.length) {
|
||||||
|
return h(ConnectScreen, {
|
||||||
|
connectToTrezor: this.connectToTrezor,
|
||||||
|
btnText: this.state.btnText,
|
||||||
|
browserSupported: this.state.browserSupported,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return h(AccountList, {
|
||||||
|
accounts: this.state.accounts,
|
||||||
|
selectedAccount: this.state.selectedAccount,
|
||||||
|
onAccountChange: this.onAccountChange,
|
||||||
|
network: this.props.network,
|
||||||
|
getPage: this.getPage,
|
||||||
|
history: this.props.history,
|
||||||
|
onUnlockAccount: this.onUnlockAccount,
|
||||||
|
onForgetDevice: this.onForgetDevice,
|
||||||
|
onCancel: this.onCancel,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return h('div', [
|
||||||
|
this.renderError(),
|
||||||
|
this.renderContent(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectHardwareForm.propTypes = {
|
||||||
|
hideModal: PropTypes.func,
|
||||||
|
showImportPage: PropTypes.func,
|
||||||
|
showConnectPage: PropTypes.func,
|
||||||
|
connectHardware: PropTypes.func,
|
||||||
|
checkHardwareStatus: PropTypes.func,
|
||||||
|
forgetDevice: PropTypes.func,
|
||||||
|
showAlert: PropTypes.func,
|
||||||
|
hideAlert: PropTypes.func,
|
||||||
|
unlockTrezorAccount: PropTypes.func,
|
||||||
|
numberOfExistingAccounts: PropTypes.number,
|
||||||
|
history: PropTypes.object,
|
||||||
|
t: PropTypes.func,
|
||||||
|
network: PropTypes.string,
|
||||||
|
accounts: PropTypes.object,
|
||||||
|
address: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const {
|
||||||
|
metamask: { network, selectedAddress, identities = {}, accounts = [] },
|
||||||
|
} = state
|
||||||
|
const numberOfExistingAccounts = Object.keys(identities).length
|
||||||
|
|
||||||
|
return {
|
||||||
|
network,
|
||||||
|
accounts,
|
||||||
|
address: selectedAddress,
|
||||||
|
numberOfExistingAccounts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
connectHardware: (deviceName, page) => {
|
||||||
|
return dispatch(actions.connectHardware(deviceName, page))
|
||||||
|
},
|
||||||
|
checkHardwareStatus: (deviceName) => {
|
||||||
|
return dispatch(actions.checkHardwareStatus(deviceName))
|
||||||
|
},
|
||||||
|
forgetDevice: (deviceName) => {
|
||||||
|
return dispatch(actions.forgetDevice(deviceName))
|
||||||
|
},
|
||||||
|
unlockTrezorAccount: index => {
|
||||||
|
return dispatch(actions.unlockTrezorAccount(index))
|
||||||
|
},
|
||||||
|
showImportPage: () => dispatch(actions.showImportPage()),
|
||||||
|
showConnectPage: () => dispatch(actions.showConnectPage()),
|
||||||
|
showAlert: (msg) => dispatch(actions.showAlert(msg)),
|
||||||
|
hideAlert: () => dispatch(actions.hideAlert()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectHardwareForm.contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps, mapDispatchToProps)(
|
||||||
|
ConnectHardwareForm
|
||||||
|
)
|
@ -8,7 +8,12 @@ const { getCurrentViewContext } = require('../../../selectors')
|
|||||||
const classnames = require('classnames')
|
const classnames = require('classnames')
|
||||||
const NewAccountCreateForm = require('./new-account')
|
const NewAccountCreateForm = require('./new-account')
|
||||||
const NewAccountImportForm = require('./import-account')
|
const NewAccountImportForm = require('./import-account')
|
||||||
const { NEW_ACCOUNT_ROUTE, IMPORT_ACCOUNT_ROUTE } = require('../../../routes')
|
const ConnectHardwareForm = require('./connect-hardware')
|
||||||
|
const {
|
||||||
|
NEW_ACCOUNT_ROUTE,
|
||||||
|
IMPORT_ACCOUNT_ROUTE,
|
||||||
|
CONNECT_HARDWARE_ROUTE,
|
||||||
|
} = require('../../../routes')
|
||||||
|
|
||||||
class CreateAccountPage extends Component {
|
class CreateAccountPage extends Component {
|
||||||
renderTabs () {
|
renderTabs () {
|
||||||
@ -36,6 +41,19 @@ class CreateAccountPage extends Component {
|
|||||||
}, [
|
}, [
|
||||||
this.context.t('import'),
|
this.context.t('import'),
|
||||||
]),
|
]),
|
||||||
|
h(
|
||||||
|
'div.new-account__tabs__tab',
|
||||||
|
{
|
||||||
|
className: classnames('new-account__tabs__tab', {
|
||||||
|
'new-account__tabs__selected': matchPath(location.pathname, {
|
||||||
|
path: CONNECT_HARDWARE_ROUTE,
|
||||||
|
exact: true,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
onClick: () => history.push(CONNECT_HARDWARE_ROUTE),
|
||||||
|
},
|
||||||
|
this.context.t('connect')
|
||||||
|
),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +75,11 @@ class CreateAccountPage extends Component {
|
|||||||
path: IMPORT_ACCOUNT_ROUTE,
|
path: IMPORT_ACCOUNT_ROUTE,
|
||||||
component: NewAccountImportForm,
|
component: NewAccountImportForm,
|
||||||
}),
|
}),
|
||||||
|
h(Route, {
|
||||||
|
exact: true,
|
||||||
|
path: CONNECT_HARDWARE_ROUTE,
|
||||||
|
component: ConnectHardwareForm,
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
|
@ -62,6 +62,7 @@ class NewAccountCreateForm extends Component {
|
|||||||
NewAccountCreateForm.propTypes = {
|
NewAccountCreateForm.propTypes = {
|
||||||
hideModal: PropTypes.func,
|
hideModal: PropTypes.func,
|
||||||
showImportPage: PropTypes.func,
|
showImportPage: PropTypes.func,
|
||||||
|
showConnectPage: PropTypes.func,
|
||||||
createAccount: PropTypes.func,
|
createAccount: PropTypes.func,
|
||||||
numberOfExistingAccounts: PropTypes.number,
|
numberOfExistingAccounts: PropTypes.number,
|
||||||
history: PropTypes.object,
|
history: PropTypes.object,
|
||||||
@ -92,6 +93,7 @@ const mapDispatchToProps = dispatch => {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
showImportPage: () => dispatch(actions.showImportPage()),
|
showImportPage: () => dispatch(actions.showImportPage()),
|
||||||
|
showConnectPage: () => dispatch(actions.showConnectPage()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,19 +27,17 @@ const {
|
|||||||
NOTICE_ROUTE,
|
NOTICE_ROUTE,
|
||||||
} = require('../../routes')
|
} = require('../../routes')
|
||||||
|
|
||||||
|
const { unconfirmedTransactionsCountSelector } = require('../../selectors/confirm-transaction')
|
||||||
|
|
||||||
class Home extends Component {
|
class Home extends Component {
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const {
|
const {
|
||||||
history,
|
history,
|
||||||
unapprovedTxs = {},
|
unconfirmedTransactionsCount = 0,
|
||||||
unapprovedMsgCount = 0,
|
|
||||||
unapprovedPersonalMsgCount = 0,
|
|
||||||
unapprovedTypedMessagesCount = 0,
|
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
// unapprovedTxs and unapproved messages
|
// unapprovedTxs and unapproved messages
|
||||||
if (Object.keys(unapprovedTxs).length ||
|
if (unconfirmedTransactionsCount > 0) {
|
||||||
unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) {
|
|
||||||
history.push(CONFIRM_TRANSACTION_ROUTE)
|
history.push(CONFIRM_TRANSACTION_ROUTE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,6 +165,7 @@ Home.propTypes = {
|
|||||||
isPopup: PropTypes.bool,
|
isPopup: PropTypes.bool,
|
||||||
isMouseUser: PropTypes.bool,
|
isMouseUser: PropTypes.bool,
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
|
unconfirmedTransactionsCount: PropTypes.number,
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
@ -230,6 +229,7 @@ function mapStateToProps (state) {
|
|||||||
|
|
||||||
// state needed to get account dropdown temporarily rendering from app bar
|
// state needed to get account dropdown temporarily rendering from app bar
|
||||||
selected,
|
selected,
|
||||||
|
unconfirmedTransactionsCount: unconfirmedTransactionsCountSelector(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import copyToClipboard from 'copy-to-clipboard'
|
import copyToClipboard from 'copy-to-clipboard'
|
||||||
|
import { addressSlicer } from '../../util'
|
||||||
|
|
||||||
const Tooltip = require('../tooltip-v2.js')
|
const Tooltip = require('../tooltip-v2.js')
|
||||||
|
|
||||||
const addressStripper = (address = '') => {
|
|
||||||
if (address.length < 11) {
|
|
||||||
return address
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${address.slice(0, 6)}...${address.slice(-4)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
class SelectedAccount extends Component {
|
class SelectedAccount extends Component {
|
||||||
state = {
|
state = {
|
||||||
copied: false,
|
copied: false,
|
||||||
@ -48,7 +41,7 @@ class SelectedAccount extends Component {
|
|||||||
{ selectedIdentity.name }
|
{ selectedIdentity.name }
|
||||||
</div>
|
</div>
|
||||||
<div className="selected-account__address">
|
<div className="selected-account__address">
|
||||||
{ addressStripper(selectedAddress) }
|
{ addressSlicer(selectedAddress) }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
background-color: $dusty-gray;
|
background-color: $dusty-gray;
|
||||||
color: $black;
|
color: $black;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
letter-spacing: .5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +85,23 @@
|
|||||||
@media screen and (max-width: 575px) {
|
@media screen and (max-width: 575px) {
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.remove-account-icon {
|
||||||
|
width: 15px;
|
||||||
|
margin-left: 10px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.remove-account-icon::after {
|
||||||
|
content: '\00D7';
|
||||||
|
font-size: 25px;
|
||||||
|
color: $white;
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__account-info {
|
&__account-info {
|
||||||
|
57
ui/app/css/itcss/components/alert.scss
Normal file
57
ui/app/css/itcss/components/alert.scss
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
.global-alert {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #33A4E7;
|
||||||
|
|
||||||
|
.msg {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-alert.hidden {
|
||||||
|
animation: alertHidden .5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-alert.visible {
|
||||||
|
animation: alert .5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation */
|
||||||
|
@keyframes alert {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
top: -50px;
|
||||||
|
padding: 0px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: 0;
|
||||||
|
padding: 8px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes alertHidden {
|
||||||
|
0% {
|
||||||
|
top: 0;
|
||||||
|
opacity: 1;
|
||||||
|
padding: 8px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
top: -50px;
|
||||||
|
padding: 0px;
|
||||||
|
line-height: 0px;
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
@import './modal.scss';
|
@import './modal.scss';
|
||||||
|
|
||||||
|
@import './alert.scss';
|
||||||
|
|
||||||
@import './newui-sections.scss';
|
@import './newui-sections.scss';
|
||||||
|
|
||||||
@import './account-dropdown.scss';
|
@import './account-dropdown.scss';
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
.new-account {
|
.new-account {
|
||||||
width: 376px;
|
width: 375px;
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
|
box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
|
||||||
z-index: 25;
|
z-index: 25;
|
||||||
padding-bottom: 31px;
|
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -28,7 +27,6 @@
|
|||||||
|
|
||||||
&__tab {
|
&__tab {
|
||||||
height: 54px;
|
height: 54px;
|
||||||
width: 75px;
|
|
||||||
padding: 15px 10px;
|
padding: 15px 10px;
|
||||||
color: $dusty-gray;
|
color: $dusty-gray;
|
||||||
font-family: Roboto;
|
font-family: Roboto;
|
||||||
@ -38,10 +36,6 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__tab:first-of-type {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__tab:hover {
|
&__tab:hover {
|
||||||
color: $black;
|
color: $black;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
@ -69,7 +63,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 30px;
|
padding: 0 30px 30px;
|
||||||
|
|
||||||
&__select-section {
|
&__select-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -158,11 +152,296 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hw-tutorial {
|
||||||
|
width: 375px;
|
||||||
|
border-top: 1px solid #D2D8DD;
|
||||||
|
border-bottom: 1px solid #D2D8DD;
|
||||||
|
overflow: visible;
|
||||||
|
display: block;
|
||||||
|
padding: 15px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-connect {
|
||||||
|
&__header {
|
||||||
|
&__title {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 22px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__msg {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #9b9b9b;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__learn-more {
|
||||||
|
margin-top: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #5B5D67;
|
||||||
|
line-height: 19px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&__arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
height: 30px;
|
||||||
|
margin: 0px auto 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
padding-top: 10px;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__msg {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #9b9b9b;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
color: #2f9ae0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__msg {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #9b9b9b;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 27px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
color: #2f9ae0;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__get-trezor {
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
padding-top: 20px;
|
||||||
|
|
||||||
|
&__msg {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #9b9b9b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
color: #2f9ae0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__step-asset {
|
||||||
|
margin: 0px auto 20px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-account-list {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-flow: column;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__title_wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin-bottom: 23px;
|
||||||
|
align-self: flex-start;
|
||||||
|
color: $scorpion;
|
||||||
|
font-family: Roboto;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 21px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__device {
|
||||||
|
margin-bottom: 23px;
|
||||||
|
align-self: flex-end;
|
||||||
|
color: $scorpion;
|
||||||
|
font-family: Roboto;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 21px;
|
||||||
|
font-weight: normal;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
font-size: 15px;
|
||||||
|
flex-direction: row;
|
||||||
|
display: flex;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item:nth-of-type(even) {
|
||||||
|
background-color: #fbfbfb;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item:nth-of-type(odd) {
|
||||||
|
background: rgba(0, 0, 0, 0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item__index {
|
||||||
|
display: flex;
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item__radio {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item__label {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item__balance {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item__link {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item__link img {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-list-pagination {
|
||||||
|
display: flex;
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
height: 19px;
|
||||||
|
display: flex;
|
||||||
|
color: #33a4e7;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 19px;
|
||||||
|
border: none;
|
||||||
|
min-width: 46px;
|
||||||
|
margin-right: 0px;
|
||||||
|
margin-left: 16px;
|
||||||
|
padding: 0px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-family: Roboto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-account-connect-form {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px 30px 0;
|
||||||
|
height: 710px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
&.unsupported-browser {
|
||||||
|
height: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.account-list {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__buttons {
|
||||||
|
margin-top: 39px;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
width: 150px;
|
||||||
|
min-width: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #259DE5;
|
||||||
|
color: #FFFFFF;
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 54px;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button.unlock {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button.btn-primary--disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hw-forget-device-container {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 22px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #2f9ae0;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.new-account-create-form {
|
.new-account-create-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 30px 30px 0;
|
padding: 30px;
|
||||||
|
|
||||||
&__input-label {
|
&__input-label {
|
||||||
color: $scorpion;
|
color: $scorpion;
|
||||||
|
@ -16,6 +16,8 @@ import {
|
|||||||
conversionGreaterThan,
|
conversionGreaterThan,
|
||||||
} from '../../conversion-util'
|
} from '../../conversion-util'
|
||||||
|
|
||||||
|
import { unconfirmedTransactionsCountSelector } from '../../selectors/confirm-transaction'
|
||||||
|
|
||||||
export function getTokenData (data = {}) {
|
export function getTokenData (data = {}) {
|
||||||
return abiDecoder.decodeMethod(data)
|
return abiDecoder.decodeMethod(data)
|
||||||
}
|
}
|
||||||
@ -131,3 +133,7 @@ export function convertTokenToFiat ({
|
|||||||
conversionRate: totalExchangeRate,
|
conversionRate: totalExchangeRate,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasUnconfirmedTransactions (state) {
|
||||||
|
return unconfirmedTransactionsCountSelector(state) > 0
|
||||||
|
}
|
||||||
|
@ -49,6 +49,8 @@ function reduceApp (state, action) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
sidebarOpen: false,
|
sidebarOpen: false,
|
||||||
|
alertOpen: false,
|
||||||
|
alertMessage: null,
|
||||||
networkDropdownOpen: false,
|
networkDropdownOpen: false,
|
||||||
currentView: seedWords ? seedConfView : defaultView,
|
currentView: seedWords ? seedConfView : defaultView,
|
||||||
accountDetail: {
|
accountDetail: {
|
||||||
@ -88,6 +90,19 @@ function reduceApp (state, action) {
|
|||||||
sidebarOpen: false,
|
sidebarOpen: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// sidebar methods
|
||||||
|
case actions.ALERT_OPEN:
|
||||||
|
return extend(appState, {
|
||||||
|
alertOpen: true,
|
||||||
|
alertMessage: action.value,
|
||||||
|
})
|
||||||
|
|
||||||
|
case actions.ALERT_CLOSE:
|
||||||
|
return extend(appState, {
|
||||||
|
alertOpen: false,
|
||||||
|
alertMessage: null,
|
||||||
|
})
|
||||||
|
|
||||||
// modal methods:
|
// modal methods:
|
||||||
case actions.MODAL_OPEN:
|
case actions.MODAL_OPEN:
|
||||||
const { name, ...modalProps } = action.payload
|
const { name, ...modalProps } = action.payload
|
||||||
|
@ -9,6 +9,7 @@ const ADD_TOKEN_ROUTE = '/add-token'
|
|||||||
const CONFIRM_ADD_TOKEN_ROUTE = '/confirm-add-token'
|
const CONFIRM_ADD_TOKEN_ROUTE = '/confirm-add-token'
|
||||||
const NEW_ACCOUNT_ROUTE = '/new-account'
|
const NEW_ACCOUNT_ROUTE = '/new-account'
|
||||||
const IMPORT_ACCOUNT_ROUTE = '/new-account/import'
|
const IMPORT_ACCOUNT_ROUTE = '/new-account/import'
|
||||||
|
const CONNECT_HARDWARE_ROUTE = '/new-account/connect'
|
||||||
const SEND_ROUTE = '/send'
|
const SEND_ROUTE = '/send'
|
||||||
const NOTICE_ROUTE = '/notice'
|
const NOTICE_ROUTE = '/notice'
|
||||||
const WELCOME_ROUTE = '/welcome'
|
const WELCOME_ROUTE = '/welcome'
|
||||||
@ -42,6 +43,7 @@ module.exports = {
|
|||||||
CONFIRM_ADD_TOKEN_ROUTE,
|
CONFIRM_ADD_TOKEN_ROUTE,
|
||||||
NEW_ACCOUNT_ROUTE,
|
NEW_ACCOUNT_ROUTE,
|
||||||
IMPORT_ACCOUNT_ROUTE,
|
IMPORT_ACCOUNT_ROUTE,
|
||||||
|
CONNECT_HARDWARE_ROUTE,
|
||||||
SEND_ROUTE,
|
SEND_ROUTE,
|
||||||
NOTICE_ROUTE,
|
NOTICE_ROUTE,
|
||||||
WELCOME_ROUTE,
|
WELCOME_ROUTE,
|
||||||
|
@ -62,6 +62,34 @@ export const unconfirmedTransactionsHashSelector = createSelector(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const unapprovedMsgCountSelector = state => state.metamask.unapprovedMsgCount
|
||||||
|
const unapprovedPersonalMsgCountSelector = state => state.metamask.unapprovedPersonalMsgCount
|
||||||
|
const unapprovedTypedMessagesCountSelector = state => state.metamask.unapprovedTypedMessagesCount
|
||||||
|
|
||||||
|
export const unconfirmedTransactionsCountSelector = createSelector(
|
||||||
|
unapprovedTxsSelector,
|
||||||
|
unapprovedMsgCountSelector,
|
||||||
|
unapprovedPersonalMsgCountSelector,
|
||||||
|
unapprovedTypedMessagesCountSelector,
|
||||||
|
networkSelector,
|
||||||
|
(
|
||||||
|
unapprovedTxs = {},
|
||||||
|
unapprovedMsgCount = 0,
|
||||||
|
unapprovedPersonalMsgCount = 0,
|
||||||
|
unapprovedTypedMessagesCount = 0,
|
||||||
|
network
|
||||||
|
) => {
|
||||||
|
const filteredUnapprovedTxIds = Object.keys(unapprovedTxs).filter(txId => {
|
||||||
|
const { metamaskNetworkId } = unapprovedTxs[txId]
|
||||||
|
return metamaskNetworkId === network
|
||||||
|
})
|
||||||
|
|
||||||
|
return filteredUnapprovedTxIds.length + unapprovedTypedMessagesCount + unapprovedMsgCount +
|
||||||
|
unapprovedPersonalMsgCount
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
export const currentCurrencySelector = state => state.metamask.currentCurrency
|
export const currentCurrencySelector = state => state.metamask.currentCurrency
|
||||||
export const conversionRateSelector = state => state.metamask.conversionRate
|
export const conversionRateSelector = state => state.metamask.conversionRate
|
||||||
|
|
||||||
@ -156,7 +184,6 @@ export const sendTokenTokenAmountAndToAddressSelector = createSelector(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
export const contractExchangeRateSelector = createSelector(
|
export const contractExchangeRateSelector = createSelector(
|
||||||
contractExchangeRatesSelector,
|
contractExchangeRatesSelector,
|
||||||
tokenAddressSelector,
|
tokenAddressSelector,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const log = require('loglevel')
|
const log = require('loglevel')
|
||||||
const util = require('./util')
|
const util = require('./util')
|
||||||
|
const BigNumber = require('bignumber.js')
|
||||||
|
|
||||||
function tokenInfoGetter () {
|
function tokenInfoGetter () {
|
||||||
const tokens = {}
|
const tokens = {}
|
||||||
@ -43,9 +44,7 @@ async function getSymbolAndDecimals (tokenAddress, existingTokens = []) {
|
|||||||
|
|
||||||
function calcTokenAmount (value, decimals) {
|
function calcTokenAmount (value, decimals) {
|
||||||
const multiplier = Math.pow(10, Number(decimals || 0))
|
const multiplier = Math.pow(10, Number(decimals || 0))
|
||||||
const amount = Number(value / multiplier)
|
return new BigNumber(value).div(multiplier).toNumber()
|
||||||
|
|
||||||
return amount
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ module.exports = {
|
|||||||
allNull,
|
allNull,
|
||||||
getTokenAddressFromTokenObject,
|
getTokenAddressFromTokenObject,
|
||||||
checksumAddress,
|
checksumAddress,
|
||||||
|
addressSlicer,
|
||||||
}
|
}
|
||||||
|
|
||||||
function valuesFor (obj) {
|
function valuesFor (obj) {
|
||||||
@ -303,3 +304,11 @@ function getTokenAddressFromTokenObject (token) {
|
|||||||
function checksumAddress (address) {
|
function checksumAddress (address) {
|
||||||
return address ? ethUtil.toChecksumAddress(address) : ''
|
return address ? ethUtil.toChecksumAddress(address) : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addressSlicer (address = '') {
|
||||||
|
if (address.length < 11) {
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${address.slice(0, 6)}...${address.slice(-4)}`
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user