diff --git a/.gitignore b/.gitignore
index 1806b1932..08a544449 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,9 @@ test/background.js
test/bundle.js
test/test-bundle.js
+#ignore css output and sourcemaps
+ui/app/css/output/
+
notes.txt
.coveralls.yml
diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 000000000..854829a54
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,10 @@
+app/
+development/
+dist/
+docs/
+fonts/
+images/
+mascara/
+node_modules/
+notices/
+test/
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 000000000..d080d68d9
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,50 @@
+{
+ "extends": "stylelint-config-standard",
+ "rules": {
+ "color-named": "never",
+ "font-family-name-quotes": "always-where-recommended",
+ "font-weight-notation": "numeric",
+ "function-url-quotes": "always",
+ "number-leading-zero": "never",
+ "value-no-vendor-prefix": true,
+ "value-list-comma-newline-before": "never-multi-line",
+ "custom-property-empty-line-before": "never",
+ "property-no-unknown": [
+ true,
+ {
+ "ignoreProperties": [
+ "composes",
+ "all",
+ "-webkit-appearance"
+ ]
+ }
+ ],
+ "declaration-block-semicolon-newline-after": "always",
+ "block-opening-brace-newline-after": "always",
+ "selector-attribute-quotes": "always",
+ "selector-max-specificity": "0,5,2",
+ "selector-pseudo-class-no-unknown": [
+ true,
+ {
+ "ignorePseudoClasses": ["local", "global"]
+ }
+ ],
+ "at-rule-empty-line-before": [
+ "always",
+ {
+ "ignore": [
+ "after-comment",
+ ]
+ }
+ ],
+ "indentation": [
+ 2,
+ {
+ "indentInsideParens": "once-at-root-twice-in-block"
+ }
+ ],
+ "max-nesting-depth": 3,
+ "no-duplicate-selectors": true,
+ "no-unknown-animations": true
+ }
+}
diff --git a/app/fonts/DIN Next/DIN Next W01 Bold.otf b/app/fonts/DIN Next/DIN Next W01 Bold.otf
new file mode 100644
index 000000000..2b78d1ff4
Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W01 Bold.otf differ
diff --git a/app/fonts/DIN Next/DIN Next W01 Regular.otf b/app/fonts/DIN Next/DIN Next W01 Regular.otf
new file mode 100644
index 000000000..09f6ee297
Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W01 Regular.otf differ
diff --git a/app/fonts/DIN Next/DIN Next W10 Black.otf b/app/fonts/DIN Next/DIN Next W10 Black.otf
new file mode 100644
index 000000000..08eb73373
Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Black.otf differ
diff --git a/app/fonts/DIN Next/DIN Next W10 Italic.otf b/app/fonts/DIN Next/DIN Next W10 Italic.otf
new file mode 100644
index 000000000..73f2b9e8c
Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Italic.otf differ
diff --git a/app/fonts/DIN Next/DIN Next W10 Light.otf b/app/fonts/DIN Next/DIN Next W10 Light.otf
new file mode 100644
index 000000000..700450e49
Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Light.otf differ
diff --git a/app/fonts/DIN Next/DIN Next W10 Medium.otf b/app/fonts/DIN Next/DIN Next W10 Medium.otf
new file mode 100644
index 000000000..b73f2e43f
Binary files /dev/null and b/app/fonts/DIN Next/DIN Next W10 Medium.otf differ
diff --git a/app/fonts/DIN_OT/DINOT-2.otf b/app/fonts/DIN_OT/DINOT-2.otf
new file mode 100644
index 000000000..4a5e13127
Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-2.otf differ
diff --git a/app/fonts/DIN_OT/DINOT-Bold 2.otf b/app/fonts/DIN_OT/DINOT-Bold 2.otf
new file mode 100644
index 000000000..6ed5b6c3d
Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-Bold 2.otf differ
diff --git a/app/fonts/DIN_OT/DINOT-BoldItalic.otf b/app/fonts/DIN_OT/DINOT-BoldItalic.otf
new file mode 100644
index 000000000..148c90588
Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-BoldItalic.otf differ
diff --git a/app/fonts/DIN_OT/DINOT-Italic 2.otf b/app/fonts/DIN_OT/DINOT-Italic 2.otf
new file mode 100644
index 000000000..e365e77ab
Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-Italic 2.otf differ
diff --git a/app/fonts/DIN_OT/DINOT-Medium 2.otf b/app/fonts/DIN_OT/DINOT-Medium 2.otf
new file mode 100644
index 000000000..a87a2df37
Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-Medium 2.otf differ
diff --git a/app/fonts/DIN_OT/DINOT-MediumItalic 2.otf b/app/fonts/DIN_OT/DINOT-MediumItalic 2.otf
new file mode 100644
index 000000000..14eddfc76
Binary files /dev/null and b/app/fonts/DIN_OT/DINOT-MediumItalic 2.otf differ
diff --git a/app/fonts/Lato/Lato-Black.ttf b/app/fonts/Lato/Lato-Black.ttf
new file mode 100755
index 000000000..6848db0d1
Binary files /dev/null and b/app/fonts/Lato/Lato-Black.ttf differ
diff --git a/app/fonts/Lato/Lato-BlackItalic.ttf b/app/fonts/Lato/Lato-BlackItalic.ttf
new file mode 100755
index 000000000..5decf1297
Binary files /dev/null and b/app/fonts/Lato/Lato-BlackItalic.ttf differ
diff --git a/app/fonts/Lato/Lato-Bold.ttf b/app/fonts/Lato/Lato-Bold.ttf
new file mode 100755
index 000000000..74343694e
Binary files /dev/null and b/app/fonts/Lato/Lato-Bold.ttf differ
diff --git a/app/fonts/Lato/Lato-BoldItalic.ttf b/app/fonts/Lato/Lato-BoldItalic.ttf
new file mode 100755
index 000000000..684aacf5b
Binary files /dev/null and b/app/fonts/Lato/Lato-BoldItalic.ttf differ
diff --git a/app/fonts/Lato/Lato-Hairline.ttf b/app/fonts/Lato/Lato-Hairline.ttf
new file mode 100755
index 000000000..288be2955
Binary files /dev/null and b/app/fonts/Lato/Lato-Hairline.ttf differ
diff --git a/app/fonts/Lato/Lato-HairlineItalic.ttf b/app/fonts/Lato/Lato-HairlineItalic.ttf
new file mode 100755
index 000000000..c2bfd3353
Binary files /dev/null and b/app/fonts/Lato/Lato-HairlineItalic.ttf differ
diff --git a/app/fonts/Lato/Lato-Italic.ttf b/app/fonts/Lato/Lato-Italic.ttf
new file mode 100755
index 000000000..3d3b7a298
Binary files /dev/null and b/app/fonts/Lato/Lato-Italic.ttf differ
diff --git a/app/fonts/Lato/Lato-Light.ttf b/app/fonts/Lato/Lato-Light.ttf
new file mode 100755
index 000000000..a958067a8
Binary files /dev/null and b/app/fonts/Lato/Lato-Light.ttf differ
diff --git a/app/fonts/Lato/Lato-LightItalic.ttf b/app/fonts/Lato/Lato-LightItalic.ttf
new file mode 100755
index 000000000..5e45ad9a6
Binary files /dev/null and b/app/fonts/Lato/Lato-LightItalic.ttf differ
diff --git a/app/fonts/Lato/Lato-Regular.ttf b/app/fonts/Lato/Lato-Regular.ttf
new file mode 100755
index 000000000..04ea8efb1
Binary files /dev/null and b/app/fonts/Lato/Lato-Regular.ttf differ
diff --git a/app/fonts/Lato/OFL.txt b/app/fonts/Lato/OFL.txt
new file mode 100755
index 000000000..dfca0da4b
--- /dev/null
+++ b/app/fonts/Lato/OFL.txt
@@ -0,0 +1,93 @@
+Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato"
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/app/fonts/Roboto/Roboto-Black.ttf b/app/fonts/Roboto/Roboto-Black.ttf
new file mode 100644
index 000000000..71f01ac2b
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Black.ttf differ
diff --git a/app/fonts/Roboto/Roboto-BlackItalic.ttf b/app/fonts/Roboto/Roboto-BlackItalic.ttf
new file mode 100644
index 000000000..ec309c785
Binary files /dev/null and b/app/fonts/Roboto/Roboto-BlackItalic.ttf differ
diff --git a/app/fonts/Roboto/Roboto-Bold.ttf b/app/fonts/Roboto/Roboto-Bold.ttf
new file mode 100644
index 000000000..aaf374d2c
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Bold.ttf differ
diff --git a/app/fonts/Roboto/Roboto-BoldItalic.ttf b/app/fonts/Roboto/Roboto-BoldItalic.ttf
new file mode 100644
index 000000000..dcd0f8007
Binary files /dev/null and b/app/fonts/Roboto/Roboto-BoldItalic.ttf differ
diff --git a/app/fonts/Roboto/Roboto-Italic.ttf b/app/fonts/Roboto/Roboto-Italic.ttf
new file mode 100644
index 000000000..f382c6874
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Italic.ttf differ
diff --git a/app/fonts/Roboto/Roboto-Light.ttf b/app/fonts/Roboto/Roboto-Light.ttf
new file mode 100644
index 000000000..664e1b2f9
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Light.ttf differ
diff --git a/app/fonts/Roboto/Roboto-LightItalic.ttf b/app/fonts/Roboto/Roboto-LightItalic.ttf
new file mode 100644
index 000000000..b8f529637
Binary files /dev/null and b/app/fonts/Roboto/Roboto-LightItalic.ttf differ
diff --git a/app/fonts/Roboto/Roboto-Medium.ttf b/app/fonts/Roboto/Roboto-Medium.ttf
new file mode 100644
index 000000000..aa00de0ef
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Medium.ttf differ
diff --git a/app/fonts/Roboto/Roboto-MediumItalic.ttf b/app/fonts/Roboto/Roboto-MediumItalic.ttf
new file mode 100644
index 000000000..67e25f019
Binary files /dev/null and b/app/fonts/Roboto/Roboto-MediumItalic.ttf differ
diff --git a/app/fonts/Roboto/Roboto-Regular.ttf b/app/fonts/Roboto/Roboto-Regular.ttf
new file mode 100644
index 000000000..3e6e2e761
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Regular.ttf differ
diff --git a/app/fonts/Roboto/Roboto-Thin.ttf b/app/fonts/Roboto/Roboto-Thin.ttf
new file mode 100644
index 000000000..d262d1446
Binary files /dev/null and b/app/fonts/Roboto/Roboto-Thin.ttf differ
diff --git a/app/fonts/Roboto/Roboto-ThinItalic.ttf b/app/fonts/Roboto/Roboto-ThinItalic.ttf
new file mode 100644
index 000000000..63e9f9718
Binary files /dev/null and b/app/fonts/Roboto/Roboto-ThinItalic.ttf differ
diff --git a/app/fonts/Roboto/RobotoCondensed-Bold.ttf b/app/fonts/Roboto/RobotoCondensed-Bold.ttf
new file mode 100644
index 000000000..48dd63534
Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Bold.ttf differ
diff --git a/app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf b/app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf
new file mode 100644
index 000000000..ad728646a
Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-BoldItalic.ttf differ
diff --git a/app/fonts/Roboto/RobotoCondensed-Italic.ttf b/app/fonts/Roboto/RobotoCondensed-Italic.ttf
new file mode 100644
index 000000000..a232513d5
Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Italic.ttf differ
diff --git a/app/fonts/Roboto/RobotoCondensed-Light.ttf b/app/fonts/Roboto/RobotoCondensed-Light.ttf
new file mode 100644
index 000000000..a6e368d40
Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Light.ttf differ
diff --git a/app/fonts/Roboto/RobotoCondensed-LightItalic.ttf b/app/fonts/Roboto/RobotoCondensed-LightItalic.ttf
new file mode 100644
index 000000000..5b2b6ae08
Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-LightItalic.ttf differ
diff --git a/app/fonts/Roboto/RobotoCondensed-Regular.ttf b/app/fonts/Roboto/RobotoCondensed-Regular.ttf
new file mode 100644
index 000000000..65bf32a19
Binary files /dev/null and b/app/fonts/Roboto/RobotoCondensed-Regular.ttf differ
diff --git a/app/images/.DS_Store b/app/images/.DS_Store
deleted file mode 100644
index d28ef2089..000000000
Binary files a/app/images/.DS_Store and /dev/null differ
diff --git a/app/images/eth_logo.svg b/app/images/eth_logo.svg
new file mode 100644
index 000000000..894bd70dd
--- /dev/null
+++ b/app/images/eth_logo.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/images/import-account.svg b/app/images/import-account.svg
new file mode 100644
index 000000000..d6a81b70c
--- /dev/null
+++ b/app/images/import-account.svg
@@ -0,0 +1,18 @@
+
+
+
+ import-account
+ Created with Sketch.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/images/mm-bolt.svg b/app/images/mm-bolt.svg
new file mode 100644
index 000000000..bbf0abcc7
--- /dev/null
+++ b/app/images/mm-bolt.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/app/images/mm-info-icon.svg b/app/images/mm-info-icon.svg
new file mode 100644
index 000000000..825f0f200
--- /dev/null
+++ b/app/images/mm-info-icon.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/app/images/plus-btn-white.svg b/app/images/plus-btn-white.svg
new file mode 100644
index 000000000..2672d39dd
--- /dev/null
+++ b/app/images/plus-btn-white.svg
@@ -0,0 +1,17 @@
+
+
+
+ plus-btn-white
+ Created with Sketch.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/images/settings.svg b/app/images/settings.svg
index fe61320a5..cf9b298dd 100644
--- a/app/images/settings.svg
+++ b/app/images/settings.svg
@@ -1,24 +1,22 @@
-
-
-
-
-
-
+
+
+
+ settings
+ Created with Sketch.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/notification.html b/app/notification.html
index cc485da7f..be38f4aa3 100644
--- a/app/notification.html
+++ b/app/notification.html
@@ -9,7 +9,7 @@
}
-
+
diff --git a/app/popup.html b/app/popup.html
index d09b09315..c4e5188e5 100644
--- a/app/popup.html
+++ b/app/popup.html
@@ -1,11 +1,11 @@
-
+
MetaMask Plugin
-
+
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index bc4848421..ecac40481 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -42,7 +42,18 @@ class PreferencesController {
}
this.store.updateState({ tokens })
- return Promise.resolve()
+ return Promise.resolve(tokens)
+ }
+
+ removeToken (rawAddress) {
+ const address = normalizeAddress(rawAddress)
+
+ const tokens = this.store.getState().tokens
+
+ const updatedTokens = tokens.filter(token => token.address !== rawAddress)
+
+ this.store.updateState({ tokens: updatedTokens })
+ return Promise.resolve(updatedTokens)
}
getTokens () {
diff --git a/app/scripts/lib/environment-type.js b/app/scripts/lib/environment-type.js
new file mode 100644
index 000000000..7966926eb
--- /dev/null
+++ b/app/scripts/lib/environment-type.js
@@ -0,0 +1,10 @@
+module.exports = function environmentType () {
+ const url = window.location.href
+ if (url.match(/popup.html$/)) {
+ return 'popup'
+ } else if (url.match(/home.html$/)) {
+ return 'responsive'
+ } else {
+ return 'notification'
+ }
+}
diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js
index 693fa8751..e2999411f 100644
--- a/app/scripts/lib/is-popup-or-notification.js
+++ b/app/scripts/lib/is-popup-or-notification.js
@@ -1,6 +1,9 @@
module.exports = function isPopupOrNotification () {
const url = window.location.href
- if (url.match(/popup.html$/)) {
+ // if (url.match(/popup.html$/) || url.match(/home.html$/)) {
+ // Below regexes needed for feature toggles (e.g. see line ~340 in ui/app/app.js)
+ // Revert below regexes to above commented out regexes before merge to master
+ if (url.match(/popup.html(?:\?.+)*$/) || url.match(/home.html(?:\?.+)*$/)) {
return 'popup'
} else {
return 'notification'
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 727f48f1c..73db866a2 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -344,6 +344,7 @@ module.exports = class MetamaskController extends EventEmitter {
// PreferencesController
setSelectedAddress: nodeify(preferencesController.setSelectedAddress, preferencesController),
addToken: nodeify(preferencesController.addToken, preferencesController),
+ removeToken: nodeify(preferencesController.removeToken, preferencesController),
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController),
// AddressController
diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js
index f1eb394d7..2e4334bb1 100644
--- a/app/scripts/popup-core.js
+++ b/app/scripts/popup-core.js
@@ -1,6 +1,7 @@
const EventEmitter = require('events').EventEmitter
const async = require('async')
const Dnode = require('dnode')
+const Eth = require('ethjs')
const EthQuery = require('eth-query')
const launchMetamaskUi = require('../../ui')
const StreamProvider = require('web3-stream-provider')
@@ -34,6 +35,7 @@ function setupWeb3Connection (connectionStream) {
providerStream.on('error', console.error.bind(console))
global.ethereumProvider = providerStream
global.ethQuery = new EthQuery(providerStream)
+ global.eth = new Eth(providerStream)
}
function setupControllerConnection (connectionStream, cb) {
diff --git a/gulpfile.js b/gulpfile.js
index 9253949c7..96aada130 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -19,10 +19,16 @@ var manifest = require('./app/manifest.json')
var gulpif = require('gulp-if')
var replace = require('gulp-replace')
var mkdirp = require('mkdirp')
+var sass = require('gulp-sass')
+var autoprefixer = require('gulp-autoprefixer')
+var gulpStylelint = require('gulp-stylelint')
+var stylefmt = require('gulp-stylefmt')
+
var disableDebugTools = gutil.env.disableDebugTools
var debug = gutil.env.debug
+
// browser reload
gulp.task('dev:reload', function() {
@@ -159,13 +165,7 @@ gulp.task('lint', function () {
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError())
-});
-
-/*
-gulp.task('default', ['lint'], function () {
- // This will only run if the lint task is successful...
-});
-*/
+})
// build js
@@ -176,6 +176,37 @@ const jsFiles = [
'popup',
]
+// scss compilation and autoprefixing tasks
+
+gulp.task('build:scss', function () {
+ return gulp.src('ui/app/css/index.scss')
+ .pipe(sourcemaps.init())
+ .pipe(sass().on('error', sass.logError))
+ .pipe(sourcemaps.write())
+ .pipe(autoprefixer())
+ .pipe(gulp.dest('ui/app/css/output'))
+})
+gulp.task('watch:scss', function() {
+ gulp.watch(['ui/app/css/**/*.scss'], gulp.series(['build:scss']))
+})
+
+gulp.task('lint-scss', function() {
+ return gulp
+ .src('ui/app/css/itcss/**/*.scss')
+ .pipe(gulpStylelint({
+ reporters: [
+ {formatter: 'string', console: true}
+ ],
+ fix: true,
+ }));
+});
+
+gulp.task('fmt-scss', function () {
+ return gulp.src('ui/app/css/itcss/**/*.scss')
+ .pipe(stylefmt())
+ .pipe(gulp.dest('ui/app/css/itcss'));
+});
+
// bundle tasks
var jsDevStrings = jsFiles.map(jsFile => `dev:js:${jsFile}`)
@@ -219,9 +250,9 @@ gulp.task('zip', gulp.parallel('zip:chrome', 'zip:firefox', 'zip:edge', 'zip:ope
// high level tasks
-gulp.task('dev', gulp.series('dev:js', 'copy', gulp.parallel('copy:watch', 'dev:reload')))
+gulp.task('dev', gulp.series('build:scss', 'dev:js', 'copy', gulp.parallel('watch:scss', 'copy:watch', 'dev:reload')))
-gulp.task('build', gulp.series('clean', gulp.parallel('build:js', 'copy')))
+gulp.task('build', gulp.series('clean', 'build:scss', gulp.parallel('build:js', 'copy')))
gulp.task('dist', gulp.series('build', 'zip'))
// task generators
@@ -249,7 +280,7 @@ function zipTask(target) {
return () => {
return gulp.src(`dist/${target}/**`)
.pipe(zip(`metamask-${target}-${manifest.version}.zip`))
- .pipe(gulp.dest('builds'));
+ .pipe(gulp.dest('builds'))
}
}
diff --git a/package.json b/package.json
index 7b1578f7b..59b2836ce 100644
--- a/package.json
+++ b/package.json
@@ -45,17 +45,24 @@
]
}
],
+ "reactify",
"envify",
"brfs"
]
},
"dependencies": {
+ "abi-decoder": "^1.0.8",
"async": "^2.5.0",
"await-semaphore": "^0.1.1",
"babel-runtime": "^6.23.0",
+ "bignumber.js": "^4.0.4",
+ "bip39": "^2.2.0",
"bluebird": "^3.5.0",
"bn.js": "^4.11.7",
+ "boron": "^0.2.3",
+ "browser-passworder": "^2.0.3",
"browserify-derequire": "^0.9.4",
+ "classnames": "^2.2.5",
"client-sw-ready-event": "^3.3.0",
"clone": "^2.1.1",
"copy-to-clipboard": "^3.0.8",
@@ -68,19 +75,21 @@
"ensnare": "^1.0.0",
"eth-bin-to-ops": "^1.0.1",
"eth-block-tracker": "^2.2.0",
- "eth-contract-metadata": "^1.1.4",
"eth-hd-keyring": "^1.2.1",
"eth-json-rpc-filters": "^1.2.2",
"eth-keyring-controller": "^2.1.0",
+ "eth-contract-metadata": "^1.1.5",
"eth-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2",
"eth-sig-util": "^1.4.0",
"eth-simple-keyring": "^1.2.0",
"eth-token-tracker": "^1.1.4",
+ "ethereumjs-abi": "^0.6.4",
"ethereumjs-tx": "^1.3.0",
"ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9",
"ethereumjs-wallet": "^0.6.0",
"etherscan-link": "^1.0.2",
+ "ethjs": "^0.2.8",
"ethjs-contract": "^0.1.9",
"ethjs-ens": "^2.0.0",
"ethjs-query": "^0.2.9",
@@ -89,8 +98,11 @@
"extensionizer": "^1.0.0",
"fast-json-patch": "^2.0.4",
"fast-levenshtein": "^2.0.6",
+ "fuse.js": "^3.1.0",
"gulp": "github:gulpjs/gulp#4.0",
+ "gulp-autoprefixer": "^4.0.0",
"gulp-eslint": "^4.0.0",
+ "gulp-sass": "^3.1.0",
"hat": "0.0.3",
"human-standard-token-abi": "^1.0.2",
"idb-global": "^2.1.0",
@@ -120,6 +132,7 @@
"pump": "^1.0.2",
"pumpify": "^1.3.4",
"qrcode-npm": "0.0.3",
+ "ramda": "^0.24.1",
"react": "^15.0.2",
"react-addons-css-transition-group": "^15.6.0",
"react-dom": "^15.5.4",
@@ -129,6 +142,8 @@
"react-select": "^1.0.0-rc.2",
"react-simple-file-input": "^2.0.0",
"react-tooltip-component": "^0.3.0",
+ "react-transition-group": "^2.2.0",
+ "reactify": "^1.1.1",
"readable-stream": "^2.3.3",
"redux": "^3.0.5",
"redux-logger": "^3.0.6",
@@ -136,6 +151,7 @@
"request-promise": "^4.2.1",
"sandwich-expando": "^1.0.5",
"semaphore": "^1.0.5",
+ "shallow-copy": "0.0.1",
"sw-stream": "^2.0.0",
"textarea-caret": "^3.0.1",
"through2": "^2.0.3",
@@ -174,6 +190,8 @@
"gulp-livereload": "^3.8.1",
"gulp-replace": "^0.6.1",
"gulp-sourcemaps": "^2.6.0",
+ "gulp-stylefmt": "^1.1.0",
+ "gulp-stylelint": "^4.0.0",
"gulp-util": "^3.0.7",
"gulp-watch": "^4.3.5",
"gulp-zip": "^4.0.0",
@@ -201,6 +219,7 @@
"react-test-renderer": "^15.5.4",
"react-testutils-additions": "^15.2.0",
"sinon": "^4.0.0",
+ "stylelint-config-standard": "^17.0.0",
"tape": "^4.5.1",
"testem": "^1.10.3",
"uglifyify": "^4.0.2",
diff --git a/test/unit/components/balance-component-test.js b/test/unit/components/balance-component-test.js
new file mode 100644
index 000000000..c32a8ab2b
--- /dev/null
+++ b/test/unit/components/balance-component-test.js
@@ -0,0 +1,32 @@
+var assert = require('assert')
+var BalanceComponent = require('../../../ui/app/components/balance-component')
+
+describe('BalanceComponent', function () {
+ let balanceComponent
+
+ beforeEach(function () {
+ balanceComponent = new BalanceComponent()
+ })
+
+ it('shows token balance and convert to fiat value based on conversion rate', function () {
+ const formattedBalance = '1.23 ETH'
+
+ const tokenBalance = balanceComponent.getTokenBalance(formattedBalance, false)
+ const fiatDisplayNumber = balanceComponent.getFiatDisplayNumber(formattedBalance, 2)
+
+ assert.equal('1.23 ETH', tokenBalance)
+ assert.equal(2.46, fiatDisplayNumber)
+ })
+
+ it('shows only the token balance when conversion rate is not available', function () {
+ const formattedBalance = '1.23 ETH'
+
+ const tokenBalance = balanceComponent.getTokenBalance(formattedBalance, false)
+ const fiatDisplayNumber = balanceComponent.getFiatDisplayNumber(formattedBalance, 0)
+
+ assert.equal('1.23 ETH', tokenBalance)
+ assert.equal('N/A', fiatDisplayNumber)
+ })
+
+})
+
diff --git a/ui/app/account-and-transaction-details.js b/ui/app/account-and-transaction-details.js
new file mode 100644
index 000000000..60293de77
--- /dev/null
+++ b/ui/app/account-and-transaction-details.js
@@ -0,0 +1,38 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+// Main Views
+const TxView = require('./components/tx-view')
+const WalletView = require('./components/wallet-view')
+
+module.exports = AccountAndTransactionDetails
+
+inherits(AccountAndTransactionDetails, Component)
+function AccountAndTransactionDetails () {
+ Component.call(this)
+}
+
+AccountAndTransactionDetails.prototype.render = function () {
+ return h('div', {
+ style: {
+ display: 'flex',
+ flex: '1 0 auto',
+ },
+ }, [
+ // wallet
+ h(WalletView, {
+ style: {
+ },
+ responsiveDisplayClassname: '.lap-visible',
+ }, [
+ ]),
+
+ // transaction
+ h(TxView, {
+ style: {
+ },
+ }, [
+ ]),
+ ])
+}
+
diff --git a/ui/app/account-detail.js b/ui/app/account-detail.js
index d4f707e0b..0da435298 100644
--- a/ui/app/account-detail.js
+++ b/ui/app/account-detail.js
@@ -5,15 +5,10 @@ const h = require('react-hyperscript')
const connect = require('react-redux').connect
const actions = require('./actions')
const valuesFor = require('./util').valuesFor
-const Identicon = require('./components/identicon')
-const EthBalance = require('./components/eth-balance')
const TransactionList = require('./components/transaction-list')
const ExportAccountView = require('./components/account-export')
-const ethUtil = require('ethereumjs-util')
-const EditableLabel = require('./components/editable-label')
const TabBar = require('./components/tab-bar')
const TokenList = require('./components/token-list')
-const AccountDropdowns = require('./components/account-dropdowns').AccountDropdowns
module.exports = connect(mapStateToProps)(AccountDetailScreen)
@@ -41,180 +36,11 @@ function AccountDetailScreen () {
Component.call(this)
}
-AccountDetailScreen.prototype.render = function () {
- var props = this.props
- var selected = props.address || Object.keys(props.accounts)[0]
- var checksumAddress = selected && ethUtil.toChecksumAddress(selected)
- var identity = props.identities[selected]
- var account = props.accounts[selected]
- const { network, conversionRate, currentCurrency } = props
-
- return (
-
- h('.account-detail-section.full-flex-height', [
-
- // identicon, label, balance, etc
- h('.account-data-subsection', {
- style: {
- margin: '0 20px',
- flex: '1 0 auto',
- },
- }, [
-
- // header - identicon + nav
- h('div', {
- style: {
- paddingTop: '20px',
- display: 'flex',
- justifyContent: 'flex-start',
- alignItems: 'flex-start',
- },
- }, [
-
- // large identicon and addresses
- h('.identicon-wrapper.select-none', [
- h(Identicon, {
- diameter: 62,
- address: selected,
- }),
- ]),
- h('flex-column', {
- style: {
- lineHeight: '10px',
- marginLeft: '15px',
- width: '100%',
- },
- }, [
- h(EditableLabel, {
- textValue: identity ? identity.name : '',
- state: {
- isEditingLabel: false,
- },
- saveText: (text) => {
- props.dispatch(actions.saveAccountLabel(selected, text))
- },
- }, [
-
- // What is shown when not editing + edit text:
- h('label.editing-label', [h('.edit-text', 'edit')]),
- h(
- 'div',
- {
- style: {
- display: 'flex',
- justifyContent: 'flex-start',
- alignItems: 'center',
- },
- },
- [
- h(
- 'div.font-medium.color-forest',
- {
- name: 'edit',
- style: {
- },
- },
- [
- h('h2', {
- style: {
- maxWidth: '180px',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- padding: '5px 0px',
- lineHeight: '25px',
- },
- }, [
- identity && identity.name,
- ]),
- ]
- ),
- h(
- AccountDropdowns,
- {
- style: {
- marginRight: '8px',
- marginLeft: 'auto',
- cursor: 'pointer',
- },
- selected,
- network,
- identities: props.identities,
- enableAccountOptions: true,
- },
- ),
- ]
- ),
- ]),
- h('.flex-row', {
- style: {
- width: '15em',
- justifyContent: 'space-between',
- alignItems: 'baseline',
- },
- }, [
-
- // address
-
- h('div', {
- style: {
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- paddingTop: '3px',
- width: '5em',
- fontSize: '13px',
- fontFamily: 'Montserrat Light',
- textRendering: 'geometricPrecision',
- marginBottom: '15px',
- color: '#AEAEAE',
- },
- }, checksumAddress),
- ]),
-
- // account ballence
-
- ]),
- ]),
- h('.flex-row', {
- style: {
- justifyContent: 'space-between',
- alignItems: 'flex-start',
- },
- }, [
-
- h(EthBalance, {
- value: account && account.balance,
- conversionRate,
- currentCurrency,
- style: {
- lineHeight: '7px',
- marginTop: '10px',
- },
- }),
-
- h('.flex-grow'),
-
- h('button', {
- onClick: () => props.dispatch(actions.buyEthView(selected)),
- style: { marginRight: '10px' },
- }, 'BUY'),
-
- h('button', {
- onClick: () => props.dispatch(actions.showSendPage()),
- style: {
- marginBottom: '20px',
- marginRight: '8px',
- },
- }, 'SEND'),
-
- ]),
- ]),
-
- // subview (tx history, pk export confirm, buy eth warning)
- this.subview(),
-
- ])
- )
-}
+// Note: This component is no longer used. Leaving the file for reference:
+// - structuring routing for add token
+// - state required for TxList
+// Delete file when those features are complete
+AccountDetailScreen.prototype.render = function () {}
AccountDetailScreen.prototype.subview = function () {
var subview
diff --git a/ui/app/accounts/import/index.js b/ui/app/accounts/import/index.js
index 97b387229..c66dcfc66 100644
--- a/ui/app/accounts/import/index.js
+++ b/ui/app/accounts/import/index.js
@@ -34,8 +34,10 @@ AccountImportSubview.prototype.render = function () {
const { type } = state
return (
- h('div', {
+ h('div.flex-center', {
style: {
+ flexDirection: 'column',
+ marginTop: '32px',
},
}, [
h('.section-title.flex-row.flex-center', [
@@ -48,7 +50,8 @@ AccountImportSubview.prototype.render = function () {
]),
h('div', {
style: {
- padding: '10px',
+ padding: '10px 0',
+ width: '260px',
color: 'rgb(174, 174, 174)',
},
}, [
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 84990922e..4c83f95b4 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -1,3 +1,4 @@
+const abi = require('human-standard-token-abi')
const getBuyEthUrl = require('../../app/scripts/lib/buy-eth-url')
var actions = {
@@ -5,6 +6,21 @@ var actions = {
GO_HOME: 'GO_HOME',
goHome: goHome,
+ // modal state
+ MODAL_OPEN: 'UI_MODAL_OPEN',
+ MODAL_CLOSE: 'UI_MODAL_CLOSE',
+ showModal: showModal,
+ hideModal: hideModal,
+ // sidebar state
+ SIDEBAR_OPEN: 'UI_SIDEBAR_OPEN',
+ SIDEBAR_CLOSE: 'UI_SIDEBAR_CLOSE',
+ showSidebar: showSidebar,
+ hideSidebar: hideSidebar,
+ // network dropdown open
+ NETWORK_DROPDOWN_OPEN: 'UI_NETWORK_DROPDOWN_OPEN',
+ NETWORK_DROPDOWN_CLOSE: 'UI_NETWORK_DROPDOWN_CLOSE',
+ showNetworkDropdown: showNetworkDropdown,
+ hideNetworkDropdown: hideNetworkDropdown,
// menu state
getNetworkStatus: 'getNetworkStatus',
// transition state
@@ -68,6 +84,8 @@ var actions = {
hideWarning: hideWarning,
// accounts screen
SET_SELECTED_ACCOUNT: 'SET_SELECTED_ACCOUNT',
+ SET_SELECTED_TOKEN: 'SET_SELECTED_TOKEN',
+ setSelectedToken,
SHOW_ACCOUNT_DETAIL: 'SHOW_ACCOUNT_DETAIL',
SHOW_ACCOUNTS_PAGE: 'SHOW_ACCOUNTS_PAGE',
SHOW_CONF_TX_PAGE: 'SHOW_CONF_TX_PAGE',
@@ -78,6 +96,8 @@ var actions = {
// account detail screen
SHOW_SEND_PAGE: 'SHOW_SEND_PAGE',
showSendPage: showSendPage,
+ SHOW_SEND_TOKEN_PAGE: 'SHOW_SEND_TOKEN_PAGE',
+ showSendTokenPage,
ADD_TO_ADDRESS_BOOK: 'ADD_TO_ADDRESS_BOOK',
addToAddressBook: addToAddressBook,
REQUEST_ACCOUNT_EXPORT: 'REQUEST_ACCOUNT_EXPORT',
@@ -86,6 +106,7 @@ var actions = {
exportAccount: exportAccount,
SHOW_PRIVATE_KEY: 'SHOW_PRIVATE_KEY',
showPrivateKey: showPrivateKey,
+ exportAccountComplete,
SAVE_ACCOUNT_LABEL: 'SAVE_ACCOUNT_LABEL',
saveAccountLabel: saveAccountLabel,
// tx conf screen
@@ -99,7 +120,9 @@ var actions = {
cancelPersonalMsg,
signTypedMsg,
cancelTypedMsg,
+ sendTx: sendTx,
signTx: signTx,
+ signTokenTx: signTokenTx,
updateAndApproveTx,
cancelTx: cancelTx,
completedTx: completedTx,
@@ -109,6 +132,26 @@ var actions = {
cancelAllTx: cancelAllTx,
viewPendingTx: viewPendingTx,
VIEW_PENDING_TX: 'VIEW_PENDING_TX',
+ // send screen
+ estimateGas,
+ getGasPrice,
+ UPDATE_GAS_LIMIT: 'UPDATE_GAS_LIMIT',
+ UPDATE_GAS_PRICE: 'UPDATE_GAS_PRICE',
+ UPDATE_GAS_TOTAL: 'UPDATE_GAS_TOTAL',
+ UPDATE_SEND_FROM: 'UPDATE_SEND_FROM',
+ UPDATE_SEND_TO: 'UPDATE_SEND_TO',
+ UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT',
+ UPDATE_SEND_MEMO: 'UPDATE_SEND_MEMO',
+ UPDATE_SEND_ERRORS: 'UPDATE_SEND_ERRORS',
+ updateGasLimit,
+ updateGasPrice,
+ updateGasTotal,
+ updateSendFrom,
+ updateSendTo,
+ updateSendAmount,
+ updateSendMemo,
+ updateSendErrors,
+ setSelectedAddress,
// app messages
confirmSeedWords: confirmSeedWords,
showAccountDetail: showAccountDetail,
@@ -125,8 +168,13 @@ var actions = {
SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE',
showAddTokenPage,
addToken,
+ addTokens,
+ removeToken,
+ updateTokens,
+ UPDATE_TOKENS: 'UPDATE_TOKENS',
setRpcTarget: setRpcTarget,
setProviderType: setProviderType,
+ updateProviderType,
// loading overlay
SHOW_LOADING: 'SHOW_LOADING_INDICATION',
HIDE_LOADING: 'HIDE_LOADING_INDICATION',
@@ -141,6 +189,8 @@ var actions = {
coinBaseSubview: coinBaseSubview,
SHAPESHIFT_SUBVIEW: 'SHAPESHIFT_SUBVIEW',
shapeShiftSubview: shapeShiftSubview,
+ UPDATE_TOKEN_EXCHANGE_RATE: 'UPDATE_TOKEN_EXCHANGE_RATE',
+ updateTokenExchangeRate,
PAIR_UPDATE: 'PAIR_UPDATE',
pairUpdate: pairUpdate,
coinShiftRquest: coinShiftRquest,
@@ -165,6 +215,9 @@ var actions = {
callBackgroundThenUpdate,
forceUpdateMetamaskState,
+
+ TOGGLE_ACCOUNT_MENU: 'TOGGLE_ACCOUNT_MENU',
+ toggleAccountMenu,
}
module.exports = actions
@@ -325,7 +378,24 @@ function navigateToNewAccountScreen () {
function addNewAccount () {
log.debug(`background.addNewAccount`)
- return callBackgroundThenUpdate(background.addNewAccount)
+ return (dispatch, getState) => {
+ const oldIdentities = getState().metamask.identities
+ dispatch(actions.showLoadingIndication())
+ return new Promise((resolve, reject) => {
+ background.addNewAccount((err, { identities: newIdentities}) => {
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ return reject(err)
+ }
+ const newAccountAddress = Object.keys(newIdentities).find(address => !oldIdentities[address])
+
+ dispatch(actions.hideLoadingIndication())
+
+ forceUpdateMetamaskState(dispatch)
+ return resolve(newAccountAddress)
+ })
+ });
+ }
}
function showInfoPage () {
@@ -336,16 +406,16 @@ function showInfoPage () {
function setCurrentCurrency (currencyCode) {
return (dispatch) => {
- dispatch(this.showLoadingIndication())
+ dispatch(actions.showLoadingIndication())
log.debug(`background.setCurrentCurrency`)
background.setCurrentCurrency(currencyCode, (err, data) => {
- dispatch(this.hideLoadingIndication())
+ dispatch(actions.hideLoadingIndication())
if (err) {
log.error(err.stack)
return dispatch(actions.displayWarning(err.message))
}
dispatch({
- type: this.SET_CURRENT_FIAT,
+ type: actions.SET_CURRENT_FIAT,
value: {
currentCurrency: data.currentCurrency,
conversionRate: data.conversionRate,
@@ -418,10 +488,127 @@ function signTx (txData) {
dispatch(actions.showLoadingIndication())
global.ethQuery.sendTransaction(txData, (err, data) => {
dispatch(actions.hideLoadingIndication())
- if (err) dispatch(actions.displayWarning(err.message))
- dispatch(this.goHome())
+ if (err) return dispatch(actions.displayWarning(err.message))
+ dispatch(actions.hideWarning())
})
- dispatch(actions.showConfTxPage())
+ dispatch(actions.showConfTxPage({}))
+ }
+}
+
+function estimateGas (params = {}) {
+ return (dispatch) => {
+ return new Promise((resolve, reject) => {
+ global.ethQuery.estimateGas(params, (err, data) => {
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ return reject(err)
+ }
+ dispatch(actions.hideWarning())
+ dispatch(actions.updateGasLimit(data))
+ return resolve(data)
+ })
+ })
+ }
+}
+
+function updateGasLimit (gasLimit) {
+ return {
+ type: actions.UPDATE_GAS_LIMIT,
+ value: gasLimit,
+ }
+}
+
+function getGasPrice () {
+ return (dispatch) => {
+ return new Promise((resolve, reject) => {
+ global.ethQuery.gasPrice((err, data) => {
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ return reject(err)
+ }
+ dispatch(actions.hideWarning())
+ dispatch(actions.updateGasPrice(data))
+ return resolve(data)
+ })
+ })
+ }
+}
+
+function updateGasPrice (gasPrice) {
+ return {
+ type: actions.UPDATE_GAS_PRICE,
+ value: gasPrice,
+ }
+}
+
+function updateGasTotal (gasTotal) {
+ return {
+ type: actions.UPDATE_GAS_TOTAL,
+ value: gasTotal,
+ }
+}
+
+function updateSendFrom (from) {
+ return {
+ type: actions.UPDATE_SEND_FROM,
+ value: from,
+ }
+}
+
+function updateSendTo (to) {
+ return {
+ type: actions.UPDATE_SEND_TO,
+ value: to,
+ }
+}
+
+function updateSendAmount (amount) {
+ return {
+ type: actions.UPDATE_SEND_AMOUNT,
+ value: amount,
+ }
+}
+
+function updateSendMemo (memo) {
+ return {
+ type: actions.UPDATE_SEND_MEMO,
+ value: memo,
+ }
+}
+
+function updateSendErrors (error) {
+ console.log(`updateSendErrors error`, error);
+ return {
+ type: actions.UPDATE_SEND_ERRORS,
+ value: error,
+ }
+}
+
+
+function sendTx (txData) {
+ log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`)
+ return (dispatch) => {
+ log.debug(`actions calling background.approveTransaction`)
+ background.approveTransaction(txData.id, (err) => {
+ if (err) {
+ dispatch(actions.txError(err))
+ return log.error(err.message)
+ }
+ dispatch(actions.completedTx(txData.id))
+ })
+ }
+}
+
+function signTokenTx (tokenAddress, toAddress, amount, txData) {
+ return dispatch => {
+ dispatch(actions.showLoadingIndication())
+ const token = global.eth.contract(abi).at(tokenAddress)
+ token.transfer(toAddress, amount, txData)
+ .catch(err => {
+ dispatch(actions.hideLoadingIndication())
+ dispatch(actions.displayWarning(err.message))
+ })
+ dispatch(actions.showConfTxPage({}))
}
}
@@ -592,6 +779,26 @@ function setCurrentAccountTab (newTabName) {
return callBackgroundThenUpdateNoSpinner(background.setCurrentAccountTab, newTabName)
}
+function setSelectedToken (tokenAddress) {
+ return {
+ type: actions.SET_SELECTED_TOKEN,
+ value: tokenAddress || null,
+ }
+}
+
+function setSelectedAddress (address) {
+ return (dispatch) => {
+ dispatch(actions.showLoadingIndication())
+ log.debug(`background.setSelectedAddress`)
+ background.setSelectedAddress(address, (err) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) {
+ return dispatch(actions.displayWarning(err.message))
+ }
+ })
+ }
+}
+
function showAccountDetail (address) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
@@ -605,6 +812,7 @@ function showAccountDetail (address) {
type: actions.SHOW_ACCOUNT_DETAIL,
value: address,
})
+ dispatch(actions.setSelectedToken())
})
}
}
@@ -622,10 +830,11 @@ function showAccountsPage () {
}
}
-function showConfTxPage (transForward = true) {
+function showConfTxPage ({transForward = true, id}) {
return {
type: actions.SHOW_CONF_TX_PAGE,
- transForward: transForward,
+ transForward,
+ id,
}
}
@@ -655,28 +864,71 @@ function showConfigPage (transitionForward = true) {
}
}
-function showAddTokenPage (transitionForward = true) {
+function showAddTokenPage () {
return {
type: actions.SHOW_ADD_TOKEN_PAGE,
- value: transitionForward,
}
}
function addToken (address, symbol, decimals) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
- background.addToken(address, symbol, decimals, (err) => {
- dispatch(actions.hideLoadingIndication())
- if (err) {
- return dispatch(actions.displayWarning(err.message))
- }
- setTimeout(() => {
- dispatch(actions.goHome())
- }, 250)
+ return new Promise((resolve, reject) => {
+ background.addToken(address, symbol, decimals, (err, tokens) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ reject(err)
+ }
+ dispatch(actions.updateTokens(tokens))
+ resolve(tokens)
+ })
})
}
}
+function removeToken (address) {
+ return (dispatch) => {
+ dispatch(actions.showLoadingIndication())
+ return new Promise((resolve, reject) => {
+ background.removeToken(address, (err, tokens) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ reject(err)
+ }
+ dispatch(actions.updateTokens(tokens))
+ resolve(tokens)
+ })
+ })
+ }
+}
+
+function addTokens (tokens) {
+ return dispatch => {
+ if (Array.isArray(tokens)) {
+ return Promise.all(tokens.map(({ address, symbol, decimals }) => (
+ dispatch(addToken(address, symbol, decimals))
+ )))
+ } else {
+ return Promise.all(
+ Object
+ .entries(tokens)
+ .map(([_, { address, symbol, decimals }]) => (
+ dispatch(addToken(address, symbol, decimals))
+ ))
+ )
+ }
+ }
+}
+
+function updateTokens(newTokens) {
+ return {
+ type: actions.UPDATE_TOKENS,
+ newTokens
+ }
+}
+
function goBackToInitView () {
return {
type: actions.BACK_TO_INIT_MENU,
@@ -738,11 +990,17 @@ function setProviderType (type) {
log.error(err)
return dispatch(self.displayWarning('Had a problem changing networks!'))
}
+ dispatch(actions.updateProviderType(type))
+ dispatch(actions.setSelectedToken())
})
- return {
- type: actions.SET_PROVIDER_TYPE,
- value: type,
- }
+
+ }
+}
+
+function updateProviderType(type) {
+ return {
+ type: actions.SET_PROVIDER_TYPE,
+ value: type,
}
}
@@ -759,7 +1017,7 @@ function setRpcTarget (newRpc) {
}
// Calls the addressBookController to add a new address.
-function addToAddressBook (recipient, nickname) {
+function addToAddressBook (recipient, nickname = '') {
log.debug(`background.addToAddressBook`)
return (dispatch) => {
background.setAddressBook(recipient, nickname, (err, result) => {
@@ -771,6 +1029,54 @@ function addToAddressBook (recipient, nickname) {
}
}
+function useEtherscanProvider () {
+ log.debug(`background.useEtherscanProvider`)
+ background.useEtherscanProvider()
+ return {
+ type: actions.USE_ETHERSCAN_PROVIDER,
+ }
+}
+
+function showNetworkDropdown () {
+ return {
+ type: actions.NETWORK_DROPDOWN_OPEN,
+ }
+}
+
+function hideNetworkDropdown () {
+ return {
+ type: actions.NETWORK_DROPDOWN_CLOSE,
+ }
+}
+
+
+function showModal (payload) {
+ return {
+ type: actions.MODAL_OPEN,
+ payload,
+ }
+}
+
+function hideModal (payload) {
+ return {
+ type: actions.MODAL_CLOSE,
+ payload,
+ }
+}
+
+function showSidebar () {
+ return {
+ type: actions.SIDEBAR_OPEN,
+ }
+}
+
+function hideSidebar () {
+ return {
+ type: actions.SIDEBAR_CLOSE,
+ }
+}
+
+
function showLoadingIndication (message) {
return {
type: actions.SHOW_LOADING,
@@ -822,27 +1128,39 @@ function exportAccount (password, address) {
dispatch(self.showLoadingIndication())
log.debug(`background.submitPassword`)
- background.submitPassword(password, function (err) {
- if (err) {
- log.error('Error in submiting password.')
- dispatch(self.hideLoadingIndication())
- return dispatch(self.displayWarning('Incorrect Password.'))
- }
- log.debug(`background.exportAccount`)
- background.exportAccount(address, function (err, result) {
- dispatch(self.hideLoadingIndication())
-
+ return new Promise((resolve, reject) => {
+ background.submitPassword(password, function (err) {
if (err) {
- log.error(err)
- return dispatch(self.displayWarning('Had a problem exporting the account.'))
+ log.error('Error in submiting password.')
+ dispatch(self.hideLoadingIndication())
+ dispatch(self.displayWarning('Incorrect Password.'))
+ return reject(err)
}
+ log.debug(`background.exportAccount`)
+ return background.exportAccount(address, function (err, result) {
+ dispatch(self.hideLoadingIndication())
- dispatch(self.showPrivateKey(result))
+ if (err) {
+ log.error(err)
+ dispatch(self.displayWarning('Had a problem exporting the account.'))
+ return reject(err)
+ }
+
+ dispatch(self.exportAccountComplete())
+
+ return resolve(result)
+ })
})
})
}
}
+function exportAccountComplete() {
+ return {
+ type: actions.EXPORT_ACCOUNT,
+ }
+}
+
function showPrivateKey (key) {
return {
type: actions.SHOW_PRIVATE_KEY,
@@ -873,6 +1191,12 @@ function showSendPage () {
}
}
+function showSendTokenPage () {
+ return {
+ type: actions.SHOW_SEND_TOKEN_PAGE,
+ }
+}
+
function buyEth (opts) {
return (dispatch) => {
const url = getBuyEthUrl(opts)
@@ -970,7 +1294,10 @@ function reshowQrCode (data, coin) {
]
dispatch(actions.hideLoadingIndication())
- return dispatch(actions.showQrView(data, message))
+ return dispatch(actions.showModal({
+ name: 'SHAPESHIFT_DEPOSIT_TX',
+ Qr: { data, message },
+ }))
})
}
}
@@ -999,6 +1326,28 @@ function shapeShiftRequest (query, options, cb) {
}
}
+function updateTokenExchangeRate (token = '') {
+ const pair = `${token.toLowerCase()}_eth`
+
+ return dispatch => {
+ if (!token) {
+ return
+ }
+
+ shapeShiftRequest('marketinfo', { pair }, marketinfo => {
+ if (!marketinfo.error) {
+ dispatch({
+ type: actions.UPDATE_TOKEN_EXCHANGE_RATE,
+ payload: {
+ pair,
+ marketinfo,
+ },
+ })
+ }
+ })
+ }
+}
+
// Call Background Then Update
//
// A function generator for a common pattern wherein:
@@ -1040,3 +1389,9 @@ function forceUpdateMetamaskState (dispatch) {
dispatch(actions.updateMetamaskState(newState))
})
}
+
+function toggleAccountMenu () {
+ return {
+ type: actions.TOGGLE_ACCOUNT_MENU,
+ }
+}
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index 9354a4cad..90edc8de1 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -1,169 +1,65 @@
const inherits = require('util').inherits
const Component = require('react').Component
+const classnames = require('classnames')
const h = require('react-hyperscript')
const connect = require('react-redux').connect
+const Fuse = require('fuse.js')
+const contractMap = require('eth-contract-metadata')
+const TokenBalance = require('./components/token-balance')
+const Identicon = require('./components/identicon')
+const contractList = Object.entries(contractMap).map(([ _, tokenData]) => tokenData)
+const fuse = new Fuse(contractList, {
+ shouldSort: true,
+ threshold: 0.45,
+ location: 0,
+ distance: 100,
+ maxPatternLength: 32,
+ minMatchCharLength: 1,
+ keys: ['address', 'name', 'symbol'],
+})
const actions = require('./actions')
-const Tooltip = require('./components/tooltip.js')
-
-
const ethUtil = require('ethereumjs-util')
const abi = require('human-standard-token-abi')
const Eth = require('ethjs-query')
const EthContract = require('ethjs-contract')
+const R = require('ramda')
const emptyAddr = '0x0000000000000000000000000000000000000000'
-module.exports = connect(mapStateToProps)(AddTokenScreen)
+module.exports = connect(mapStateToProps, mapDispatchToProps)(AddTokenScreen)
function mapStateToProps (state) {
+ const { identities, tokens } = state.metamask
return {
- identities: state.metamask.identities,
+ identities,
+ tokens,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ goHome: () => dispatch(actions.goHome()),
+ addTokens: tokens => dispatch(actions.addTokens(tokens)),
}
}
inherits(AddTokenScreen, Component)
function AddTokenScreen () {
this.state = {
- warning: null,
- address: null,
- symbol: 'TOKEN',
- decimals: 18,
+ isShowingConfirmation: false,
+ customAddress: '',
+ customSymbol: '',
+ customDecimals: 0,
+ searchQuery: '',
+ isCollapsed: true,
+ selectedTokens: {},
+ errors: {},
}
+ this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this)
+ this.onNext = this.onNext.bind(this)
Component.call(this)
}
-AddTokenScreen.prototype.render = function () {
- const state = this.state
- const props = this.props
- const { warning, symbol, decimals } = state
-
- return (
- h('.flex-column.flex-grow', [
-
- // subtitle and nav
- h('.section-title.flex-row.flex-center', [
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- onClick: (event) => {
- props.dispatch(actions.goHome())
- },
- }),
- h('h2.page-subtitle', 'Add Token'),
- ]),
-
- h('.error', {
- style: {
- display: warning ? 'block' : 'none',
- padding: '0 20px',
- textAlign: 'center',
- },
- }, warning),
-
- // conf view
- h('.flex-column.flex-justify-center.flex-grow.select-none', [
- h('.flex-space-around', {
- style: {
- padding: '20px',
- },
- }, [
-
- h('div', [
- h(Tooltip, {
- position: 'top',
- title: 'The contract of the actual token contract. Click for more info.',
- }, [
- h('a', {
- style: { fontWeight: 'bold', paddingRight: '10px'},
- href: 'https://support.metamask.io/kb/article/24-what-is-a-token-contract-address',
- target: '_blank',
- }, [
- h('span', 'Token Contract Address '),
- h('i.fa.fa-question-circle'),
- ]),
- ]),
- ]),
-
- h('section.flex-row.flex-center', [
- h('input#token-address', {
- name: 'address',
- placeholder: 'Token Contract Address',
- onChange: this.tokenAddressDidChange.bind(this),
- style: {
- width: 'inherit',
- flex: '1 0 auto',
- height: '30px',
- margin: '8px',
- },
- }),
- ]),
-
- h('div', [
- h('span', {
- style: { fontWeight: 'bold', paddingRight: '10px'},
- }, 'Token Symbol'),
- ]),
-
- h('div', { style: {display: 'flex'} }, [
- h('input#token_symbol', {
- placeholder: `Like "ETH"`,
- value: symbol,
- style: {
- width: 'inherit',
- flex: '1 0 auto',
- height: '30px',
- margin: '8px',
- },
- onChange: (event) => {
- var element = event.target
- var symbol = element.value
- this.setState({ symbol })
- },
- }),
- ]),
-
- h('div', [
- h('span', {
- style: { fontWeight: 'bold', paddingRight: '10px'},
- }, 'Decimals of Precision'),
- ]),
-
- h('div', { style: {display: 'flex'} }, [
- h('input#token_decimals', {
- value: decimals,
- type: 'number',
- min: 0,
- max: 36,
- style: {
- width: 'inherit',
- flex: '1 0 auto',
- height: '30px',
- margin: '8px',
- },
- onChange: (event) => {
- var element = event.target
- var decimals = element.value.trim()
- this.setState({ decimals })
- },
- }),
- ]),
-
- h('button', {
- style: {
- alignSelf: 'center',
- },
- onClick: (event) => {
- const valid = this.validateInputs()
- if (!valid) return
-
- const { address, symbol, decimals } = this.state
- this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals))
- },
- }, 'Add'),
- ]),
- ]),
- ])
- )
-}
-
AddTokenScreen.prototype.componentWillMount = function () {
if (typeof global.ethereumProvider === 'undefined') return
@@ -172,54 +68,96 @@ AddTokenScreen.prototype.componentWillMount = function () {
this.TokenContract = this.contract(abi)
}
-AddTokenScreen.prototype.tokenAddressDidChange = function (event) {
- const el = event.target
- const address = el.value.trim()
- if (ethUtil.isValidAddress(address) && address !== emptyAddr) {
- this.setState({ address })
- this.attemptToAutoFillTokenParams(address)
+AddTokenScreen.prototype.toggleToken = function (address, token) {
+ const { selectedTokens, errors } = this.state
+ const { [address]: selectedToken } = selectedTokens
+ this.setState({
+ selectedTokens: {
+ ...selectedTokens,
+ [address]: selectedToken ? null : token,
+ },
+ errors: {
+ ...errors,
+ tokenSelector: null,
+ },
+ })
+}
+
+AddTokenScreen.prototype.onNext = function () {
+ const { isValid, errors } = this.validate()
+
+ return !isValid
+ ? this.setState({ errors })
+ : this.setState({ isShowingConfirmation: true })
+}
+
+AddTokenScreen.prototype.tokenAddressDidChange = function (e) {
+ const customAddress = e.target.value.trim()
+ this.setState({ customAddress })
+ if (ethUtil.isValidAddress(customAddress) && customAddress !== emptyAddr) {
+ this.attemptToAutoFillTokenParams(customAddress)
+ } else {
+ this.setState({
+ customSymbol: '',
+ customDecimals: 0,
+ })
}
}
-AddTokenScreen.prototype.validateInputs = function () {
- let msg = ''
- const state = this.state
+AddTokenScreen.prototype.checkExistingAddresses = function (address) {
+ const tokensList = this.props.tokens
+ const matchesAddress = existingToken => {
+ return existingToken.address.toLowerCase() === address.toLowerCase()
+ }
+
+ return R.any(matchesAddress)(tokensList)
+}
+
+AddTokenScreen.prototype.validate = function () {
+ const errors = {}
const identitiesList = Object.keys(this.props.identities)
- const { address, symbol, decimals } = state
- const standardAddress = ethUtil.addHexPrefix(address).toLowerCase()
+ const { customAddress, customSymbol, customDecimals, selectedTokens } = this.state
+ const standardAddress = ethUtil.addHexPrefix(customAddress).toLowerCase()
- const validAddress = ethUtil.isValidAddress(address)
- if (!validAddress) {
- msg += 'Address is invalid. '
+ if (customAddress) {
+ const validAddress = ethUtil.isValidAddress(customAddress)
+ if (!validAddress) {
+ errors.customAddress = 'Address is invalid. '
+ }
+
+ const validDecimals = customDecimals >= 0 && customDecimals < 36
+ if (!validDecimals) {
+ errors.customDecimals = 'Decimals must be at least 0, and not over 36.'
+ }
+
+ const symbolLen = customSymbol.trim().length
+ const validSymbol = symbolLen > 0 && symbolLen < 10
+ if (!validSymbol) {
+ errors.customSymbol = 'Symbol must be between 0 and 10 characters.'
+ }
+
+ const ownAddress = identitiesList.includes(standardAddress)
+ if (ownAddress) {
+ errors.customAddress = 'Personal address detected. Input the token contract address.'
+ }
+
+ const tokenAlreadyAdded = this.checkExistingAddresses(customAddress)
+ if (tokenAlreadyAdded) {
+ errors.customAddress = 'Token has already been added.'
+ }
+ } else if (
+ Object.entries(selectedTokens)
+ .reduce((isEmpty, [ symbol, isSelected ]) => (
+ isEmpty && !isSelected
+ ), true)
+ ) {
+ errors.tokenSelector = 'Must select at least 1 token.'
}
- const validDecimals = decimals >= 0 && decimals < 36
- if (!validDecimals) {
- msg += 'Decimals must be at least 0, and not over 36. '
+ return {
+ isValid: !Object.keys(errors).length,
+ errors,
}
-
- const symbolLen = symbol.trim().length
- const validSymbol = symbolLen > 0 && symbolLen < 10
- if (!validSymbol) {
- msg += 'Symbol must be between 0 and 10 characters.'
- }
-
- const ownAddress = identitiesList.includes(standardAddress)
- if (ownAddress) {
- msg = 'Personal address detected. Input the token contract address.'
- }
-
- const isValid = validAddress && validDecimals && !ownAddress
-
- if (!isValid) {
- this.setState({
- warning: msg,
- })
- } else {
- this.setState({ warning: null })
- }
-
- return isValid
}
AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
@@ -232,7 +170,195 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address)
const [ symbol, decimals ] = results
if (symbol && decimals) {
- console.log('SETTING SYMBOL AND DECIMALS', { symbol, decimals })
- this.setState({ symbol: symbol[0], decimals: decimals[0].toString() })
+ this.setState({
+ customSymbol: symbol[0],
+ customDecimals: decimals[0].toString(),
+ })
}
}
+
+AddTokenScreen.prototype.renderCustomForm = function () {
+ const { customAddress, customSymbol, customDecimals, errors } = this.state
+
+ return !this.state.isCollapsed && (
+ h('div.add-token__add-custom-form', [
+ h('div', {
+ className: classnames('add-token__add-custom-field', {
+ 'add-token__add-custom-field--error': errors.customAddress,
+ }),
+ }, [
+ h('div.add-token__add-custom-label', 'Token Address'),
+ h('input.add-token__add-custom-input', {
+ type: 'text',
+ onChange: this.tokenAddressDidChange,
+ value: customAddress,
+ }),
+ h('div.add-token__add-custom-error-message', errors.customAddress),
+ ]),
+ h('div', {
+ className: classnames('add-token__add-custom-field', {
+ 'add-token__add-custom-field--error': errors.customSymbol,
+ }),
+ }, [
+ h('div.add-token__add-custom-label', 'Token Symbol'),
+ h('input.add-token__add-custom-input', {
+ type: 'text',
+ value: customSymbol,
+ disabled: true,
+ }),
+ h('div.add-token__add-custom-error-message', errors.customSymbol),
+ ]),
+ h('div', {
+ className: classnames('add-token__add-custom-field', {
+ 'add-token__add-custom-field--error': errors.customDecimals,
+ }),
+ }, [
+ h('div.add-token__add-custom-label', 'Decimals of Precision'),
+ h('input.add-token__add-custom-input', {
+ type: 'number',
+ value: customDecimals,
+ disabled: true,
+ }),
+ h('div.add-token__add-custom-error-message', errors.customDecimals),
+ ]),
+ ])
+ )
+}
+
+AddTokenScreen.prototype.renderTokenList = function () {
+ const { searchQuery = '', selectedTokens } = this.state
+ const results = searchQuery
+ ? fuse.search(searchQuery) || []
+ : contractList
+
+ return Array(6).fill(undefined)
+ .map((_, i) => {
+ const { logo, symbol, name, address } = results[i] || {}
+ const tokenAlreadyAdded = this.checkExistingAddresses(address)
+ return Boolean(logo || symbol || name) && (
+ h('div.add-token__token-wrapper', {
+ className: classnames({
+ 'add-token__token-wrapper--selected': selectedTokens[address],
+ 'add-token__token-wrapper--disabled': tokenAlreadyAdded,
+ }),
+ onClick: () => !tokenAlreadyAdded && this.toggleToken(address, results[i]),
+ }, [
+ h('div.add-token__token-icon', {
+ style: {
+ backgroundImage: `url(images/contract/${logo})`,
+ },
+ }),
+ h('div.add-token__token-data', [
+ h('div.add-token__token-symbol', symbol),
+ h('div.add-token__token-name', name),
+ ]),
+ tokenAlreadyAdded && (
+ h('div.add-token__token-message', 'Already added')
+ ),
+ ])
+ )
+ })
+}
+
+AddTokenScreen.prototype.renderConfirmation = function () {
+ const {
+ customAddress: address,
+ customSymbol: symbol,
+ customDecimals: decimals,
+ selectedTokens,
+ } = this.state
+
+ const { addTokens, goHome } = this.props
+
+ const customToken = {
+ address,
+ symbol,
+ decimals,
+ }
+
+ const tokens = address && symbol && decimals
+ ? { ...selectedTokens, [address]: customToken }
+ : selectedTokens
+
+ return (
+ h('div.add-token', [
+ h('div.add-token__wrapper', [
+ h('div.add-token__title-container.add-token__confirmation-title', [
+ h('div.add-token__title', 'Add Token'),
+ h('div.add-token__description', 'Would you like to add these tokens?'),
+ ]),
+ h('div.add-token__content-container.add-token__confirmation-content', [
+ h('div.add-token__description.add-token__confirmation-description', 'Your balances'),
+ h('div.add-token__confirmation-token-list',
+ Object.entries(tokens)
+ .map(([ address, token ]) => (
+ h('span.add-token__confirmation-token-list-item', [
+ h(Identicon, {
+ className: 'add-token__confirmation-token-icon',
+ diameter: 75,
+ address,
+ }),
+ h(TokenBalance, { token }),
+ ])
+ ))
+ ),
+ ]),
+ ]),
+ h('div.add-token__buttons', [
+ h('button.btn-secondary', {
+ onClick: () => addTokens(tokens).then(goHome),
+ }, 'Add Tokens'),
+ h('button.btn-tertiary', {
+ onClick: () => this.setState({ isShowingConfirmation: false }),
+ }, 'Back'),
+ ]),
+ ])
+ )
+}
+
+AddTokenScreen.prototype.render = function () {
+ const { isCollapsed, errors, isShowingConfirmation } = this.state
+ const { goHome } = this.props
+
+ return isShowingConfirmation
+ ? this.renderConfirmation()
+ : (
+ h('div.add-token', [
+ h('div.add-token__wrapper', [
+ h('div.add-token__title-container', [
+ h('div.add-token__title', 'Add Token'),
+ h('div.add-token__description', 'Keep track of the tokens you’ve bought with your MetaMask account. If you bought tokens using a different account, those tokens will not appear here.'),
+ h('div.add-token__description', 'Search for tokens or select from our list of popular tokens.'),
+ ]),
+ h('div.add-token__content-container', [
+ h('div.add-token__input-container', [
+ h('input.add-token__input', {
+ type: 'text',
+ placeholder: 'Search',
+ onChange: e => this.setState({ searchQuery: e.target.value }),
+ }),
+ h('div.add-token__search-input-error-message', errors.tokenSelector),
+ ]),
+ h(
+ 'div.add-token__token-icons-container',
+ this.renderTokenList(),
+ ),
+ ]),
+ h('div.add-token__footers', [
+ h('div.add-token__add-custom', {
+ onClick: () => this.setState({ isCollapsed: !isCollapsed }),
+ }, 'Add custom token'),
+ this.renderCustomForm(),
+ ]),
+ ]),
+ h('div.add-token__buttons', [
+ h('button.btn-secondary', {
+ onClick: this.onNext,
+ }, 'Next'),
+ h('button.btn-tertiary', {
+ onClick: goHome,
+ }, 'Cancel'),
+ ]),
+ ])
+ )
+}
diff --git a/ui/app/app.js b/ui/app/app.js
index 613577913..76cf1bae1 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -2,37 +2,44 @@ const inherits = require('util').inherits
const Component = require('react').Component
const connect = require('react-redux').connect
const h = require('react-hyperscript')
+const { checkFeatureToggle } = require('../lib/feature-toggle-utils')
const actions = require('./actions')
// init
const InitializeMenuScreen = require('./first-time/init-menu')
const NewKeyChainScreen = require('./new-keychain')
-// unlock
-const UnlockScreen = require('./unlock')
// accounts
-const AccountDetailScreen = require('./account-detail')
+const MainContainer = require('./main-container')
const SendTransactionScreen = require('./send')
+const SendTransactionScreen2 = require('./components/send/send-v2-container')
+const SendTokenScreen = require('./components/send-token')
const ConfirmTxScreen = require('./conf-tx')
// notice
const NoticeScreen = require('./components/notice')
const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
+
+// slideout menu
+const WalletView = require('./components/wallet-view')
+
// other views
const ConfigScreen = require('./config')
const AddTokenScreen = require('./add-token')
const Import = require('./accounts/import')
const InfoScreen = require('./info')
const Loading = require('./components/loading')
-const SandwichExpando = require('sandwich-expando')
-const Dropdown = require('./components/dropdown').Dropdown
-const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem
const NetworkIndicator = require('./components/network')
+const Identicon = require('./components/identicon')
const BuyView = require('./components/buy-button-subview')
-const QrView = require('./components/qr-code')
const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete')
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation')
-const AccountDropdowns = require('./components/account-dropdowns').AccountDropdowns
+const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
+const NetworkDropdown = require('./components/dropdowns/network-dropdown')
+const AccountMenu = require('./components/account-menu')
-module.exports = connect(mapStateToProps)(App)
+// Global Modals
+const Modal = require('./components/modals/index').Modal
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(App)
inherits(App, Component)
function App () { Component.call(this) }
@@ -48,11 +55,14 @@ function mapStateToProps (state) {
return {
// state from plugin
+ networkDropdownOpen: state.appState.networkDropdownOpen,
+ sidebarOpen: state.appState.sidebarOpen,
isLoading: state.appState.isLoading,
loadingMessage: state.appState.loadingMessage,
noActiveNotices: state.metamask.noActiveNotices,
isInitialized: state.metamask.isInitialized,
isUnlocked: state.metamask.isUnlocked,
+ selectedAddress: state.metamask.selectedAddress,
currentView: state.appState.currentView,
activeAddress: state.appState.activeAddress,
transForward: state.appState.transForward,
@@ -74,9 +84,24 @@ function mapStateToProps (state) {
}
}
+function mapDispatchToProps (dispatch, ownProps) {
+ return {
+ dispatch,
+ hideSidebar: () => dispatch(actions.hideSidebar()),
+ showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()),
+ hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()),
+ setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
+ toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
+ }
+}
+
+App.prototype.componentWillMount = function () {
+ this.props.setCurrentCurrencyToUSD()
+}
+
App.prototype.render = function () {
var props = this.props
- const { isLoading, loadingMessage, transForward, network } = props
+ const { isLoading, loadingMessage, network } = props
const isLoadingNetwork = network === 'loading' && props.currentView.name !== 'config'
const loadMessage = loadingMessage || isLoadingNetwork ?
`Connecting to ${this.getNetworkName()}` : null
@@ -86,307 +111,166 @@ App.prototype.render = function () {
h('.flex-column.full-height', {
style: {
- // Windows was showing a vertical scroll bar:
- overflow: 'hidden',
+ overflowX: 'hidden',
position: 'relative',
alignItems: 'center',
},
}, [
+ // global modal
+ h(Modal, {}, []),
+
// app bar
this.renderAppBar(),
- this.renderNetworkDropdown(),
- this.renderDropdown(),
+
+ // sidebar
+ this.renderSidebar(),
+
+ // network dropdown
+ h(NetworkDropdown, {
+ provider: this.props.provider,
+ frequentRpcList: this.props.frequentRpcList,
+ }, []),
+
+ h(AccountMenu),
h(Loading, {
isLoading: isLoading || isLoadingNetwork,
loadingMessage: loadMessage,
}),
- // panel content
- h('.app-primary' + (transForward ? '.from-right' : '.from-left'), {
- style: {
- width: '100%',
- },
- }, [
- this.renderPrimary(),
- ]),
+ // content
+ this.renderPrimary(),
])
)
}
+App.prototype.renderGlobalModal = function () {
+ return h(Modal, {
+ ref: 'modalRef',
+ }, [
+ // h(BuyOptions, {}, []),
+ ])
+}
+
+App.prototype.renderSidebar = function () {
+
+ return h('div', {
+ }, [
+ h('style', `
+ .sidebar-enter {
+ transition: transform 300ms ease-in-out;
+ transform: translateX(-100%);
+ }
+ .sidebar-enter.sidebar-enter-active {
+ transition: transform 300ms ease-in-out;
+ transform: translateX(0%);
+ }
+ .sidebar-leave {
+ transition: transform 200ms ease-out;
+ transform: translateX(0%);
+ }
+ .sidebar-leave.sidebar-leave-active {
+ transition: transform 200ms ease-out;
+ transform: translateX(-100%);
+ }
+ `),
+
+ h(ReactCSSTransitionGroup, {
+ transitionName: 'sidebar',
+ transitionEnterTimeout: 300,
+ transitionLeaveTimeout: 200,
+ }, [
+ // A second instance of Walletview is used for non-mobile viewports
+ this.props.sidebarOpen ? h(WalletView, {
+ responsiveDisplayClassname: '.sidebar',
+ style: {},
+ }) : undefined,
+
+ ]),
+
+ // overlay
+ // TODO: add onClick for overlay to close sidebar
+ this.props.sidebarOpen ? h('div.sidebar-overlay', {
+ style: {},
+ onClick: () => {
+ this.props.hideSidebar()
+ },
+ }, []) : undefined,
+ ])
+}
+
App.prototype.renderAppBar = function () {
if (window.METAMASK_UI_TYPE === 'notification') {
return null
}
-
- const props = this.props
- const state = this.state || {}
- const isNetworkMenuOpen = state.isNetworkMenuOpen || false
-
+ console.log(this.props)
return (
h('.full-width', {
- height: '38px',
+ style: {},
}, [
h('.app-header.flex-row.flex-space-between', {
- style: {
- alignItems: 'center',
- visibility: props.isUnlocked ? 'visible' : 'none',
- background: props.isUnlocked ? 'white' : 'none',
- height: '38px',
- position: 'relative',
- zIndex: 12,
- },
+ style: {},
}, [
-
- h('div.left-menu-section', {
- style: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- },
- }, [
-
- // mini logo
- h('img', {
- height: 24,
- width: 24,
- src: '/images/icon-128.png',
- }),
-
- h(NetworkIndicator, {
- network: this.props.network,
- provider: this.props.provider,
- onClick: (event) => {
- event.preventDefault()
- event.stopPropagation()
- this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen })
- },
- }),
- ]),
-
- props.isUnlocked && h('div', {
- style: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- },
- }, [
-
- props.isUnlocked && h(AccountDropdowns, {
+ h('div.app-header-contents', {}, [
+ h('div.left-menu-wrapper', {
style: {},
- enableAccountsSelector: true,
- identities: this.props.identities,
- selected: this.props.currentView.context,
- network: this.props.network,
- keyrings: this.props.keyrings,
- }, []),
+ }, [
+ // mini logo
+ h('img', {
+ height: 24,
+ width: 24,
+ src: '/images/icon-128.png',
+ }),
- // hamburger
- props.isUnlocked && h(SandwichExpando, {
- className: 'sandwich-expando',
- width: 16,
- barHeight: 2,
- padding: 0,
- isOpen: state.isMainMenuOpen,
- color: 'rgb(247,146,30)',
- onClick: () => {
- this.setState({
- isMainMenuOpen: !state.isMainMenuOpen,
- })
- },
- }),
+ // metamask name
+ h('h1', {
+ style: {
+ position: 'relative',
+ paddingLeft: '9px',
+ color: '#5B5D67',
+ },
+ }, 'MetaMask'),
+
+ ]),
+
+ h('div.header__right-actions', [
+ h('div.network-component-wrapper', {
+ style: {},
+ }, [
+ // Network Indicator
+ h(NetworkIndicator, {
+ network: this.props.network,
+ provider: this.props.provider,
+ onClick: (event) => {
+ event.preventDefault()
+ event.stopPropagation()
+ if (this.props.networkDropdownOpen === false) {
+ this.props.showNetworkDropdown()
+ } else {
+ this.props.hideNetworkDropdown()
+ }
+ },
+ }),
+
+ ]),
+
+ h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
+ h(Identicon, {
+ address: this.props.selectedAddress,
+ diameter: 32,
+ }),
+ ]),
+ ]),
]),
]),
+
])
)
}
-App.prototype.renderNetworkDropdown = function () {
- const props = this.props
- const { provider: { type: providerType, rpcTarget: activeNetwork } } = props
- const rpcList = props.frequentRpcList
- const state = this.state || {}
- const isOpen = state.isNetworkMenuOpen
-
- return h(Dropdown, {
- useCssTransition: true,
- isOpen,
- onClickOutside: (event) => {
- const { classList } = event.target
- const isNotToggleElement = [
- classList.contains('menu-icon'),
- classList.contains('network-name'),
- classList.contains('network-indicator'),
- ].filter(bool => bool).length === 0
- // classes from three constituent nodes of the toggle element
-
- if (isNotToggleElement) {
- this.setState({ isNetworkMenuOpen: false })
- }
- },
- zIndex: 11,
- style: {
- position: 'absolute',
- left: '2px',
- top: '36px',
- },
- innerStyle: {
- padding: '2px 16px 2px 0px',
- },
- }, [
-
- h(
- DropdownMenuItem,
- {
- key: 'main',
- closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
- onClick: () => props.dispatch(actions.setProviderType('mainnet')),
- style: {
- fontSize: '18px',
- },
- },
- [
- h('.menu-icon.diamond'),
- 'Main Ethereum Network',
- providerType === 'mainnet' ? h('.check', '✓') : null,
- ]
- ),
-
- h(
- DropdownMenuItem,
- {
- key: 'ropsten',
- closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
- onClick: () => props.dispatch(actions.setProviderType('ropsten')),
- style: {
- fontSize: '18px',
- },
- },
- [
- h('.menu-icon.red-dot'),
- 'Ropsten Test Network',
- providerType === 'ropsten' ? h('.check', '✓') : null,
- ]
- ),
-
- h(
- DropdownMenuItem,
- {
- key: 'kovan',
- closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
- onClick: () => props.dispatch(actions.setProviderType('kovan')),
- style: {
- fontSize: '18px',
- },
- },
- [
- h('.menu-icon.hollow-diamond'),
- 'Kovan Test Network',
- providerType === 'kovan' ? h('.check', '✓') : null,
- ]
- ),
-
- h(
- DropdownMenuItem,
- {
- key: 'rinkeby',
- closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
- onClick: () => props.dispatch(actions.setProviderType('rinkeby')),
- style: {
- fontSize: '18px',
- },
- },
- [
- h('.menu-icon.golden-square'),
- 'Rinkeby Test Network',
- providerType === 'rinkeby' ? h('.check', '✓') : null,
- ]
- ),
-
- h(
- DropdownMenuItem,
- {
- key: 'default',
- closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
- onClick: () => props.dispatch(actions.setProviderType('localhost')),
- style: {
- fontSize: '18px',
- },
- },
- [
- h('i.fa.fa-question-circle.fa-lg.menu-icon'),
- 'Localhost 8545',
- activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null,
- ]
- ),
-
- this.renderCustomOption(props.provider),
- this.renderCommonRpc(rpcList, props.provider),
-
- h(
- DropdownMenuItem,
- {
- closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
- onClick: () => this.props.dispatch(actions.showConfigPage()),
- style: {
- fontSize: '18px',
- },
- },
- [
- h('i.fa.fa-question-circle.fa-lg.menu-icon'),
- 'Custom RPC',
- activeNetwork === 'custom' ? h('.check', '✓') : null,
- ]
- ),
-
- ])
-}
-
-App.prototype.renderDropdown = function () {
- const state = this.state || {}
- const isOpen = state.isMainMenuOpen
-
- return h(Dropdown, {
- useCssTransition: true,
- isOpen: isOpen,
- zIndex: 11,
- onClickOutside: (event) => {
- const classList = event.target.classList
- const parentClassList = event.target.parentElement.classList
-
- const isToggleElement = classList.contains('sandwich-expando') ||
- parentClassList.contains('sandwich-expando')
-
- if (isOpen && !isToggleElement) {
- this.setState({ isMainMenuOpen: false })
- }
- },
- style: {
- position: 'absolute',
- right: '2px',
- top: '38px',
- },
- innerStyle: {},
- }, [
- h(DropdownMenuItem, {
- closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- onClick: () => { this.props.dispatch(actions.showConfigPage()) },
- }, 'Settings'),
-
- h(DropdownMenuItem, {
- closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- onClick: () => { this.props.dispatch(actions.lockMetamask()) },
- }, 'Lock'),
-
- h(DropdownMenuItem, {
- closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }),
- onClick: () => { this.props.dispatch(actions.showInfoPage()) },
- }, 'Info/Help'),
- ])
-}
App.prototype.renderBackButton = function (style, justArrow = false) {
var props = this.props
@@ -451,32 +335,38 @@ App.prototype.renderPrimary = function () {
// show unlock screen
if (!props.isUnlocked) {
- switch (props.currentView.name) {
-
- case 'restoreVault':
- log.debug('rendering restore vault screen')
- return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'})
-
- case 'config':
- log.debug('rendering config screen from unlock screen.')
- return h(ConfigScreen, {key: 'config'})
-
- default:
- log.debug('rendering locked screen')
- return h(UnlockScreen, {key: 'locked'})
- }
+ return h(MainContainer, {
+ currentViewName: props.currentView.name,
+ isUnlocked: props.isUnlocked,
+ })
}
// show current view
switch (props.currentView.name) {
case 'accountDetail':
- log.debug('rendering account detail screen')
- return h(AccountDetailScreen, {key: 'account-detail'})
+ log.debug('rendering main container')
+ return h(MainContainer, {key: 'account-detail'})
case 'sendTransaction':
log.debug('rendering send tx screen')
- return h(SendTransactionScreen, {key: 'send-transaction'})
+
+ // Going to leave this here until we are ready to delete SendTransactionScreen v1
+ // const SendComponentToRender = checkFeatureToggle('send-v2')
+ // ? SendTransactionScreen2
+ // : SendTransactionScreen
+
+ return h(SendTransactionScreen2, {key: 'send-transaction'})
+
+ case 'sendToken':
+ log.debug('rendering send token screen')
+
+ // Going to leave this here until we are ready to delete SendTransactionScreen v1
+ // const SendTokenComponentToRender = checkFeatureToggle('send-v2')
+ // ? SendTransactionScreen2
+ // : SendTokenScreen
+
+ return h(SendTransactionScreen2, {key: 'sendToken'})
case 'newKeychain':
log.debug('rendering new keychain screen')
@@ -510,37 +400,9 @@ App.prototype.renderPrimary = function () {
log.debug('rendering buy ether screen')
return h(BuyView, {key: 'buyEthView'})
- case 'qr':
- log.debug('rendering show qr screen')
- return h('div', {
- style: {
- position: 'absolute',
- height: '100%',
- top: '0px',
- left: '0px',
- },
- }, [
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
- onClick: () => props.dispatch(actions.backToAccountDetail(props.activeAddress)),
- style: {
- marginLeft: '10px',
- marginTop: '50px',
- },
- }),
- h('div', {
- style: {
- position: 'absolute',
- left: '44px',
- width: '285px',
- },
- }, [
- h(QrView, {key: 'qr'}),
- ]),
- ])
-
default:
log.debug('rendering default, account detail screen')
- return h(AccountDetailScreen, {key: 'account-detail'})
+ return h(MainContainer, {key: 'account-detail'})
}
}
@@ -556,40 +418,6 @@ App.prototype.toggleMetamaskActive = function () {
}
}
-App.prototype.renderCustomOption = function (provider) {
- const { rpcTarget, type } = provider
- const props = this.props
-
- if (type !== 'rpc') return null
-
- // Concatenate long URLs
- let label = rpcTarget
- if (rpcTarget.length > 31) {
- label = label.substr(0, 34) + '...'
- }
-
- switch (rpcTarget) {
-
- case 'http://localhost:8545':
- return null
-
- default:
- return h(
- DropdownMenuItem,
- {
- key: rpcTarget,
- onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)),
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- },
- [
- h('i.fa.fa-question-circle.fa-lg.menu-icon'),
- label,
- h('.check', '✓'),
- ]
- )
- }
-}
-
App.prototype.getNetworkName = function () {
const { provider } = this.props
const providerName = provider.type
@@ -610,28 +438,3 @@ App.prototype.getNetworkName = function () {
return name
}
-
-App.prototype.renderCommonRpc = function (rpcList, provider) {
- const props = this.props
- const rpcTarget = provider.rpcTarget
-
- return rpcList.map((rpc) => {
- if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) {
- return null
- } else {
- return h(
- DropdownMenuItem,
- {
- key: `common${rpc}`,
- closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
- onClick: () => props.dispatch(actions.setRpcTarget(rpc)),
- },
- [
- h('i.fa.fa-question-circle.fa-lg.menu-icon'),
- rpc,
- rpcTarget === rpc ? h('.check', '✓') : null,
- ]
- )
- }
- })
-}
diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js
new file mode 100644
index 000000000..2ebdba24a
--- /dev/null
+++ b/ui/app/components/account-menu/index.js
@@ -0,0 +1,154 @@
+const inherits = require('util').inherits
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const actions = require('../../actions')
+const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
+const Identicon = require('../identicon')
+const { formatBalance } = require('../../util')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountMenu)
+
+inherits(AccountMenu, Component)
+function AccountMenu () { Component.call(this) }
+
+function mapStateToProps (state) {
+ return {
+ selectedAddress: state.metamask.selectedAddress,
+ isAccountMenuOpen: state.metamask.isAccountMenuOpen,
+ keyrings: state.metamask.keyrings,
+ identities: state.metamask.identities,
+ accounts: state.metamask.accounts,
+
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
+ showAccountDetail: address => {
+ dispatch(actions.showAccountDetail(address))
+ dispatch(actions.toggleAccountMenu())
+ },
+ lockMetamask: () => {
+ dispatch(actions.lockMetamask())
+ dispatch(actions.toggleAccountMenu())
+ },
+ showConfigPage: () => {
+ console.log('hihihih')
+ dispatch(actions.showConfigPage())
+ dispatch(actions.toggleAccountMenu())
+ },
+ showNewAccountModal: () => {
+ dispatch(actions.showModal({ name: 'NEW_ACCOUNT' }))
+ dispatch(actions.toggleAccountMenu())
+ },
+ showImportPage: () => {
+ dispatch(actions.showImportPage())
+ dispatch(actions.toggleAccountMenu())
+ },
+ }
+}
+
+AccountMenu.prototype.render = function () {
+ const {
+ isAccountMenuOpen,
+ toggleAccountMenu,
+ showNewAccountModal,
+ showImportPage,
+ lockMetamask,
+ showConfigPage,
+ } = this.props
+
+ console.log(showConfigPage)
+ return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [
+ h(CloseArea, { onClick: toggleAccountMenu }),
+ h(Item, {
+ className: 'account-menu__header',
+ onClick: lockMetamask,
+ }, [
+ 'My Accounts',
+ h('button.account-menu__logout-button', 'Log out'),
+ ]),
+ h(Divider),
+ h('div.account-menu__accounts', this.renderAccounts()),
+ h(Divider),
+ h(Item, {
+ onClick: showNewAccountModal,
+ icon: h('img', { src: 'images/plus-btn-white.svg' }),
+ text: 'Create Account',
+ }),
+ h(Item, {
+ onClick: showImportPage,
+ icon: h('img', { src: 'images/import-account.svg' }),
+ text: 'Import Account',
+ }),
+ h(Divider),
+ h(Item, {
+ icon: h('img', { src: 'images/mm-info-icon.svg' }),
+ text: 'Info & Help',
+ }),
+ h(Item, {
+ onClick: showConfigPage,
+ icon: h('img', { src: 'images/settings.svg' }),
+ text: 'Settings',
+ }),
+ ])
+}
+
+AccountMenu.prototype.renderAccounts = function () {
+ const {
+ identities,
+ accounts,
+ selected,
+ keyrings,
+ showAccountDetail,
+ } = this.props
+
+ return Object.keys(identities).map((key, index) => {
+ const identity = identities[key]
+ const isSelected = identity.address === selected
+
+ const balanceValue = accounts[key].balance
+ const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
+ const simpleAddress = identity.address.substring(2).toLowerCase()
+
+ const keyring = keyrings.find((kr) => {
+ return kr.accounts.includes(simpleAddress) ||
+ kr.accounts.includes(identity.address)
+ })
+
+ return h(
+ 'div.account-menu__account.menu__item--clickable',
+ { onClick: () => showAccountDetail(identity.address) },
+ [
+ h('div.account-menu__check-mark', [
+ isSelected ? h('i.fa.fa-check') : null,
+ ]),
+
+ h(
+ Identicon,
+ {
+ address: identity.address,
+ diameter: 24,
+ },
+ ),
+
+ h('div.account-menu__account-info', [
+ h('div.account-menu__name', identity.name || ''),
+ h('div.account-menu__balance', formattedBalance),
+ ]),
+
+ this.indicateIfLoose(keyring),
+ ],
+ )
+ })
+}
+
+AccountMenu.prototype.indicateIfLoose = function (keyring) {
+ try { // Sometimes keyrings aren't loaded yet:
+ const type = keyring.type
+ const isLoose = type !== 'HD Key Tree'
+ return isLoose ? h('.keyring-label', 'LOOSE') : null
+ } catch (e) { return }
+}
diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js
new file mode 100644
index 000000000..d14aa675f
--- /dev/null
+++ b/ui/app/components/balance-component.js
@@ -0,0 +1,120 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const TokenBalance = require('./token-balance')
+const Identicon = require('./identicon')
+
+const { formatBalance, generateBalanceObject } = require('../util')
+
+module.exports = connect(mapStateToProps)(BalanceComponent)
+
+function mapStateToProps (state) {
+ const accounts = state.metamask.accounts
+ const network = state.metamask.network
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ const account = accounts[selectedAddress]
+
+ return {
+ account,
+ network,
+ conversionRate: state.metamask.conversionRate,
+ currentCurrency: state.metamask.currentCurrency,
+ }
+}
+
+inherits(BalanceComponent, Component)
+function BalanceComponent () {
+ Component.call(this)
+}
+
+BalanceComponent.prototype.render = function () {
+ const props = this.props
+ const { token, network } = props
+
+ return h('div.balance-container', {}, [
+
+ // TODO: balance icon needs to be passed in
+ // h('img.balance-icon', {
+ // src: '../images/eth_logo.svg',
+ // style: {},
+ // }),
+ h(Identicon, {
+ diameter: 45,
+ address: token && token.address,
+ network,
+ }),
+
+ token ? this.renderTokenBalance() : this.renderBalance(),
+ ])
+}
+
+BalanceComponent.prototype.renderTokenBalance = function () {
+ const { token } = this.props
+
+ return h('div.flex-column.balance-display', [
+ h('div.token-amount', [ h(TokenBalance, { token }) ]),
+ ])
+}
+
+BalanceComponent.prototype.renderBalance = function () {
+ const props = this.props
+ const { shorten, account } = props
+ const balanceValue = account && account.balance
+ const needsParse = 'needsParse' in props ? props.needsParse : true
+ const formattedBalance = balanceValue ? formatBalance(balanceValue, 6, needsParse) : '...'
+ const showFiat = 'showFiat' in props ? props.showFiat : true
+
+ if (formattedBalance === 'None' || formattedBalance === '...') {
+ return h('div.flex-column.balance-display', {}, [
+ h('div.token-amount', {
+ style: {},
+ }, formattedBalance),
+ ])
+ }
+
+ return h('div.flex-column.balance-display', {}, [
+ h('div.token-amount', {
+ style: {},
+ }, this.getTokenBalance(formattedBalance, shorten)),
+
+ showFiat ? this.renderFiatValue(formattedBalance) : null,
+ ])
+}
+
+BalanceComponent.prototype.renderFiatValue = function (formattedBalance) {
+
+ const { conversionRate, currentCurrency } = this.props
+
+ const fiatDisplayNumber = this.getFiatDisplayNumber(formattedBalance, conversionRate)
+
+ const fiatPrefix = currentCurrency === 'USD' ? '$' : ''
+
+ return this.renderFiatAmount(fiatDisplayNumber, currentCurrency, fiatPrefix)
+}
+
+BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix, fiatPrefix) {
+ if (fiatDisplayNumber === 'N/A') return null
+
+ return h('div.fiat-amount', {
+ style: {},
+ }, `${fiatPrefix}${fiatDisplayNumber} ${fiatSuffix}`)
+}
+
+BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) {
+ const balanceObj = generateBalanceObject(formattedBalance, shorten ? 1 : 3)
+
+ const balanceValue = shorten ? balanceObj.shortBalance : balanceObj.balance
+ const label = balanceObj.label
+
+ return `${balanceValue} ${label}`
+}
+
+BalanceComponent.prototype.getFiatDisplayNumber = function (formattedBalance, conversionRate) {
+ if (formattedBalance === 'None') return formattedBalance
+ if (conversionRate === 0) return 'N/A'
+
+ const splitBalance = formattedBalance.split(' ')
+
+ return (Number(splitBalance[0]) * conversionRate).toFixed(2)
+}
diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js
index 15281171c..6cf6e9eb9 100644
--- a/ui/app/components/buy-button-subview.js
+++ b/ui/app/components/buy-button-subview.js
@@ -245,7 +245,7 @@ BuyButtonSubview.prototype.navigateTo = function (url) {
BuyButtonSubview.prototype.backButtonContext = function () {
if (this.props.context === 'confTx') {
- this.props.dispatch(actions.showConfTxPage(false))
+ this.props.dispatch(actions.showConfTxPage({transForward: false}))
} else {
this.props.dispatch(actions.goHome())
}
diff --git a/ui/app/components/customize-gas-modal/gas-modal-card.js b/ui/app/components/customize-gas-modal/gas-modal-card.js
new file mode 100644
index 000000000..8e739ee40
--- /dev/null
+++ b/ui/app/components/customize-gas-modal/gas-modal-card.js
@@ -0,0 +1,55 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const InputNumber = require('../input-number.js')
+const GasSlider = require('./gas-slider.js')
+
+module.exports = GasModalCard
+
+inherits(GasModalCard, Component)
+function GasModalCard () {
+ Component.call(this)
+}
+
+GasModalCard.prototype.render = function () {
+ const {
+ memo,
+ identities,
+ onChange,
+ unitLabel,
+ value,
+ min,
+ max,
+ step,
+ title,
+ copy
+ } = this.props
+
+ return h('div.send-v2__gas-modal-card', [
+
+ h('div.send-v2__gas-modal-card__title', {}, title),
+
+ h('div.send-v2__gas-modal-card__copy', {}, copy),
+
+ h(InputNumber, {
+ unitLabel,
+ step,
+ max,
+ min,
+ placeholder: '0',
+ value,
+ onChange,
+ }),
+
+ h(GasSlider, {
+ value,
+ step,
+ max,
+ min,
+ onChange,
+ }),
+
+ ])
+
+}
+
diff --git a/ui/app/components/customize-gas-modal/gas-slider.js b/ui/app/components/customize-gas-modal/gas-slider.js
new file mode 100644
index 000000000..e76e96545
--- /dev/null
+++ b/ui/app/components/customize-gas-modal/gas-slider.js
@@ -0,0 +1,50 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = GasSlider
+
+inherits(GasSlider, Component)
+function GasSlider () {
+ Component.call(this)
+}
+
+GasSlider.prototype.render = function () {
+ const {
+ memo,
+ identities,
+ onChange,
+ unitLabel,
+ value,
+ id,
+ step,
+ max,
+ min,
+ } = this.props
+
+ return h('div.gas-slider', [
+
+ h('input.gas-slider__input', {
+ type: 'range',
+ step,
+ max,
+ min,
+ value,
+ id: 'gasSlider',
+ onChange: event => onChange(event.target.value),
+ }, []),
+
+ h('div.gas-slider__bar', [
+
+ h('div.gas-slider__low'),
+
+ h('div.gas-slider__mid'),
+
+ h('div.gas-slider__high'),
+
+ ]),
+
+ ])
+
+}
+
diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js
new file mode 100644
index 000000000..0ba768893
--- /dev/null
+++ b/ui/app/components/customize-gas-modal/index.js
@@ -0,0 +1,158 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const GasModalCard = require('./gas-modal-card')
+
+const { conversionUtil, multiplyCurrencies } = require('../../conversion-util')
+
+const {
+ getGasPrice,
+ getGasLimit,
+ conversionRateSelector,
+} = require('../../selectors')
+
+function mapStateToProps (state) {
+ return {
+ gasPrice: getGasPrice(state),
+ gasLimit: getGasLimit(state),
+ conversionRate: conversionRateSelector(state),
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => dispatch(actions.hideModal()),
+ updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)),
+ updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)),
+ updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)),
+ }
+}
+
+inherits(CustomizeGasModal, Component)
+function CustomizeGasModal (props) {
+ Component.call(this)
+
+ this.state = {
+ gasPrice: props.gasPrice,
+ gasLimit: props.gasLimit,
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(CustomizeGasModal)
+
+CustomizeGasModal.prototype.save = function (gasPrice, gasLimit) {
+ const {
+ updateGasPrice,
+ updateGasLimit,
+ hideModal,
+ updateGasTotal
+ } = this.props
+
+ const newGasTotal = multiplyCurrencies(gasLimit, gasPrice, {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ })
+
+ updateGasPrice(gasPrice)
+ updateGasLimit(gasLimit)
+ updateGasTotal(newGasTotal)
+ hideModal()
+}
+
+CustomizeGasModal.prototype.convertAndSetGasLimit = function (newGasLimit) {
+ const convertedGasLimit = conversionUtil(newGasLimit, {
+ fromNumericBase: 'dec',
+ toNumericBase: 'hex',
+ })
+
+ this.setState({ gasLimit: convertedGasLimit })
+}
+
+CustomizeGasModal.prototype.convertAndSetGasPrice = function (newGasPrice) {
+ const convertedGasPrice = conversionUtil(newGasPrice, {
+ fromNumericBase: 'dec',
+ toNumericBase: 'hex',
+ fromDenomination: 'GWEI',
+ toDenomination: 'WEI',
+ })
+
+ this.setState({ gasPrice: convertedGasPrice })
+}
+
+CustomizeGasModal.prototype.render = function () {
+ const { hideModal, conversionRate } = this.props
+ const { gasPrice, gasLimit } = this.state
+
+ const convertedGasPrice = conversionUtil(gasPrice, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ toDenomination: 'GWEI',
+ })
+
+ const convertedGasLimit = conversionUtil(gasLimit, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ })
+
+ return h('div.send-v2__customize-gas', {}, [
+ h('div', {
+ }, [
+ h('div.send-v2__customize-gas__header', {}, [
+
+ h('div.send-v2__customize-gas__title', 'Customize Gas'),
+
+ h('div.send-v2__customize-gas__close', {
+ onClick: hideModal,
+ }),
+
+ ]),
+
+ h('div.send-v2__customize-gas__body', {}, [
+
+ h(GasModalCard, {
+ value: convertedGasPrice,
+ min: 0,
+ max: 1000,
+ step: 1,
+ onChange: value => this.convertAndSetGasPrice(value),
+ title: 'Gas Price',
+ copy: 'We calculate the suggested gas prices based on network success rates.',
+ }),
+
+ h(GasModalCard, {
+ value: convertedGasLimit,
+ min: 20000,
+ max: 100000,
+ step: 1,
+ onChange: value => this.convertAndSetGasLimit(value),
+ title: 'Gas Limit',
+ copy: 'We calculate the suggested gas limit based on network success rates.',
+ }),
+
+ ]),
+
+ h('div.send-v2__customize-gas__footer', {}, [
+
+ h('div.send-v2__customize-gas__revert', {
+ onClick: () => console.log('Revert'),
+ }, ['Revert']),
+
+ h('div.send-v2__customize-gas__buttons', [
+ h('div.send-v2__customize-gas__cancel', {
+ onClick: this.props.hideModal,
+ }, ['CANCEL']),
+
+ h('div.send-v2__customize-gas__save', {
+ onClick: () => this.save(gasPrice, gasLimit),
+ }, ['SAVE']),
+ ])
+
+ ]),
+
+ ]),
+ ])
+}
diff --git a/ui/app/components/dropdowns/account-options-dropdown.js b/ui/app/components/dropdowns/account-options-dropdown.js
new file mode 100644
index 000000000..50e793d87
--- /dev/null
+++ b/ui/app/components/dropdowns/account-options-dropdown.js
@@ -0,0 +1,29 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const AccountDropdowns = require('./components/account-dropdowns')
+
+inherits(AccountOptionsDropdown, Component)
+function AccountOptionsDropdown () {
+ Component.call(this)
+}
+
+module.exports = AccountOptionsDropdown
+
+// TODO: specify default props and proptypes
+// TODO: hook up to state, connect to redux to clean up API
+// TODO: selectedAddress is not defined... should we use selected?
+AccountOptionsDropdown.prototype.render = function () {
+ const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props
+
+ return h(AccountDropdowns, {
+ enableAccountOptions: true,
+ enableAccountsSelector: false,
+ selected: selectedAddress,
+ network,
+ identities,
+ style: style || {},
+ dropdownWrapperStyle: dropdownWrapperStyle || {},
+ menuItemStyles: menuItemStyles || {},
+ }, [])
+}
diff --git a/ui/app/components/dropdowns/account-selection-dropdown.js b/ui/app/components/dropdowns/account-selection-dropdown.js
new file mode 100644
index 000000000..7a8502d18
--- /dev/null
+++ b/ui/app/components/dropdowns/account-selection-dropdown.js
@@ -0,0 +1,29 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const AccountDropdowns = require('./components/account-dropdowns')
+
+inherits(AccountSelectionDropdown, Component)
+function AccountSelectionDropdown () {
+ Component.call(this)
+}
+
+module.exports = AccountSelectionDropdown
+
+// TODO: specify default props and proptypes
+// TODO: hook up to state, connect to redux to clean up API
+// TODO: selectedAddress is not defined... should we use selected?
+AccountSelectionDropdown.prototype.render = function () {
+ const { selected, network, identities, style, dropdownWrapperStyle, menuItemStyles } = this.props
+
+ return h(AccountDropdowns, {
+ enableAccountOptions: false,
+ enableAccountsSelector: true,
+ selected: selectedAddress,
+ network,
+ identities,
+ style: style || {},
+ dropdownWrapperStyle: dropdownWrapperStyle || {},
+ menuItemStyles: menuItemStyles || {},
+ }, [])
+}
diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js
new file mode 100644
index 000000000..e2eed1e4b
--- /dev/null
+++ b/ui/app/components/dropdowns/components/account-dropdowns.js
@@ -0,0 +1,469 @@
+const Component = require('react').Component
+const PropTypes = require('react').PropTypes
+const h = require('react-hyperscript')
+const actions = require('../../../actions')
+const genAccountLink = require('../../../../lib/account-link.js')
+const connect = require('react-redux').connect
+const Dropdown = require('./dropdown').Dropdown
+const DropdownMenuItem = require('./dropdown').DropdownMenuItem
+const Identicon = require('../../identicon')
+const ethUtil = require('ethereumjs-util')
+const copyToClipboard = require('copy-to-clipboard')
+const { formatBalance } = require('../../../util')
+
+class AccountDropdowns extends Component {
+ constructor (props) {
+ super(props)
+ this.state = {
+ accountSelectorActive: false,
+ optionsMenuActive: false,
+ }
+ // Used for orangeaccount selector icon
+ // this.accountSelectorToggleClassName = 'accounts-selector'
+ this.accountSelectorToggleClassName = 'fa-angle-down'
+ this.optionsMenuToggleClassName = 'fa-ellipsis-h'
+ }
+
+ renderAccounts () {
+ const { identities, accounts, selected, menuItemStyles, actions, keyrings } = this.props
+
+ return Object.keys(identities).map((key, index) => {
+ const identity = identities[key]
+ const isSelected = identity.address === selected
+
+ const balanceValue = accounts[key].balance
+ const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
+ const simpleAddress = identity.address.substring(2).toLowerCase()
+
+ const keyring = keyrings.find((kr) => {
+ return kr.accounts.includes(simpleAddress) ||
+ kr.accounts.includes(identity.address)
+ })
+
+ return h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ this.props.actions.showAccountDetail(identity.address)
+ },
+ style: Object.assign(
+ {
+ marginTop: index === 0 ? '5px' : '',
+ fontSize: '24px',
+ width: '260px',
+ },
+ menuItemStyles,
+ ),
+ },
+ [
+ h('div.flex-row.flex-center', {}, [
+
+ h('span', {
+ style: {
+ flex: '1 1 0',
+ minWidth: '20px',
+ minHeight: '30px',
+ },
+ }, [
+ h('span', {
+ style: {
+ flex: '1 1 auto',
+ fontSize: '14px',
+ },
+ }, isSelected ? h('i.fa.fa-check') : null),
+ ]),
+
+ h(
+ Identicon,
+ {
+ address: identity.address,
+ diameter: 24,
+ style: {
+ flex: '1 1 auto',
+ marginLeft: '10px',
+ },
+ },
+ ),
+
+ h('span.flex-column', {
+ style: {
+ flex: '10 10 auto',
+ width: '175px',
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+ marginLeft: '10px',
+ position: 'relative',
+ },
+ }, [
+ this.indicateIfLoose(keyring),
+ h('span.account-dropdown-name', {
+ style: {
+ fontSize: '18px',
+ maxWidth: '145px',
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ },
+ }, identity.name || ''),
+
+ h('span.account-dropdown-balance', {
+ style: {
+ fontSize: '14px',
+ fontFamily: 'Avenir',
+ fontWeight: 500,
+ },
+ }, formattedBalance),
+ ]),
+
+ h('span', {
+ style: {
+ flex: '3 3 auto',
+ },
+ }, [
+ h('span.account-dropdown-edit-button', {
+ style: {
+ fontSize: '16px',
+ },
+ onClick: () => {
+ actions.showEditAccountModal(identity)
+ },
+ }, [
+ 'Edit',
+ ]),
+ ]),
+
+ ]),
+// =======
+// },
+// ),
+// this.indicateIfLoose(keyring),
+// h('span', {
+// style: {
+// marginLeft: '20px',
+// fontSize: '24px',
+// maxWidth: '145px',
+// whiteSpace: 'nowrap',
+// overflow: 'hidden',
+// textOverflow: 'ellipsis',
+// },
+// }, identity.name || ''),
+// h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null),
+// >>>>>>> master:ui/app/components/account-dropdowns.js
+ ]
+ )
+ })
+ }
+
+ indicateIfLoose (keyring) {
+ try { // Sometimes keyrings aren't loaded yet:
+ const type = keyring.type
+ const isLoose = type !== 'HD Key Tree'
+ return isLoose ? h('.keyring-label', 'LOOSE') : null
+ } catch (e) { return }
+ }
+
+ renderAccountSelector () {
+ const { actions, useCssTransition, innerStyle, sidebarOpen } = this.props
+ const { accountSelectorActive, menuItemStyles } = this.state
+
+ return h(
+ Dropdown,
+ {
+ useCssTransition,
+ style: {
+ marginLeft: '-185px',
+ marginTop: '50px',
+ minWidth: '180px',
+ overflowY: 'auto',
+ maxHeight: '300px',
+ width: '300px',
+ },
+ innerStyle,
+ isOpen: accountSelectorActive,
+ onClickOutside: (event) => {
+ const { classList } = event.target
+ const isNotToggleElement = !classList.contains(this.accountSelectorToggleClassName)
+ if (accountSelectorActive && isNotToggleElement) {
+ this.setState({ accountSelectorActive: false })
+ }
+ },
+ },
+ [
+ ...this.renderAccounts(),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ style: Object.assign(
+ {},
+ menuItemStyles,
+ ),
+ onClick: () => actions.showNewAccountModal(),
+ },
+ [
+ h(
+ 'i.fa.fa-plus.fa-lg',
+ {
+ style: {
+ marginLeft: '8px',
+ },
+ }
+ ),
+ h('span', {
+ style: {
+ marginLeft: '14px',
+ fontFamily: 'DIN OT',
+ fontSize: '16px',
+ lineHeight: '23px',
+ },
+ }, 'Create Account'),
+ ],
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {
+ if (sidebarOpen) {
+ actions.hideSidebar()
+ }
+ },
+ onClick: () => actions.showImportPage(),
+ style: Object.assign(
+ {},
+ menuItemStyles,
+ ),
+ },
+ [
+ h(
+ 'i.fa.fa-download.fa-lg',
+ {
+ style: {
+ marginLeft: '8px',
+ },
+ }
+ ),
+ h('span', {
+ style: {
+ marginLeft: '20px',
+ marginBottom: '5px',
+ fontFamily: 'DIN OT',
+ fontSize: '16px',
+ lineHeight: '23px',
+ },
+ }, 'Import Account'),
+ ]
+ ),
+ ]
+ )
+ }
+
+ renderAccountOptions () {
+ const { actions, dropdownWrapperStyle, useCssTransition } = this.props
+ const { optionsMenuActive, menuItemStyles } = this.state
+ const dropdownMenuItemStyle = {
+ fontFamily: 'DIN OT',
+ fontSize: 16,
+ lineHeight: '24px',
+ padding: '8px',
+ }
+
+ return h(
+ Dropdown,
+ {
+ useCssTransition,
+ style: Object.assign(
+ {
+ marginLeft: '-10px',
+ position: 'absolute',
+ width: '29vh', // affects both mobile and laptop views
+ },
+ dropdownWrapperStyle,
+ ),
+ isOpen: optionsMenuActive,
+ onClickOutside: () => {
+ const { classList } = event.target
+ const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName)
+ if (optionsMenuActive && isNotToggleElement) {
+ this.setState({ optionsMenuActive: false })
+ }
+ },
+ },
+ [
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ this.props.actions.showAccountDetailModal()
+ },
+ style: Object.assign(
+ dropdownMenuItemStyle,
+ menuItemStyles,
+ ),
+ },
+ 'Account Details',
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ const { selected, network } = this.props
+ const url = genAccountLink(selected, network)
+ global.platform.openWindow({ url })
+ },
+ style: Object.assign(
+ dropdownMenuItemStyle,
+ menuItemStyles,
+ ),
+ },
+ 'View account on Etherscan',
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ const { selected } = this.props
+ const checkSumAddress = selected && ethUtil.toChecksumAddress(selected)
+ copyToClipboard(checkSumAddress)
+ },
+ style: Object.assign(
+ dropdownMenuItemStyle,
+ menuItemStyles,
+ ),
+ },
+ 'Copy Address to clipboard',
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => this.props.actions.showExportPrivateKeyModal(),
+ style: Object.assign(
+ dropdownMenuItemStyle,
+ menuItemStyles,
+ ),
+ },
+ 'Export Private Key',
+ ),
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => {},
+ onClick: () => {
+ actions.hideSidebar()
+ actions.showAddTokenPage()
+ },
+ style: Object.assign(
+ dropdownMenuItemStyle,
+ menuItemStyles,
+ ),
+ },
+ 'Add Token',
+ ),
+
+ ]
+ )
+ }
+
+ render () {
+ const { style, enableAccountsSelector, enableAccountOptions } = this.props
+ const { optionsMenuActive, accountSelectorActive } = this.state
+
+ return h(
+ 'span',
+ {
+ style: style,
+ },
+ [
+ enableAccountsSelector && h(
+ 'i.fa.fa-angle-down',
+ {
+ style: {
+ cursor: 'pointer',
+ },
+ onClick: (event) => {
+ event.stopPropagation()
+ this.setState({
+ accountSelectorActive: !accountSelectorActive,
+ optionsMenuActive: false,
+ })
+ },
+ },
+ this.renderAccountSelector(),
+ ),
+ enableAccountOptions && h(
+ 'i.fa.fa-ellipsis-h',
+ {
+ style: {
+ fontSize: '135%',
+ cursor: 'pointer',
+ },
+ onClick: (event) => {
+ event.stopPropagation()
+ this.setState({
+ accountSelectorActive: false,
+ optionsMenuActive: !optionsMenuActive,
+ })
+ },
+ },
+ this.renderAccountOptions()
+ ),
+ ]
+ )
+ }
+}
+
+AccountDropdowns.defaultProps = {
+ enableAccountsSelector: false,
+ enableAccountOptions: false,
+}
+
+AccountDropdowns.propTypes = {
+ identities: PropTypes.objectOf(PropTypes.object),
+ selected: PropTypes.string,
+ keyrings: PropTypes.array,
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ actions: {
+ hideSidebar: () => dispatch(actions.hideSidebar()),
+ showConfigPage: () => dispatch(actions.showConfigPage()),
+ showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)),
+ showAccountDetailModal: () => {
+ dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
+ },
+ showEditAccountModal: (identity) => {
+ dispatch(actions.showModal({
+ name: 'EDIT_ACCOUNT_NAME',
+ identity,
+ }))
+ },
+ showNewAccountModal: () => {
+ dispatch(actions.showModal({ name: 'NEW_ACCOUNT' }))
+ },
+ showExportPrivateKeyModal: () => {
+ dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
+ },
+ showAddTokenPage: () => {
+ dispatch(actions.showAddTokenPage())
+ },
+ addNewAccount: () => dispatch(actions.addNewAccount()),
+ showImportPage: () => dispatch(actions.showImportPage()),
+ showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)),
+ },
+ }
+}
+
+function mapStateToProps (state) {
+ return {
+ keyrings: state.metamask.keyrings,
+ sidebarOpen: state.appState.sidebarOpen,
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDropdowns)
+
diff --git a/ui/app/components/dropdown.js b/ui/app/components/dropdowns/components/dropdown.js
similarity index 76%
rename from ui/app/components/dropdown.js
rename to ui/app/components/dropdowns/components/dropdown.js
index 73710acc2..991c89cb8 100644
--- a/ui/app/components/dropdown.js
+++ b/ui/app/components/dropdowns/components/dropdown.js
@@ -1,14 +1,22 @@
const Component = require('react').Component
const PropTypes = require('react').PropTypes
const h = require('react-hyperscript')
-const MenuDroppo = require('./menu-droppo')
+const MenuDroppo = require('../../menu-droppo')
const extend = require('xtend')
const noop = () => {}
class Dropdown extends Component {
render () {
- const { isOpen, onClickOutside, style, innerStyle, children, useCssTransition } = this.props
+ const {
+ containerClassName,
+ isOpen,
+ onClickOutside,
+ style,
+ innerStyle,
+ children,
+ useCssTransition,
+ } = this.props
const innerStyleDefaults = extend({
borderRadius: '4px',
@@ -20,9 +28,10 @@ class Dropdown extends Component {
return h(
MenuDroppo,
{
+ containerClassName,
useCssTransition,
isOpen,
- zIndex: 11,
+ zIndex: 30,
onClickOutside,
style,
innerStyle: innerStyleDefaults,
@@ -31,8 +40,12 @@ class Dropdown extends Component {
h(
'style',
`
- li.dropdown-menu-item:hover { color:rgb(225, 225, 225); }
- li.dropdown-menu-item { color: rgb(185, 185, 185); position: relative }
+ li.dropdown-menu-item:hover {
+ color:rgb(225, 225, 225);
+ background-color: rgba(255, 255, 255, 0.05);
+ border-radius: 4px;
+ }
+ li.dropdown-menu-item { color: rgb(185, 185, 185); }
`
),
...children,
@@ -67,7 +80,7 @@ class DropdownMenuItem extends Component {
},
style: Object.assign({
listStyle: 'none',
- padding: '8px 0px 8px 0px',
+ padding: '8px 0px',
fontSize: '18px',
fontStyle: 'normal',
fontFamily: 'Montserrat Regular',
@@ -75,6 +88,7 @@ class DropdownMenuItem extends Component {
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
+ color: 'white',
}, style),
},
children
diff --git a/ui/app/components/dropdowns/components/menu.js b/ui/app/components/dropdowns/components/menu.js
new file mode 100644
index 000000000..f6d8a139e
--- /dev/null
+++ b/ui/app/components/dropdowns/components/menu.js
@@ -0,0 +1,51 @@
+const inherits = require('util').inherits
+const Component = require('react').Component
+const h = require('react-hyperscript')
+
+inherits(Menu, Component)
+function Menu () { Component.call(this) }
+
+Menu.prototype.render = function () {
+ const { className = '', children, isShowing } = this.props
+ return isShowing
+ ? h('div', { className: `menu ${className}` }, children)
+ : h('noscript')
+}
+
+inherits(Item, Component)
+function Item () { Component.call(this) }
+
+Item.prototype.render = function () {
+ const {
+ icon,
+ children,
+ text,
+ className = '',
+ onClick,
+ } = this.props
+ const itemClassName = `menu__item ${className} ${onClick ? 'menu__item--clickable' : ''}`
+ const iconComponent = icon ? h('div.menu__item__icon', [icon]) : null
+ const textComponent = text ? h('div.menu__item__text', text) : null
+
+ return children
+ ? h('div', { className: itemClassName, onClick }, children)
+ : h('div.menu__item', { className: itemClassName, onClick }, [ iconComponent, textComponent ]
+ .filter(d => Boolean(d))
+ )
+}
+
+inherits(Divider, Component)
+function Divider () { Component.call(this) }
+
+Divider.prototype.render = function () {
+ return h('div.menu__divider')
+}
+
+inherits(CloseArea, Component)
+function CloseArea () { Component.call(this) }
+
+CloseArea.prototype.render = function () {
+ return h('div.menu__close-area', { onClick: this.props.onClick })
+}
+
+module.exports = { Menu, Item, Divider, CloseArea }
diff --git a/ui/app/components/dropdowns/components/network-dropdown-icon.js b/ui/app/components/dropdowns/components/network-dropdown-icon.js
new file mode 100644
index 000000000..7e94e0af5
--- /dev/null
+++ b/ui/app/components/dropdowns/components/network-dropdown-icon.js
@@ -0,0 +1,28 @@
+const inherits = require('util').inherits
+const Component = require('react').Component
+const h = require('react-hyperscript')
+
+
+inherits(NetworkDropdownIcon, Component)
+module.exports = NetworkDropdownIcon
+
+function NetworkDropdownIcon () {
+ Component.call(this)
+}
+
+NetworkDropdownIcon.prototype.render = function () {
+ const {
+ backgroundColor,
+ isSelected,
+ innerBorder = 'none',
+ } = this.props
+
+ return h(`.menu-icon-circle${isSelected ? '--active' : ''}`, {},
+ h('div', {
+ style: {
+ background: backgroundColor,
+ border: innerBorder,
+ },
+ })
+ )
+}
diff --git a/ui/app/components/dropdowns/index.js b/ui/app/components/dropdowns/index.js
new file mode 100644
index 000000000..fa66f5000
--- /dev/null
+++ b/ui/app/components/dropdowns/index.js
@@ -0,0 +1,17 @@
+// Reusable Dropdown Components
+// TODO: Refactor into separate components
+const Dropdown = require('./components/dropdown').Dropdown
+const AccountDropdowns = require('./components/account-dropdowns')
+
+// App-Specific Instances
+const AccountSelectionDropdown = require('./account-selection-dropdown')
+const AccountOptionsDropdown = require('./account-options-dropdown')
+const NetworkDropdown = require('./network-dropdown').default
+
+module.exports = {
+ AccountSelectionDropdown,
+ AccountOptionsDropdown,
+ NetworkDropdown,
+ Dropdown,
+ AccountDropdowns,
+}
diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js
new file mode 100644
index 000000000..736019c39
--- /dev/null
+++ b/ui/app/components/dropdowns/network-dropdown.js
@@ -0,0 +1,316 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const Dropdown = require('./components/dropdown').Dropdown
+const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem
+const NetworkDropdownIcon = require('./components/network-dropdown-icon')
+
+function mapStateToProps (state) {
+ return {
+ provider: state.metamask.provider,
+ frequentRpcList: state.metamask.frequentRpcList || [],
+ networkDropdownOpen: state.appState.networkDropdownOpen,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ setProviderType: (type) => {
+ dispatch(actions.setProviderType(type))
+ },
+ setDefaultRpcTarget: type => {
+ dispatch(actions.setDefaultRpcTarget(type))
+ },
+ setRpcTarget: (target) => {
+ dispatch(actions.setRpcTarget(target))
+ },
+ showConfigPage: () => {
+ dispatch(actions.showConfigPage())
+ },
+ showNetworkDropdown: () => { dispatch(actions.showNetworkDropdown()) },
+ hideNetworkDropdown: () => { dispatch(actions.hideNetworkDropdown()) },
+ }
+}
+
+
+inherits(NetworkDropdown, Component)
+function NetworkDropdown () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown)
+
+// TODO: specify default props and proptypes
+NetworkDropdown.prototype.render = function () {
+ const props = this.props
+ const { provider: { type: providerType, rpcTarget: activeNetwork } } = props
+ const rpcList = props.frequentRpcList
+ const isOpen = this.props.networkDropdownOpen
+ const dropdownMenuItemStyle = {
+ fontFamily: 'DIN OT',
+ fontSize: '16px',
+ lineHeight: '20px',
+ padding: '12px 0',
+ }
+
+ return h(Dropdown, {
+ useCssTransition: true,
+ isOpen,
+ onClickOutside: (event) => {
+ const { classList } = event.target
+ const isNotToggleElement = [
+ classList.contains('menu-icon'),
+ classList.contains('network-name'),
+ classList.contains('network-indicator'),
+ ].filter(bool => bool).length === 0
+ // classes from three constituent nodes of the toggle element
+
+ if (isNotToggleElement) {
+ this.props.hideNetworkDropdown()
+ }
+ },
+ containerClassName: 'network-droppo',
+ zIndex: 11,
+ style: {
+ position: 'absolute',
+ top: '38px',
+ minWidth: '309px',
+ },
+ innerStyle: {
+ padding: '18px 8px',
+ },
+ }, [
+
+ h('div.network-dropdown-header', {}, [
+ h('div.network-dropdown-title', {}, 'Networks'),
+
+ h('div.network-dropdown-divider'),
+
+ h('div.network-dropdown-content',
+ {},
+ 'The default network for Ether transactions is Main Net.'
+ ),
+ ]),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'main',
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => props.setProviderType('mainnet'),
+ style: { ...dropdownMenuItemStyle, borderColor: '#038789' },
+ },
+ [
+ providerType === 'mainnet' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#038789', // $blue-lagoon
+ isSelected: providerType === 'mainnet',
+ }),
+ h('span.network-name-item', {
+ style: {
+ color: providerType === 'mainnet' ? '#ffffff' : '#9b9b9b',
+ },
+ }, 'Main Ethereum Network'),
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'ropsten',
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => props.setProviderType('ropsten'),
+ style: dropdownMenuItemStyle,
+ },
+ [
+ providerType === 'ropsten' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#e91550', // $crimson
+ isSelected: providerType === 'ropsten',
+ }),
+ h('span.network-name-item', {
+ style: {
+ color: providerType === 'ropsten' ? '#ffffff' : '#9b9b9b',
+ },
+ }, 'Ropsten Test Network'),
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'kovan',
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => props.setProviderType('kovan'),
+ style: dropdownMenuItemStyle,
+ },
+ [
+ providerType === 'kovan' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#690496', // $purple
+ isSelected: providerType === 'kovan',
+ }),
+ h('span.network-name-item', {
+ style: {
+ color: providerType === 'kovan' ? '#ffffff' : '#9b9b9b',
+ },
+ }, 'Kovan Test Network'),
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'rinkeby',
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => props.setProviderType('rinkeby'),
+ style: dropdownMenuItemStyle,
+ },
+ [
+ providerType === 'rinkeby' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#ebb33f', // $tulip-tree
+ isSelected: providerType === 'rinkeby',
+ }),
+ h('span.network-name-item', {
+ style: {
+ color: providerType === 'rinkeby' ? '#ffffff' : '#9b9b9b',
+ },
+ }, 'Rinkeby Test Network'),
+ ]
+ ),
+
+ h(
+ DropdownMenuItem,
+ {
+ key: 'default',
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => props.setRpcTarget('http://localhost:8545'),
+ style: dropdownMenuItemStyle,
+ },
+ [
+ activeNetwork === 'http://localhost:8545' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ h(NetworkDropdownIcon, {
+ isSelected: activeNetwork === 'http://localhost:8545',
+ innerBorder: '1px solid #9b9b9b',
+ }),
+ h('span.network-name-item', {
+ style: {
+ color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b',
+ },
+ }, 'Localhost 8545'),
+ ]
+ ),
+
+ this.renderCustomOption(props.provider),
+ this.renderCommonRpc(rpcList, props.provider),
+
+ h(
+ DropdownMenuItem,
+ {
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => this.props.showConfigPage(),
+ style: dropdownMenuItemStyle,
+ },
+ [
+ activeNetwork === 'custom' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ h(NetworkDropdownIcon, {
+ isSelected: activeNetwork === 'custom',
+ innerBorder: '1px solid #9b9b9b',
+ }),
+ h('span.network-name-item', {
+ style: {
+ color: activeNetwork === 'custom' ? '#ffffff' : '#9b9b9b',
+ },
+ }, 'Custom RPC'),
+ ]
+ ),
+
+ ])
+}
+
+
+NetworkDropdown.prototype.getNetworkName = function () {
+ const { provider } = this.props
+ const providerName = provider.type
+
+ let name
+
+ if (providerName === 'mainnet') {
+ name = 'Main Ethereum Network'
+ } else if (providerName === 'ropsten') {
+ name = 'Ropsten Test Network'
+ } else if (providerName === 'kovan') {
+ name = 'Kovan Test Network'
+ } else if (providerName === 'rinkeby') {
+ name = 'Rinkeby Test Network'
+ } else {
+ name = 'Unknown Private Network'
+ }
+
+ return name
+}
+
+NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) {
+ const props = this.props
+ const rpcTarget = provider.rpcTarget
+
+ return rpcList.map((rpc) => {
+ if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) {
+ return null
+ } else {
+ return h(
+ DropdownMenuItem,
+ {
+ key: `common${rpc}`,
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ onClick: () => props.setRpcTarget(rpc),
+ },
+ [
+ h('i.fa.fa-question-circle.fa-lg.menu-icon'),
+ rpc,
+ rpcTarget === rpc ? h('.check', '✓') : null,
+ ]
+ )
+ }
+ })
+}
+
+NetworkDropdown.prototype.renderCustomOption = function (provider) {
+ const { rpcTarget, type } = provider
+ const props = this.props
+
+ if (type !== 'rpc') return null
+
+ // Concatenate long URLs
+ let label = rpcTarget
+ if (rpcTarget.length > 31) {
+ label = label.substr(0, 34) + '...'
+ }
+
+ switch (rpcTarget) {
+
+ case 'http://localhost:8545':
+ return null
+
+ default:
+ return h(
+ DropdownMenuItem,
+ {
+ key: rpcTarget,
+ onClick: () => props.setRpcTarget(rpcTarget),
+ closeMenu: () => this.props.hideNetworkDropdown(),
+ },
+ [
+ h('i.fa.fa-question-circle.fa-lg.menu-icon'),
+ label,
+ h('.check', '✓'),
+ ]
+ )
+ }
+}
diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js
new file mode 100644
index 000000000..7234a9b21
--- /dev/null
+++ b/ui/app/components/dropdowns/token-menu-dropdown.js
@@ -0,0 +1,51 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+
+module.exports = connect(null, mapDispatchToProps)(TokenMenuDropdown)
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showHideTokenConfirmationModal: (token) => {
+ dispatch(actions.showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token }))
+ }
+ }
+}
+
+
+inherits(TokenMenuDropdown, Component)
+function TokenMenuDropdown () {
+ Component.call(this)
+
+ this.onClose = this.onClose.bind(this)
+}
+
+TokenMenuDropdown.prototype.onClose = function (e) {
+ e.stopPropagation()
+ this.props.onClose()
+}
+
+TokenMenuDropdown.prototype.render = function () {
+ const { showHideTokenConfirmationModal } = this.props
+
+ return h('div.token-menu-dropdown', {}, [
+ h('div.token-menu-dropdown__close-area', {
+ onClick: this.onClose,
+ }),
+ h('div.token-menu-dropdown__container', {}, [
+ h('div.token-menu-dropdown__options', {}, [
+
+ h('div.token-menu-dropdown__option', {
+ onClick: (e) => {
+ e.stopPropagation()
+ showHideTokenConfirmationModal(this.props.token)
+ this.props.onClose()
+ },
+ }, 'Hide Token')
+
+ ]),
+ ]),
+ ])
+}
diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js
index 3a33ebf74..fb8c8e579 100644
--- a/ui/app/components/ens-input.js
+++ b/ui/app/components/ens-input.js
@@ -44,7 +44,7 @@ EnsInput.prototype.render = function () {
return h('div', {
style: { width: '100%' },
}, [
- h('input.large-input', opts),
+ h('input.large-input.send-screen-input', opts),
// The address book functionality.
h('datalist#addresses',
[
@@ -125,7 +125,7 @@ EnsInput.prototype.componentDidUpdate = function (prevProps, prevState) {
EnsInput.prototype.ensIcon = function (recipient) {
const { hoverText } = this.state || {}
- return h('span', {
+ return h('span.#ensIcon', {
title: hoverText,
style: {
position: 'absolute',
diff --git a/ui/app/components/eth-balance.js b/ui/app/components/eth-balance.js
index 4f538fd31..1be8c9731 100644
--- a/ui/app/components/eth-balance.js
+++ b/ui/app/components/eth-balance.js
@@ -1,8 +1,10 @@
-const Component = require('react').Component
+const { Component } = require('react')
const h = require('react-hyperscript')
-const inherits = require('util').inherits
-const formatBalance = require('../util').formatBalance
-const generateBalanceObject = require('../util').generateBalanceObject
+const { inherits } = require('util')
+const {
+ formatBalance,
+ generateBalanceObject,
+} = require('../util')
const Tooltip = require('./tooltip.js')
const FiatValue = require('./fiat-value.js')
@@ -14,11 +16,10 @@ function EthBalanceComponent () {
}
EthBalanceComponent.prototype.render = function () {
- var props = this.props
- let { value } = props
- const { style, width } = props
- var needsParse = this.props.needsParse !== undefined ? this.props.needsParse : true
- value = value ? formatBalance(value, 6, needsParse) : '...'
+ const props = this.props
+ const { value, style, width, needsParse = true } = props
+
+ const formattedValue = value ? formatBalance(value, 6, needsParse) : '...'
return (
@@ -30,60 +31,66 @@ EthBalanceComponent.prototype.render = function () {
display: 'inline',
width,
},
- }, this.renderBalance(value)),
+ }, this.renderBalance(formattedValue)),
])
)
}
EthBalanceComponent.prototype.renderBalance = function (value) {
- var props = this.props
- const { conversionRate, shorten, incoming, currentCurrency } = props
if (value === 'None') return value
if (value === '...') return value
- var balanceObj = generateBalanceObject(value, shorten ? 1 : 3)
- var balance
- var splitBalance = value.split(' ')
- var ethNumber = splitBalance[0]
- var ethSuffix = splitBalance[1]
- const showFiat = 'showFiat' in props ? props.showFiat : true
- if (shorten) {
- balance = balanceObj.shortBalance
- } else {
- balance = balanceObj.balance
+ const {
+ conversionRate,
+ shorten,
+ incoming,
+ currentCurrency,
+ hideTooltip,
+ styleOveride,
+ showFiat = true,
+ } = this.props
+ const { fontSize, color, fontFamily, lineHeight } = styleOveride
+
+ const { shortBalance, balance, label } = generateBalanceObject(value, shorten ? 1 : 3)
+ const balanceToRender = shorten ? shortBalance : balance
+
+ const [ethNumber, ethSuffix] = value.split(' ')
+ const containerProps = hideTooltip ? {} : {
+ position: 'bottom',
+ title: `${ethNumber} ${ethSuffix}`,
}
- var label = balanceObj.label
-
return (
- h(Tooltip, {
- position: 'bottom',
- title: `${ethNumber} ${ethSuffix}`,
- }, h('div.flex-column', [
- h('.flex-row', {
- style: {
- alignItems: 'flex-end',
- lineHeight: '13px',
- fontFamily: 'Montserrat Light',
- textRendering: 'geometricPrecision',
- },
- }, [
- h('div', {
+ h(hideTooltip ? 'div' : Tooltip,
+ containerProps,
+ h('div.flex-column', [
+ h('.flex-row', {
style: {
- width: '100%',
- textAlign: 'right',
+ alignItems: 'flex-end',
+ lineHeight: lineHeight || '13px',
+ fontFamily: fontFamily || 'Montserrat Light',
+ textRendering: 'geometricPrecision',
},
- }, incoming ? `+${balance}` : balance),
- h('div', {
- style: {
- color: ' #AEAEAE',
- fontSize: '12px',
- marginLeft: '5px',
- },
- }, label),
- ]),
+ }, [
+ h('div', {
+ style: {
+ width: '100%',
+ textAlign: 'right',
+ fontSize: fontSize || 'inherit',
+ color: color || 'inherit',
+ },
+ }, incoming ? `+${balanceToRender}` : balanceToRender),
+ h('div', {
+ style: {
+ color: color || '#AEAEAE',
+ fontSize: fontSize || '12px',
+ marginLeft: '5px',
+ },
+ }, label),
+ ]),
- showFiat ? h(FiatValue, { value: props.value, conversionRate, currentCurrency }) : null,
- ]))
+ showFiat ? h(FiatValue, { value: this.props.value, conversionRate, currentCurrency }) : null,
+ ])
+ )
)
}
diff --git a/ui/app/components/fiat-value.js b/ui/app/components/fiat-value.js
index d69f41d11..56465fc9d 100644
--- a/ui/app/components/fiat-value.js
+++ b/ui/app/components/fiat-value.js
@@ -12,7 +12,7 @@ function FiatValue () {
FiatValue.prototype.render = function () {
const props = this.props
- const { conversionRate, currentCurrency } = props
+ const { conversionRate, currentCurrency, style } = props
const renderedCurrency = currentCurrency || ''
const value = formatBalance(props.value, 6)
@@ -29,16 +29,18 @@ FiatValue.prototype.render = function () {
fiatTooltipNumber = 'Unknown'
}
- return fiatDisplay(fiatDisplayNumber, renderedCurrency.toUpperCase())
+ return fiatDisplay(fiatDisplayNumber, renderedCurrency.toUpperCase(), style)
}
-function fiatDisplay (fiatDisplayNumber, fiatSuffix) {
+function fiatDisplay (fiatDisplayNumber, fiatSuffix, styleOveride = {}) {
+ const { fontSize, color, fontFamily, lineHeight } = styleOveride
+
if (fiatDisplayNumber !== 'N/A') {
return h('.flex-row', {
style: {
alignItems: 'flex-end',
- lineHeight: '13px',
- fontFamily: 'Montserrat Light',
+ lineHeight: lineHeight || '13px',
+ fontFamily: fontFamily || 'Montserrat Light',
textRendering: 'geometricPrecision',
},
}, [
@@ -46,15 +48,15 @@ function fiatDisplay (fiatDisplayNumber, fiatSuffix) {
style: {
width: '100%',
textAlign: 'right',
- fontSize: '12px',
- color: '#333333',
+ fontSize: fontSize || '12px',
+ color: color || '#333333',
},
}, fiatDisplayNumber),
h('div', {
style: {
- color: '#AEAEAE',
+ color: color || '#AEAEAE',
marginLeft: '5px',
- fontSize: '12px',
+ fontSize: fontSize || '12px',
},
}, fiatSuffix),
])
diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js
index c754bc6ba..259fa4d73 100644
--- a/ui/app/components/identicon.js
+++ b/ui/app/components/identicon.js
@@ -18,21 +18,35 @@ function IdenticonComponent () {
IdenticonComponent.prototype.render = function () {
var props = this.props
+ const { className = '', address } = props
var diameter = props.diameter || this.defaultDiameter
- return (
- h('div', {
- key: 'identicon-' + this.props.address,
- style: {
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- height: diameter,
- width: diameter,
- borderRadius: diameter / 2,
- overflow: 'hidden',
- },
- })
- )
+
+ return address
+ ? (
+ h('div', {
+ className: `${className} identicon`,
+ key: 'identicon-' + address,
+ style: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: diameter,
+ width: diameter,
+ borderRadius: diameter / 2,
+ overflow: 'hidden',
+ },
+ })
+ )
+ : (
+ h('img.balance-icon', {
+ src: '../images/eth_logo.svg',
+ style: {
+ height: diameter,
+ width: diameter,
+ borderRadius: diameter / 2,
+ },
+ })
+ )
}
IdenticonComponent.prototype.componentDidMount = function () {
diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js
new file mode 100644
index 000000000..16347fd5e
--- /dev/null
+++ b/ui/app/components/input-number.js
@@ -0,0 +1,46 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const { addCurrencies } = require('../conversion-util')
+
+module.exports = InputNumber
+
+inherits(InputNumber, Component)
+function InputNumber () {
+ Component.call(this)
+
+ this.setValue = this.setValue.bind(this)
+}
+
+InputNumber.prototype.setValue = function (newValue) {
+ const { fixed, min = -1, max = Infinity, onChange } = this.props
+
+ newValue = Number(fixed ? newValue.toFixed(4) : newValue)
+
+ if (newValue >= min && newValue <= max) {
+ onChange(newValue)
+ }
+}
+
+InputNumber.prototype.render = function () {
+ const { unitLabel, step = 1, placeholder, value = 0 } = this.props
+
+ return h('div.customize-gas-input-wrapper', {}, [
+ h('input.customize-gas-input', {
+ placeholder,
+ type: 'number',
+ value: value,
+ onChange: (e) => this.setValue(e.target.value),
+ }),
+ h('span.gas-tooltip-input-detail', {}, [unitLabel]),
+ h('div.gas-tooltip-input-arrows', {}, [
+ h('i.fa.fa-angle-up', {
+ onClick: () => this.setValue(addCurrencies(value, step)),
+ }),
+ h('i.fa.fa-angle-down', {
+ style: { cursor: 'pointer' },
+ onClick: () => this.setValue(addCurrencies(value, step * -1)),
+ }),
+ ]),
+ ])
+}
diff --git a/ui/app/components/menu-droppo.js b/ui/app/components/menu-droppo.js
index 66ab18954..95b75f54c 100644
--- a/ui/app/components/menu-droppo.js
+++ b/ui/app/components/menu-droppo.js
@@ -13,21 +13,23 @@ function MenuDroppoComponent () {
}
MenuDroppoComponent.prototype.render = function () {
+ const { containerClassName = '' } = this.props
const speed = this.props.speed || '300ms'
const useCssTransition = this.props.useCssTransition
const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0
this.manageListeners()
- let style = this.props.style || {}
+ const style = this.props.style || {}
if (!('position' in style)) {
style.position = 'fixed'
}
style.zIndex = zIndex
return (
- h('.menu-droppo-container', {
+ h('div', {
style,
+ className: `.menu-droppo-container ${containerClassName}`,
}, [
h('style', `
.menu-droppo-enter {
diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js
new file mode 100644
index 000000000..37a62e1c0
--- /dev/null
+++ b/ui/app/components/modals/account-details-modal.js
@@ -0,0 +1,70 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const AccountModalContainer = require('./account-modal-container')
+const { getSelectedIdentity, getSelectedAddress } = require('../../selectors')
+const genAccountLink = require('../../../lib/account-link.js')
+const QrView = require('../qr-code')
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ selectedIdentity: getSelectedIdentity(state),
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ // Is this supposed to be used somewhere?
+ showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)),
+ showExportPrivateKeyModal: () => {
+ dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
+ },
+ hideModal: () => dispatch(actions.hideModal()),
+ }
+}
+
+inherits(AccountDetailsModal, Component)
+function AccountDetailsModal () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsModal)
+
+// Not yet pixel perfect todos:
+ // fonts of qr-header
+
+AccountDetailsModal.prototype.render = function () {
+ const {
+ selectedIdentity,
+ network,
+ showExportPrivateKeyModal,
+ hideModal,
+ } = this.props
+ const { name, address } = selectedIdentity
+
+ return h(AccountModalContainer, {}, [
+ h(QrView, {
+ Qr: {
+ message: name,
+ data: address,
+ },
+ }),
+
+ h('div.account-modal-divider'),
+
+ h('button.btn-clear', {
+ onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }),
+ }, [ 'View account on Etherscan' ]),
+
+ // Holding on redesign for Export Private Key functionality
+ h('button.btn-clear', {
+ onClick: () => {
+ showExportPrivateKeyModal()
+ },
+ }, [ 'Export private key' ]),
+
+ ])
+}
diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js
new file mode 100644
index 000000000..c548fb7b3
--- /dev/null
+++ b/ui/app/components/modals/account-modal-container.js
@@ -0,0 +1,74 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const { getSelectedIdentity } = require('../../selectors')
+const Identicon = require('../identicon')
+
+function mapStateToProps (state) {
+ return {
+ selectedIdentity: getSelectedIdentity(state),
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ }
+}
+
+inherits(AccountModalContainer, Component)
+function AccountModalContainer () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountModalContainer)
+
+AccountModalContainer.prototype.render = function () {
+ const {
+ selectedIdentity,
+ showBackButton = false,
+ backButtonAction,
+ } = this.props
+ let { children } = this.props
+
+ if (children.constructor !== Array) {
+ children = [children]
+ }
+
+ return h('div', { style: { borderRadius: '4px' }}, [
+ h('div.account-modal-container', [
+
+ h('div', [
+
+ // Needs a border; requires changes to svg
+ h(Identicon, {
+ address: selectedIdentity.address,
+ diameter: 64,
+ style: {},
+ }),
+
+ ]),
+
+ showBackButton && h('div.account-modal-back', {
+ onClick: backButtonAction,
+ }, [
+
+ h('i.fa.fa-angle-left.fa-lg'),
+
+ h('span.account-modal-back__text', ' Back'),
+
+ ]),
+
+ h('div.account-modal-close', {
+ onClick: this.props.hideModal,
+ }),
+
+ ...children,
+
+ ]),
+ ])
+}
diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js
new file mode 100644
index 000000000..f1a5aa9fd
--- /dev/null
+++ b/ui/app/components/modals/buy-options-modal.js
@@ -0,0 +1,87 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ address: state.metamask.selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ toCoinbase: (address) => {
+ dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
+ },
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ showAccountDetailModal: () => {
+ dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
+ },
+ }
+}
+
+inherits(BuyOptions, Component)
+function BuyOptions () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(BuyOptions)
+
+BuyOptions.prototype.render = function () {
+ return h('div', {}, [
+ h('div.buy-modal-content.transfers-subview', {
+ }, [
+ h('div.buy-modal-content-title-wrapper.flex-column.flex-center', {
+ style: {},
+ }, [
+ h('div.buy-modal-content-title', {
+ style: {},
+ }, 'Transfers'),
+ h('div', {}, 'How would you like to buy Ether?'),
+ ]),
+
+ h('div.buy-modal-content-options.flex-column.flex-center', {}, [
+
+ h('div.buy-modal-content-option', {
+ onClick: () => {
+ const { toCoinbase, address } = this.props
+ toCoinbase(address)
+ },
+ }, [
+ h('div.buy-modal-content-option-title', {}, 'Coinbase'),
+ h('div.buy-modal-content-option-subtitle', {}, 'Buy with Fiat'),
+ ]),
+
+ // h('div.buy-modal-content-option', {}, [
+ // h('div.buy-modal-content-option-title', {}, 'Shapeshift'),
+ // h('div.buy-modal-content-option-subtitle', {}, 'Trade any digital asset for any other'),
+ // ]),
+
+ h('div.buy-modal-content-option', {
+ onClick: () => this.goToAccountDetailsModal(),
+ }, [
+ h('div.buy-modal-content-option-title', {}, 'Direct Deposit'),
+ h('div.buy-modal-content-option-subtitle', {}, 'Deposit from another account'),
+ ]),
+
+ ]),
+
+ h('button', {
+ style: {
+ background: 'white',
+ },
+ onClick: () => { this.props.hideModal() },
+ }, h('div.buy-modal-content-footer#buy-modal-content-footer-text', {}, 'Cancel')),
+ ]),
+ ])
+}
+
+BuyOptions.prototype.goToAccountDetailsModal = function () {
+ this.props.hideModal()
+ this.props.showAccountDetailModal()
+}
diff --git a/ui/app/components/modals/edit-account-name-modal.js b/ui/app/components/modals/edit-account-name-modal.js
new file mode 100644
index 000000000..e2361140d
--- /dev/null
+++ b/ui/app/components/modals/edit-account-name-modal.js
@@ -0,0 +1,77 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const { getSelectedAccount } = require('../../selectors')
+
+function mapStateToProps (state) {
+ return {
+ selectedAccount: getSelectedAccount(state),
+ identity: state.appState.modal.modalState.identity,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ saveAccountLabel: (account, label) => {
+ dispatch(actions.saveAccountLabel(account, label))
+ },
+ }
+}
+
+inherits(EditAccountNameModal, Component)
+function EditAccountNameModal (props) {
+ Component.call(this)
+
+ this.state = {
+ inputText: props.identity.name,
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(EditAccountNameModal)
+
+EditAccountNameModal.prototype.render = function () {
+ const { hideModal, saveAccountLabel, identity } = this.props
+
+ return h('div', {}, [
+ h('div.flex-column.edit-account-name-modal-content', {
+ }, [
+
+ h('div.edit-account-name-modal-cancel', {
+ onClick: () => {
+ hideModal()
+ },
+ }, [
+ h('i.fa.fa-times'),
+ ]),
+
+ h('div.edit-account-name-modal-title', {
+ }, ['Edit Account Name']),
+
+ h('input.edit-account-name-modal-input', {
+ placeholder: identity.name,
+ onChange: (event) => {
+ this.setState({ inputText: event.target.value })
+ },
+ value: this.state.inputText,
+ }, []),
+
+ h('button.btn-clear.edit-account-name-modal-save-button', {
+ onClick: () => {
+ if (this.state.inputText.length !== 0) {
+ saveAccountLabel(identity.address, this.state.inputText)
+ hideModal()
+ }
+ },
+ disabled: this.state.inputText.length === 0,
+ }, [
+ 'SAVE',
+ ]),
+
+ ]),
+ ])
+}
diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js
new file mode 100644
index 000000000..302596eda
--- /dev/null
+++ b/ui/app/components/modals/export-private-key-modal.js
@@ -0,0 +1,139 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const ethUtil = require('ethereumjs-util')
+const actions = require('../../actions')
+const AccountModalContainer = require('./account-modal-container')
+const { getSelectedIdentity } = require('../../selectors')
+const ReadOnlyInput = require('../readonly-input')
+const copyToClipboard = require('copy-to-clipboard')
+
+function mapStateToProps (state) {
+ return {
+ warning: state.appState.warning,
+ privateKey: state.appState.accountDetail.privateKey,
+ network: state.metamask.network,
+ selectedIdentity: getSelectedIdentity(state),
+ previousModalState: state.appState.modal.previousModalState.name,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ exportAccount: (password, address) => dispatch(actions.exportAccount(password, address)),
+ showAccountDetailModal: () => dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })),
+ hideModal: () => dispatch(actions.hideModal()),
+ }
+}
+
+inherits(ExportPrivateKeyModal, Component)
+function ExportPrivateKeyModal () {
+ Component.call(this)
+
+ this.state = {
+ password: '',
+ privateKey: null,
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(ExportPrivateKeyModal)
+
+ExportPrivateKeyModal.prototype.exportAccountAndGetPrivateKey = function (password, address) {
+ const { exportAccount } = this.props
+
+ exportAccount(password, address)
+ .then(privateKey => this.setState({ privateKey }))
+}
+
+ExportPrivateKeyModal.prototype.renderPasswordLabel = function (privateKey) {
+ return h('span.private-key-password-label', privateKey
+ ? 'This is your private key (click to copy)'
+ : 'Type Your Password'
+ )
+}
+
+ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) {
+ const plainKey = privateKey && ethUtil.stripHexPrefix(privateKey)
+
+ return privateKey
+ ? h(ReadOnlyInput, {
+ wrapperClass: 'private-key-password-display-wrapper',
+ inputClass: 'private-key-password-display-textarea',
+ textarea: true,
+ value: plainKey,
+ onClick: () => copyToClipboard(plainKey),
+ })
+ : h('input.private-key-password-input', {
+ type: 'password',
+ placeholder: 'Type password',
+ onChange: event => this.setState({ password: event.target.value }),
+ })
+}
+
+ExportPrivateKeyModal.prototype.renderButton = function (className, onClick, label) {
+ return h('button', {
+ className,
+ onClick,
+ }, label)
+}
+
+ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, address, hideModal) {
+ return h('div.export-private-key-buttons', {}, [
+ !privateKey && this.renderButton('btn-clear btn-cancel', () => hideModal(), 'Cancel'),
+
+ (privateKey
+ ? this.renderButton('btn-clear', () => hideModal(), 'Done')
+ : this.renderButton('btn-clear', () => this.exportAccountAndGetPrivateKey(this.state.password, address), 'Download')
+ ),
+
+ ])
+}
+
+ExportPrivateKeyModal.prototype.render = function () {
+ const {
+ selectedIdentity,
+ network,
+ warning,
+ showAccountDetailModal,
+ hideModal,
+ previousModalState,
+ } = this.props
+ const { name, address } = selectedIdentity
+
+ const { privateKey } = this.state
+
+ return h(AccountModalContainer, {
+ showBackButton: previousModalState === 'ACCOUNT_DETAILS',
+ backButtonAction: () => showAccountDetailModal(),
+ }, [
+
+ h('span.account-name', name),
+
+ h(ReadOnlyInput, {
+ wrapperClass: 'ellip-address-wrapper',
+ inputClass: 'qr-ellip-address ellip-address',
+ value: address,
+ }),
+
+ h('div.account-modal-divider'),
+
+ h('span.modal-body-title', 'Download Private Keys'),
+
+ h('div.private-key-password', {}, [
+ this.renderPasswordLabel(privateKey),
+
+ this.renderPasswordInput(privateKey),
+
+ !warning ? null : h('span.private-key-password-error', warning),
+ ]),
+
+ h('div.private-key-password-warning', `Warning: Never disclose this key.
+ Anyone with your private keys can take steal any assets held in your
+ account.`
+ ),
+
+ this.renderButtons(privateKey, this.state.password, address, hideModal),
+
+ ])
+}
diff --git a/ui/app/components/modals/hide-token-confirmation-modal.js b/ui/app/components/modals/hide-token-confirmation-modal.js
new file mode 100644
index 000000000..fa3ad0b1e
--- /dev/null
+++ b/ui/app/components/modals/hide-token-confirmation-modal.js
@@ -0,0 +1,74 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const Identicon = require('../identicon')
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ token: state.appState.modal.modalState.token,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => dispatch(actions.hideModal()),
+ hideToken: address => {
+ dispatch(actions.removeToken(address))
+ .then(() => {
+ dispatch(actions.hideModal())
+ })
+ },
+ }
+}
+
+inherits(HideTokenConfirmationModal, Component)
+function HideTokenConfirmationModal () {
+ Component.call(this)
+
+ this.state = {}
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(HideTokenConfirmationModal)
+
+HideTokenConfirmationModal.prototype.render = function () {
+ const { token, network, hideToken, hideModal } = this.props
+ const { symbol, address } = token
+
+ return h('div.hide-token-confirmation', {}, [
+ h('div.hide-token-confirmation__container', {
+ }, [
+ h('div.hide-token-confirmation__title', {}, [
+ 'Hide Token?',
+ ]),
+
+ h(Identicon, {
+ className: 'hide-token-confirmation__identicon',
+ diameter: 45,
+ address,
+ network,
+ }),
+
+ h('div.hide-token-confirmation__symbol', {}, symbol),
+
+ h('div.hide-token-confirmation__copy', {}, [
+ 'You can add this token back in the future by going go to “Add token” in your accounts options menu.',
+ ]),
+
+ h('div.hide-token-confirmation__buttons', {}, [
+ h('button.btn-clear', {
+ onClick: () => hideModal(),
+ }, [
+ 'CANCEL',
+ ]),
+ h('button.btn-clear', {
+ onClick: () => hideToken(address),
+ }, [
+ 'HIDE',
+ ]),
+ ]),
+ ]),
+ ])
+}
diff --git a/ui/app/components/modals/index.js b/ui/app/components/modals/index.js
new file mode 100644
index 000000000..1db1d33d4
--- /dev/null
+++ b/ui/app/components/modals/index.js
@@ -0,0 +1,5 @@
+const Modal = require('./modal')
+
+module.exports = {
+ Modal,
+}
diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js
new file mode 100644
index 000000000..88deb2bb0
--- /dev/null
+++ b/ui/app/components/modals/modal.js
@@ -0,0 +1,263 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const FadeModal = require('boron').FadeModal
+const actions = require('../../actions')
+const isMobileView = require('../../../lib/is-mobile-view')
+const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification')
+
+// Modal Components
+const BuyOptions = require('./buy-options-modal')
+const AccountDetailsModal = require('./account-details-modal')
+const EditAccountNameModal = require('./edit-account-name-modal')
+const ExportPrivateKeyModal = require('./export-private-key-modal')
+const NewAccountModal = require('./new-account-modal')
+const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js')
+const HideTokenConfirmationModal = require('./hide-token-confirmation-modal')
+const CustomizeGasModal = require('../customize-gas-modal')
+
+const accountModalStyle = {
+ mobileModalStyle: {
+ width: '95%',
+ // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+ borderRadius: '4px',
+ top: '10%',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ laptopModalStyle: {
+ width: '360px',
+ // top: 'calc(33% + 45px)',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+ borderRadius: '4px',
+ top: '10%',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ contentStyle: {
+ borderRadius: '4px',
+ },
+}
+
+const MODALS = {
+ BUY: {
+ contents: [
+ h(BuyOptions, {}, []),
+ ],
+ mobileModalStyle: {
+ width: '95%',
+ // top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)',
+ top: '10%',
+ },
+ laptopModalStyle: {
+ width: '66%',
+ maxWidth: '550px',
+ top: 'calc(10% + 10px)',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)',
+ transform: 'none',
+ },
+ },
+
+ EDIT_ACCOUNT_NAME: {
+ contents: [
+ h(EditAccountNameModal, {}, []),
+ ],
+ mobileModalStyle: {
+ width: '95%',
+ // top: isPopupOrNotification() === 'popup' ? '48vh' : '36.5vh',
+ top: '10%',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ laptopModalStyle: {
+ width: '375px',
+ // top: 'calc(30% + 10px)',
+ top: '10%',
+ boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ },
+
+ ACCOUNT_DETAILS: {
+ contents: [
+ h(AccountDetailsModal, {}, []),
+ ],
+ ...accountModalStyle,
+ },
+
+ EXPORT_PRIVATE_KEY: {
+ contents: [
+ h(ExportPrivateKeyModal, {}, []),
+ ],
+ ...accountModalStyle,
+ },
+
+ SHAPESHIFT_DEPOSIT_TX: {
+ contents: [
+ h(ShapeshiftDepositTxModal),
+ ],
+ ...accountModalStyle,
+ },
+
+ HIDE_TOKEN_CONFIRMATION: {
+ contents: [
+ h(HideTokenConfirmationModal, {}, []),
+ ],
+ mobileModalStyle: {
+ width: '95%',
+ top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh',
+ },
+ laptopModalStyle: {
+ width: '449px',
+ top: 'calc(33% + 45px)',
+ },
+ },
+
+ NEW_ACCOUNT: {
+ contents: [
+ h(NewAccountModal, {}, []),
+ ],
+ mobileModalStyle: {
+ width: '95%',
+ // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh',
+ top: '10%',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ laptopModalStyle: {
+ width: '449px',
+ // top: 'calc(33% + 45px)',
+ top: '10%',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ },
+
+ CUSTOMIZE_GAS: {
+ contents: [
+ h(CustomizeGasModal, {}, []),
+ ],
+ mobileModalStyle: {
+ width: '355px',
+ height: '598px',
+ // top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh',
+ top: '5%',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ laptopModalStyle: {
+ width: '720px',
+ height: '377px',
+ top: '80px',
+ transform: 'none',
+ left: '0',
+ right: '0',
+ margin: '0 auto',
+ },
+ },
+
+ DEFAULT: {
+ contents: [],
+ mobileModalStyle: {},
+ laptopModalStyle: {},
+ },
+}
+
+const BACKDROPSTYLE = {
+ backgroundColor: 'rgba(245, 245, 245, 0.85)',
+}
+
+function mapStateToProps (state) {
+ return {
+ active: state.appState.modal.open,
+ modalState: state.appState.modal.modalState,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ }
+}
+
+// Global Modal Component
+inherits(Modal, Component)
+function Modal () {
+ Component.call(this)
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(Modal)
+
+Modal.prototype.render = function () {
+ const modal = MODALS[this.props.modalState.name || 'DEFAULT']
+
+ const children = modal.contents
+ const modalStyle = modal[isMobileView() ? 'mobileModalStyle' : 'laptopModalStyle']
+ const contentStyle = modal.contentStyle || {};
+
+ return h(FadeModal,
+ {
+ className: 'modal',
+ keyboard: false,
+ onHide: () => { this.onHide() },
+ ref: (ref) => {
+ this.modalRef = ref
+ },
+ modalStyle,
+ contentStyle,
+ backdropStyle: BACKDROPSTYLE,
+ },
+ children,
+ )
+}
+
+Modal.prototype.componentWillReceiveProps = function (nextProps) {
+ if (nextProps.active) {
+ this.show()
+ } else if (this.props.active) {
+ this.hide()
+ }
+}
+
+Modal.prototype.onHide = function () {
+ if (this.props.onHideCallback) {
+ this.props.onHideCallback()
+ }
+ this.props.hideModal()
+}
+
+Modal.prototype.hide = function () {
+ this.modalRef.hide()
+}
+
+Modal.prototype.show = function () {
+ this.modalRef.show()
+}
diff --git a/ui/app/components/modals/new-account-modal.js b/ui/app/components/modals/new-account-modal.js
new file mode 100644
index 000000000..25beb6745
--- /dev/null
+++ b/ui/app/components/modals/new-account-modal.js
@@ -0,0 +1,87 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ address: state.metamask.selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ toCoinbase: (address) => {
+ dispatch(actions.buyEth({ network: '1', address, amount: 0 }))
+ },
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ createAccount: (newAccountName) => {
+ dispatch(actions.addNewAccount())
+ .then((newAccountAddress) => {
+ if (newAccountName) {
+ dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName))
+ }
+ dispatch(actions.hideModal())
+ })
+ },
+ }
+}
+
+inherits(NewAccountModal, Component)
+function NewAccountModal () {
+ Component.call(this)
+
+ this.state = {
+ newAccountName: ''
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(NewAccountModal)
+
+NewAccountModal.prototype.render = function () {
+ const { newAccountName } = this.state
+
+ return h('div', {}, [
+ h('div.new-account-modal-wrapper', {
+ }, [
+ h('div.new-account-modal-header', {}, [
+ 'New Account',
+ ]),
+
+ h('div.modal-close-x', {
+ onClick: this.props.hideModal,
+ }),
+
+ h('div.new-account-modal-content', {}, [
+ 'Account Name',
+ ]),
+
+ h('div.new-account-input-wrapper', {}, [
+ h('input.new-account-input', {
+ placeholder: 'E.g. My new account',
+ onChange: (event) => this.setState({ newAccountName: event.target.value })
+ }, []),
+ ]),
+
+ h('div.new-account-modal-content.after-input', {}, [
+ 'or',
+ ]),
+
+ h('div.new-account-modal-content.after-input', {}, [
+ 'Import an account',
+ ]),
+
+ h('div.new-account-modal-content.button', {}, [
+ h('button.btn-clear', {
+ onClick: () => this.props.createAccount(newAccountName)
+ }, [
+ 'SAVE',
+ ]),
+ ]),
+ ]),
+ ])
+}
diff --git a/ui/app/components/modals/shapeshift-deposit-tx-modal.js b/ui/app/components/modals/shapeshift-deposit-tx-modal.js
new file mode 100644
index 000000000..1fd1ade00
--- /dev/null
+++ b/ui/app/components/modals/shapeshift-deposit-tx-modal.js
@@ -0,0 +1,40 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const QrView = require('../qr-code')
+const AccountModalContainer = require('./account-modal-container')
+
+function mapStateToProps (state) {
+ return {
+ Qr: state.appState.modal.modalState.Qr,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ hideModal: () => {
+ dispatch(actions.hideModal())
+ },
+ }
+}
+
+inherits(ShapeshiftDepositTxModal, Component)
+function ShapeshiftDepositTxModal () {
+ Component.call(this)
+
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(ShapeshiftDepositTxModal)
+
+ShapeshiftDepositTxModal.prototype.render = function () {
+ const { Qr } = this.props
+
+ return h(AccountModalContainer, {
+ }, [
+ h('div', {}, [
+ h(QrView, {key: 'qr', Qr}),
+ ])
+ ])
+}
diff --git a/ui/app/components/network.js b/ui/app/components/network.js
index 0dbe37cdd..b24505750 100644
--- a/ui/app/components/network.js
+++ b/ui/app/components/network.js
@@ -1,6 +1,8 @@
const Component = require('react').Component
const h = require('react-hyperscript')
+const classnames = require('classnames');
const inherits = require('util').inherits
+const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon')
module.exports = Network
@@ -60,7 +62,13 @@ Network.prototype.render = function () {
}
return (
- h('#network_component.pointer', {
+ h('div.network-component.pointer', {
+ className: classnames('network-component pointer', {
+ 'ethereum-network': providerName === 'mainnet',
+ 'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3,
+ 'kovan-test-network': providerName === 'kovan',
+ 'rinkeby-test-network': providerName === 'rinkeby',
+ }),
title: hoverText,
onClick: (event) => this.props.onClick(event),
}, [
@@ -68,7 +76,10 @@ Network.prototype.render = function () {
switch (iconName) {
case 'ethereum-network':
return h('.network-indicator', [
- h('.menu-icon.diamond'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#038789', // $blue-lagoon
+ nonSelectBackgroundColor: '#15afb2',
+ }),
h('.network-name', {
style: {
color: '#039396',
@@ -78,7 +89,10 @@ Network.prototype.render = function () {
])
case 'ropsten-test-network':
return h('.network-indicator', [
- h('.menu-icon.red-dot'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#e91550', // $crimson
+ nonSelectBackgroundColor: '#ec2c50',
+ }),
h('.network-name', {
style: {
color: '#ff6666',
@@ -88,7 +102,10 @@ Network.prototype.render = function () {
])
case 'kovan-test-network':
return h('.network-indicator', [
- h('.menu-icon.hollow-diamond'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#690496', // $purple
+ nonSelectBackgroundColor: '#b039f3',
+ }),
h('.network-name', {
style: {
color: '#690496',
@@ -98,7 +115,10 @@ Network.prototype.render = function () {
])
case 'rinkeby-test-network':
return h('.network-indicator', [
- h('.menu-icon.golden-square'),
+ h(NetworkDropdownIcon, {
+ backgroundColor: '#ebb33f', // $tulip-tree
+ nonSelectBackgroundColor: '#ecb23e',
+ }),
h('.network-name', {
style: {
color: '#e7a218',
diff --git a/ui/app/components/notice.js b/ui/app/components/notice.js
index c26505193..abfff1f5c 100644
--- a/ui/app/components/notice.js
+++ b/ui/app/components/notice.js
@@ -102,7 +102,7 @@ Notice.prototype.render = function () {
}),
]),
- h('button', {
+ h('button.primary', {
disabled,
onClick: () => {
this.setState({disclaimerDisabled: true})
diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js
deleted file mode 100644
index c3350fcc1..000000000
--- a/ui/app/components/pending-tx.js
+++ /dev/null
@@ -1,501 +0,0 @@
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-const actions = require('../actions')
-const clone = require('clone')
-
-const ethUtil = require('ethereumjs-util')
-const BN = ethUtil.BN
-const hexToBn = require('../../../app/scripts/lib/hex-to-bn')
-const util = require('../util')
-const MiniAccountPanel = require('./mini-account-panel')
-const Copyable = require('./copyable')
-const EthBalance = require('./eth-balance')
-const addressSummary = util.addressSummary
-const nameForAddress = require('../../lib/contract-namer')
-const BNInput = require('./bn-as-decimal-input')
-
-const MIN_GAS_PRICE_GWEI_BN = new BN(1)
-const GWEI_FACTOR = new BN(1e9)
-const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
-const MIN_GAS_LIMIT_BN = new BN(21000)
-
-module.exports = PendingTx
-inherits(PendingTx, Component)
-function PendingTx () {
- Component.call(this)
- this.state = {
- valid: true,
- txData: null,
- submitting: false,
- }
-}
-
-PendingTx.prototype.render = function () {
- const props = this.props
- const { currentCurrency, blockGasLimit } = props
-
- const conversionRate = props.conversionRate
- const txMeta = this.gatherTxMeta()
- const txParams = txMeta.txParams || {}
-
- // Account Details
- const address = txParams.from || props.selectedAddress
- const identity = props.identities[address] || { address: address }
- const account = props.accounts[address]
- const balance = account ? account.balance : '0x0'
-
- // recipient check
- const isValidAddress = !txParams.to || util.isValidAddress(txParams.to)
-
- // Gas
- const gas = txParams.gas
- const gasBn = hexToBn(gas)
- const gasLimit = new BN(parseInt(blockGasLimit))
- const safeGasLimitBN = this.bnMultiplyByFraction(gasLimit, 19, 20)
- const saferGasLimitBN = this.bnMultiplyByFraction(gasLimit, 18, 20)
- const safeGasLimit = safeGasLimitBN.toString(10)
-
- // Gas Price
- const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
- const gasPriceBn = hexToBn(gasPrice)
-
- const txFeeBn = gasBn.mul(gasPriceBn)
- const valueBn = hexToBn(txParams.value)
- const maxCost = txFeeBn.add(valueBn)
-
- const dataLength = txParams.data ? (txParams.data.length - 2) / 2 : 0
-
- const balanceBn = hexToBn(balance)
- const insufficientBalance = balanceBn.lt(maxCost)
- const dangerousGasLimit = gasBn.gte(saferGasLimitBN)
- const gasLimitSpecified = txMeta.gasLimitSpecified
- const buyDisabled = insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting
- const showRejectAll = props.unconfTxListLength > 1
-
- this.inputs = []
-
- return (
-
- h('div', {
- key: txMeta.id,
- }, [
-
- h('form#pending-tx-form', {
- onSubmit: this.onSubmit.bind(this),
-
- }, [
-
- // tx info
- h('div', [
-
- h('.flex-row.flex-center', {
- style: {
- maxWidth: '100%',
- },
- }, [
-
- h(MiniAccountPanel, {
- imageSeed: address,
- picOrder: 'right',
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, identity.name),
-
- h(Copyable, {
- value: ethUtil.toChecksumAddress(address),
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, addressSummary(address, 6, 4, false)),
- ]),
-
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, [
- h(EthBalance, {
- value: balance,
- conversionRate,
- currentCurrency,
- inline: true,
- labelColor: '#F7861C',
- }),
- ]),
- ]),
-
- forwardCarrat(),
-
- this.miniAccountPanelForRecipient(),
- ]),
-
- h('style', `
- .table-box {
- margin: 7px 0px 0px 0px;
- width: 100%;
- }
- .table-box .row {
- margin: 0px;
- background: rgb(236,236,236);
- display: flex;
- justify-content: space-between;
- font-family: Montserrat Light, sans-serif;
- font-size: 13px;
- padding: 5px 25px;
- }
- .table-box .row .value {
- font-family: Montserrat Regular;
- }
- `),
-
- h('.table-box', [
-
- // Ether Value
- // Currently not customizable, but easily modified
- // in the way that gas and gasLimit currently are.
- h('.row', [
- h('.cell.label', 'Amount'),
- h(EthBalance, { value: txParams.value, currentCurrency, conversionRate }),
- ]),
-
- // Gas Limit (customizable)
- h('.cell.row', [
- h('.cell.label', 'Gas Limit'),
- h('.cell.value', {
- }, [
- h(BNInput, {
- name: 'Gas Limit',
- value: gasBn,
- precision: 0,
- scale: 0,
- // The hard lower limit for gas.
- min: MIN_GAS_LIMIT_BN.toString(10),
- max: safeGasLimit,
- suffix: 'UNITS',
- style: {
- position: 'relative',
- top: '5px',
- },
- onChange: this.gasLimitChanged.bind(this),
-
- ref: (hexInput) => { this.inputs.push(hexInput) },
- }),
- ]),
- ]),
-
- // Gas Price (customizable)
- h('.cell.row', [
- h('.cell.label', 'Gas Price'),
- h('.cell.value', {
- }, [
- h(BNInput, {
- name: 'Gas Price',
- value: gasPriceBn,
- precision: 9,
- scale: 9,
- suffix: 'GWEI',
- min: MIN_GAS_PRICE_GWEI_BN.toString(10),
- style: {
- position: 'relative',
- top: '5px',
- },
- onChange: this.gasPriceChanged.bind(this),
- ref: (hexInput) => { this.inputs.push(hexInput) },
- }),
- ]),
- ]),
-
- // Max Transaction Fee (calculated)
- h('.cell.row', [
- h('.cell.label', 'Max Transaction Fee'),
- h(EthBalance, { value: txFeeBn.toString(16), currentCurrency, conversionRate }),
- ]),
-
- h('.cell.row', {
- style: {
- fontFamily: 'Montserrat Regular',
- background: 'white',
- padding: '10px 25px',
- },
- }, [
- h('.cell.label', 'Max Total'),
- h('.cell.value', {
- style: {
- display: 'flex',
- alignItems: 'center',
- },
- }, [
- h(EthBalance, {
- value: maxCost.toString(16),
- currentCurrency,
- conversionRate,
- inline: true,
- labelColor: 'black',
- fontSize: '16px',
- }),
- ]),
- ]),
-
- // Data size row:
- h('.cell.row', {
- style: {
- background: '#f7f7f7',
- paddingBottom: '0px',
- },
- }, [
- h('.cell.label'),
- h('.cell.value', {
- style: {
- fontFamily: 'Montserrat Light',
- fontSize: '11px',
- },
- }, `Data included: ${dataLength} bytes`),
- ]),
- ]), // End of Table
-
- ]),
-
- h('style', `
- .conf-buttons button {
- margin-left: 10px;
- text-transform: uppercase;
- }
- `),
- h('.cell.row', {
- style: {
- textAlign: 'center',
- },
- }, [
- txMeta.simulationFails ?
- h('.error', {
- style: {
- fontSize: '0.9em',
- },
- }, 'Transaction Error. Exception thrown in contract code.')
- : null,
-
- !isValidAddress ?
- h('.error', {
- style: {
- fontSize: '0.9em',
- },
- }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.')
- : null,
-
- insufficientBalance ?
- h('span.error', {
- style: {
- fontSize: '0.9em',
- },
- }, 'Insufficient balance for transaction')
- : null,
-
- (dangerousGasLimit && !gasLimitSpecified) ?
- h('span.error', {
- style: {
- fontSize: '0.9em',
- },
- }, 'Gas limit set dangerously high. Approving this transaction is likely to fail.')
- : null,
- ]),
-
-
- // send + cancel
- h('.flex-row.flex-space-around.conf-buttons', {
- style: {
- display: 'flex',
- justifyContent: 'flex-end',
- margin: '14px 25px',
- },
- }, [
- h('button', {
- onClick: (event) => {
- this.resetGasFields()
- event.preventDefault()
- },
- }, 'Reset'),
-
- // Accept Button or Buy Button
- insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') :
- h('input.confirm.btn-green', {
- type: 'submit',
- value: 'SUBMIT',
- style: { marginLeft: '10px' },
- disabled: buyDisabled,
- }),
-
- h('button.cancel.btn-red', {
- onClick: props.cancelTransaction,
- }, 'Reject'),
- ]),
- showRejectAll ? h('.flex-row.flex-space-around.conf-buttons', {
- style: {
- display: 'flex',
- justifyContent: 'flex-end',
- margin: '14px 25px',
- },
- }, [
- h('button.cancel.btn-red', {
- onClick: props.cancelAllTransactions,
- }, 'Reject All'),
- ]) : null,
- ]),
- ])
- )
-}
-
-PendingTx.prototype.miniAccountPanelForRecipient = function () {
- const props = this.props
- const txData = props.txData
- const txParams = txData.txParams || {}
- const isContractDeploy = !('to' in txParams)
-
- // If it's not a contract deploy, send to the account
- if (!isContractDeploy) {
- return h(MiniAccountPanel, {
- imageSeed: txParams.to,
- picOrder: 'left',
- }, [
-
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, nameForAddress(txParams.to, props.identities)),
-
- h(Copyable, {
- value: ethUtil.toChecksumAddress(txParams.to),
- }, [
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Light, Montserrat, sans-serif',
- },
- }, addressSummary(txParams.to, 6, 4, false)),
- ]),
-
- ])
- } else {
- return h(MiniAccountPanel, {
- picOrder: 'left',
- }, [
-
- h('span.font-small', {
- style: {
- fontFamily: 'Montserrat Bold, Montserrat, sans-serif',
- },
- }, 'New Contract'),
-
- ])
- }
-}
-
-PendingTx.prototype.gasPriceChanged = function (newBN, valid) {
- log.info(`Gas price changed to: ${newBN.toString(10)}`)
- const txMeta = this.gatherTxMeta()
- txMeta.txParams.gasPrice = '0x' + newBN.toString('hex')
- this.setState({
- txData: clone(txMeta),
- valid,
- })
-}
-
-PendingTx.prototype.gasLimitChanged = function (newBN, valid) {
- log.info(`Gas limit changed to ${newBN.toString(10)}`)
- const txMeta = this.gatherTxMeta()
- txMeta.txParams.gas = '0x' + newBN.toString('hex')
- this.setState({
- txData: clone(txMeta),
- valid,
- })
-}
-
-PendingTx.prototype.resetGasFields = function () {
- log.debug(`pending-tx resetGasFields`)
-
- this.inputs.forEach((hexInput) => {
- if (hexInput) {
- hexInput.setValid()
- }
- })
-
- this.setState({
- txData: null,
- valid: true,
- })
-}
-
-PendingTx.prototype.onSubmit = function (event) {
- event.preventDefault()
- const txMeta = this.gatherTxMeta()
- const valid = this.checkValidity()
- this.setState({ valid, submitting: true })
- if (valid && this.verifyGasParams()) {
- this.props.sendTransaction(txMeta, event)
- } else {
- this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
- this.setState({ submitting: false })
- }
-}
-
-PendingTx.prototype.checkValidity = function () {
- const form = this.getFormEl()
- const valid = form.checkValidity()
- return valid
-}
-
-PendingTx.prototype.getFormEl = function () {
- const form = document.querySelector('form#pending-tx-form')
- // Stub out form for unit tests:
- if (!form) {
- return { checkValidity () { return true } }
- }
- return form
-}
-
-// After a customizable state value has been updated,
-PendingTx.prototype.gatherTxMeta = function () {
- log.debug(`pending-tx gatherTxMeta`)
- const props = this.props
- const state = this.state
- const txData = clone(state.txData) || clone(props.txData)
-
- log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`)
- return txData
-}
-
-PendingTx.prototype.verifyGasParams = function () {
- // We call this in case the gas has not been modified at all
- if (!this.state) { return true }
- return (
- this._notZeroOrEmptyString(this.state.gas) &&
- this._notZeroOrEmptyString(this.state.gasPrice)
- )
-}
-
-PendingTx.prototype._notZeroOrEmptyString = function (obj) {
- return obj !== '' && obj !== '0x0'
-}
-
-PendingTx.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) {
- const numBN = new BN(numerator)
- const denomBN = new BN(denominator)
- return targetBN.mul(numBN).div(denomBN)
-}
-
-function forwardCarrat () {
- return (
- h('img', {
- src: 'images/forward-carrat.svg',
- style: {
- padding: '5px 6px 0px 10px',
- height: '37px',
- },
- })
- )
-}
diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js
new file mode 100644
index 000000000..ea4aa1dde
--- /dev/null
+++ b/ui/app/components/pending-tx/confirm-deploy-contract.js
@@ -0,0 +1,344 @@
+const Component = require('react').Component
+const { connect } = require('react-redux')
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const actions = require('../../actions')
+const clone = require('clone')
+const Identicon = require('../identicon')
+const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
+const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
+const { conversionUtil } = require('../../conversion-util')
+
+const MIN_GAS_PRICE_GWEI_BN = new BN(1)
+const GWEI_FACTOR = new BN(1e9)
+const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
+
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract)
+
+function mapStateToProps (state) {
+ const {
+ conversionRate,
+ identities,
+ } = state.metamask
+ const accounts = state.metamask.accounts
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ return {
+ conversionRate,
+ identities,
+ selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)),
+ cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
+ }
+}
+
+
+inherits(ConfirmDeployContract, Component)
+function ConfirmDeployContract () {
+ Component.call(this)
+ this.state = {}
+ this.onSubmit = this.onSubmit.bind(this)
+}
+
+ConfirmDeployContract.prototype.onSubmit = function (event) {
+ event.preventDefault()
+ const txMeta = this.gatherTxMeta()
+ const valid = this.checkValidity()
+ this.setState({ valid, submitting: true })
+
+ if (valid && this.verifyGasParams()) {
+ this.props.sendTransaction(txMeta, event)
+ } else {
+ this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
+ this.setState({ submitting: false })
+ }
+}
+
+ConfirmDeployContract.prototype.cancel = function (event, txMeta) {
+ event.preventDefault()
+ this.props.cancelTransaction(txMeta)
+}
+
+ConfirmDeployContract.prototype.checkValidity = function () {
+ const form = this.getFormEl()
+ const valid = form.checkValidity()
+ return valid
+}
+
+ConfirmDeployContract.prototype.getFormEl = function () {
+ const form = document.querySelector('form#pending-tx-form')
+ // Stub out form for unit tests:
+ if (!form) {
+ return { checkValidity () { return true } }
+ }
+ return form
+}
+
+// After a customizable state value has been updated,
+ConfirmDeployContract.prototype.gatherTxMeta = function () {
+ const props = this.props
+ const state = this.state
+ const txData = clone(state.txData) || clone(props.txData)
+
+ // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`)
+ return txData
+}
+
+ConfirmDeployContract.prototype.verifyGasParams = function () {
+ // We call this in case the gas has not been modified at all
+ if (!this.state) { return true }
+ return (
+ this._notZeroOrEmptyString(this.state.gas) &&
+ this._notZeroOrEmptyString(this.state.gasPrice)
+ )
+}
+
+ConfirmDeployContract.prototype._notZeroOrEmptyString = function (obj) {
+ return obj !== '' && obj !== '0x0'
+}
+
+ConfirmDeployContract.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) {
+ const numBN = new BN(numerator)
+ const denomBN = new BN(denominator)
+ return targetBN.mul(numBN).div(denomBN)
+}
+
+ConfirmDeployContract.prototype.getData = function () {
+ const { identities } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ return {
+ from: {
+ address: txParams.from,
+ name: identities[txParams.from].name,
+ },
+ memo: txParams.memo || '',
+ }
+}
+
+ConfirmDeployContract.prototype.getAmount = function () {
+ const { conversionRate } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ const USD = conversionUtil(txParams.value, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromCurrency: 'ETH',
+ toCurrency: 'USD',
+ numberOfDecimals: 2,
+ fromDenomination: 'WEI',
+ conversionRate,
+ })
+ const ETH = conversionUtil(txParams.value, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromCurrency: 'ETH',
+ toCurrency: 'ETH',
+ fromDenomination: 'WEI',
+ conversionRate,
+ numberOfDecimals: 6,
+ })
+
+ return {
+ fiat: Number(USD),
+ token: Number(ETH),
+ }
+
+}
+
+ConfirmDeployContract.prototype.getGasFee = function () {
+ const { conversionRate } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ // Gas
+ const gas = txParams.gas
+ const gasBn = hexToBn(gas)
+
+ // Gas Price
+ const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
+ const gasPriceBn = hexToBn(gasPrice)
+
+ const txFeeBn = gasBn.mul(gasPriceBn)
+
+ const USD = conversionUtil(txFeeBn, {
+ fromNumericBase: 'BN',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ fromCurrency: 'ETH',
+ toCurrency: 'USD',
+ numberOfDecimals: 2,
+ conversionRate,
+ })
+ const ETH = conversionUtil(txFeeBn, {
+ fromNumericBase: 'BN',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ fromCurrency: 'ETH',
+ toCurrency: 'ETH',
+ numberOfDecimals: 6,
+ conversionRate,
+ })
+
+ return {
+ fiat: Number(USD),
+ eth: Number(ETH),
+ }
+}
+ConfirmDeployContract.prototype.renderGasFee = function () {
+ const { fiat: fiatGas, eth: ethGas } = this.getGasFee()
+
+ return (
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `$${fiatGas} USD`),
+
+ h(
+ 'div.confirm-screen-row-detail',
+ `${ethGas} ETH`
+ ),
+ ]),
+ ])
+ )
+}
+
+ConfirmDeployContract.prototype.renderHeroAmount = function () {
+ const { fiat: fiatAmount } = this.getAmount()
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+ const { memo = '' } = txParams
+
+ return (
+ h('div.confirm-send-token__hero-amount-wrapper', [
+ h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`),
+ h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'),
+ h('div.flex-center.confirm-memo-wrapper', [
+ h('h3.confirm-screen-send-memo', memo),
+ ]),
+ ])
+ )
+}
+
+ConfirmDeployContract.prototype.renderTotalPlusGas = function () {
+ const { fiat: fiatAmount, token: tokenAmount } = this.getAmount()
+ const { fiat: fiatGas, eth: ethGas } = this.getGasFee()
+
+ return (
+ h('section.flex-row.flex-center.confirm-screen-total-box ', [
+ h('div.confirm-screen-section-column', [
+ h('span.confirm-screen-label', [ 'Total ' ]),
+ h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]),
+ ]),
+
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`),
+ h('div.confirm-screen-row-detail', `${tokenAmount + ethGas} ETH`),
+ ]),
+ ])
+ )
+}
+
+ConfirmDeployContract.prototype.render = function () {
+ const { backToAccountDetail, selectedAddress } = this.props
+ const txMeta = this.gatherTxMeta()
+
+ const {
+ from: {
+ address: fromAddress,
+ name: fromName,
+ },
+ } = this.getData()
+
+ this.inputs = []
+
+ return (
+ h('div.flex-column.flex-grow.confirm-screen-container', {
+ style: { minWidth: '355px' },
+ }, [
+ // Main Send token Card
+ h('div.confirm-screen-wrapper.flex-column.flex-grow', [
+ h('h3.flex-center.confirm-screen-header', [
+ h('button.confirm-screen-back-button', {
+ onClick: () => backToAccountDetail(selectedAddress),
+ }, 'BACK'),
+ h('div.confirm-screen-title', 'Confirm Contract'),
+ h('div.confirm-screen-header-tip'),
+ ]),
+ h('div.flex-row.flex-center.confirm-screen-identicons', [
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: fromAddress,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', fromName),
+ // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)),
+ ]),
+ h('i.fa.fa-arrow-right.fa-lg'),
+ h('div.confirm-screen-account-wrapper', [
+ h('i.fa.fa-file-text-o'),
+ h('span.confirm-screen-account-name', 'New Contract'),
+ h('span.confirm-screen-account-number', ' '),
+ ]),
+ ]),
+
+ // h('h3.flex-center.confirm-screen-sending-to-message', {
+ // style: {
+ // textAlign: 'center',
+ // fontSize: '16px',
+ // },
+ // }, [
+ // `You're deploying a new contract.`,
+ // ]),
+
+ this.renderHeroAmount(),
+
+ h('div.confirm-screen-rows', [
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', fromName),
+ h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`),
+ ]),
+ ]),
+
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', 'New Contract'),
+ ]),
+ ]),
+
+ this.renderGasFee(),
+
+ this.renderTotalPlusGas(),
+
+ ]),
+ ]),
+
+ h('form#pending-tx-form', {
+ onSubmit: this.onSubmit,
+ }, [
+ // Cancel Button
+ h('div.cancel.btn-light.confirm-screen-cancel-button', {
+ onClick: (event) => this.cancel(event, txMeta),
+ }, 'CANCEL'),
+
+ // Accept Button
+ h('button.confirm-screen-confirm-button', ['CONFIRM']),
+
+ ]),
+ ])
+ )
+}
diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js
new file mode 100644
index 000000000..537a9a659
--- /dev/null
+++ b/ui/app/components/pending-tx/confirm-send-ether.js
@@ -0,0 +1,445 @@
+const Component = require('react').Component
+const { connect } = require('react-redux')
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const actions = require('../../actions')
+const clone = require('clone')
+const Identicon = require('../identicon')
+const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
+const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
+const { conversionUtil, addCurrencies } = require('../../conversion-util')
+
+const MIN_GAS_PRICE_GWEI_BN = new BN(1)
+const GWEI_FACTOR = new BN(1e9)
+const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendEther)
+
+function mapStateToProps (state) {
+ const {
+ conversionRate,
+ identities,
+ } = state.metamask
+ const accounts = state.metamask.accounts
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ return {
+ conversionRate,
+ identities,
+ selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)),
+ cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
+ }
+}
+
+inherits(ConfirmSendEther, Component)
+function ConfirmSendEther () {
+ Component.call(this)
+ this.state = {}
+ this.onSubmit = this.onSubmit.bind(this)
+}
+
+ConfirmSendEther.prototype.getAmount = function () {
+ const { conversionRate } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+ console.log(txParams)
+ const USD = conversionUtil(txParams.value, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromCurrency: 'ETH',
+ toCurrency: 'USD',
+ numberOfDecimals: 2,
+ fromDenomination: 'WEI',
+ conversionRate,
+ })
+ const ETH = conversionUtil(txParams.value, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromCurrency: 'ETH',
+ toCurrency: 'ETH',
+ fromDenomination: 'WEI',
+ conversionRate,
+ numberOfDecimals: 6,
+ })
+
+ return {
+ USD,
+ ETH,
+ }
+
+}
+
+ConfirmSendEther.prototype.getGasFee = function () {
+ const { conversionRate } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ // Gas
+ const gas = txParams.gas
+ const gasBn = hexToBn(gas)
+
+ // From latest master
+// const gasLimit = new BN(parseInt(blockGasLimit))
+// const safeGasLimitBN = this.bnMultiplyByFraction(gasLimit, 19, 20)
+// const saferGasLimitBN = this.bnMultiplyByFraction(gasLimit, 18, 20)
+// const safeGasLimit = safeGasLimitBN.toString(10)
+
+ // Gas Price
+ const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
+ const gasPriceBn = hexToBn(gasPrice)
+
+ const txFeeBn = gasBn.mul(gasPriceBn)
+
+ const USD = conversionUtil(txFeeBn, {
+ fromNumericBase: 'BN',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ fromCurrency: 'ETH',
+ toCurrency: 'USD',
+ numberOfDecimals: 2,
+ conversionRate,
+ })
+ const ETH = conversionUtil(txFeeBn, {
+ fromNumericBase: 'BN',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ fromCurrency: 'ETH',
+ toCurrency: 'ETH',
+ numberOfDecimals: 6,
+ conversionRate,
+ })
+
+ return {
+ USD,
+ ETH,
+ }
+}
+
+ConfirmSendEther.prototype.getData = function () {
+ const { identities } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+ const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee()
+ const { USD: amountInUSD, ETH: amountInETH } = this.getAmount()
+
+ const totalInUSD = addCurrencies(gasFeeInUSD, amountInUSD, {
+ toNumericBase: 'dec',
+ numberOfDecimals: 2,
+ })
+ const totalInETH = addCurrencies(gasFeeInETH, amountInETH, {
+ toNumericBase: 'dec',
+ numberOfDecimals: 6,
+ })
+
+ return {
+ from: {
+ address: txParams.from,
+ name: identities[txParams.from].name,
+ },
+ to: {
+ address: txParams.to,
+ name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient',
+ },
+ memo: txParams.memo || '',
+ gasFeeInUSD,
+ gasFeeInETH,
+ amountInUSD,
+ amountInETH,
+ totalInUSD,
+ totalInETH,
+ }
+}
+
+ConfirmSendEther.prototype.render = function () {
+ const { backToAccountDetail, selectedAddress } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ const {
+ from: {
+ address: fromAddress,
+ name: fromName,
+ },
+ to: {
+ address: toAddress,
+ name: toName,
+ },
+ memo,
+ gasFeeInUSD,
+ gasFeeInETH,
+ amountInUSD,
+ totalInUSD,
+ totalInETH,
+ } = this.getData()
+
+ // This is from the latest master
+ // It handles some of the errors that we are not currently handling
+ // Leaving as comments fo reference
+
+ // const balanceBn = hexToBn(balance)
+ // const insufficientBalance = balanceBn.lt(maxCost)
+ // const buyDisabled = insufficientBalance || !this.state.valid || !isValidAddress || this.state.submitting
+ // const showRejectAll = props.unconfTxListLength > 1
+// const dangerousGasLimit = gasBn.gte(saferGasLimitBN)
+// const gasLimitSpecified = txMeta.gasLimitSpecified
+
+ this.inputs = []
+
+ return (
+ h('div.confirm-screen-container', {
+ style: { minWidth: '355px' },
+ }, [
+ // Main Send token Card
+ h('div.confirm-screen-wrapper.flex-column.flex-grow', [
+ h('h3.flex-center.confirm-screen-header', [
+ h('button.confirm-screen-back-button', {
+ onClick: () => backToAccountDetail(selectedAddress),
+ }, 'BACK'),
+ h('div.confirm-screen-title', 'Confirm Transaction'),
+ h('div.confirm-screen-header-tip'),
+ ]),
+ h('div.flex-row.flex-center.confirm-screen-identicons', [
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: fromAddress,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', fromName),
+ // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)),
+ ]),
+ h('i.fa.fa-arrow-right.fa-lg'),
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: txParams.to,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', toName),
+ // h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)),
+ ]),
+ ]),
+
+ // h('h3.flex-center.confirm-screen-sending-to-message', {
+ // style: {
+ // textAlign: 'center',
+ // fontSize: '16px',
+ // },
+ // }, [
+ // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`,
+ // ]),
+
+ h('h3.flex-center.confirm-screen-send-amount', [`$${amountInUSD}`]),
+ h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]),
+ h('div.flex-center.confirm-memo-wrapper', [
+ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]),
+ ]),
+
+ h('div.confirm-screen-rows', [
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', fromName),
+ h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`),
+ ]),
+ ]),
+
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', toName),
+ h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`),
+ ]),
+ ]),
+
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `$${gasFeeInUSD} USD`),
+
+ h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`),
+ ]),
+ ]),
+
+
+ h('section.flex-row.flex-center.confirm-screen-total-box ', [
+ h('div.confirm-screen-section-column', [
+ h('span.confirm-screen-label', [ 'Total ' ]),
+ h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]),
+ ]),
+
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `$${totalInUSD} USD`),
+ h('div.confirm-screen-row-detail', `${totalInETH} ETH`),
+ ]),
+ ]),
+ ]),
+
+// These are latest errors handling from master
+// Leaving as comments as reference when we start implementing error handling
+// h('style', `
+// .conf-buttons button {
+// margin-left: 10px;
+// text-transform: uppercase;
+// }
+// `),
+
+// txMeta.simulationFails ?
+// h('.error', {
+// style: {
+// marginLeft: 50,
+// fontSize: '0.9em',
+// },
+// }, 'Transaction Error. Exception thrown in contract code.')
+// : null,
+
+// !isValidAddress ?
+// h('.error', {
+// style: {
+// marginLeft: 50,
+// fontSize: '0.9em',
+// },
+// }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.')
+// : null,
+
+// insufficientBalance ?
+// h('span.error', {
+// style: {
+// marginLeft: 50,
+// fontSize: '0.9em',
+// },
+// }, 'Insufficient balance for transaction')
+// : null,
+
+// // send + cancel
+// h('.flex-row.flex-space-around.conf-buttons', {
+// style: {
+// display: 'flex',
+// justifyContent: 'flex-end',
+// margin: '14px 25px',
+// },
+// }, [
+// h('button', {
+// onClick: (event) => {
+// this.resetGasFields()
+// event.preventDefault()
+// },
+// }, 'Reset'),
+
+// // Accept Button or Buy Button
+// insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') :
+// h('input.confirm.btn-green', {
+// type: 'submit',
+// value: 'SUBMIT',
+// style: { marginLeft: '10px' },
+// disabled: buyDisabled,
+// }),
+
+// h('button.cancel.btn-red', {
+// onClick: props.cancelTransaction,
+// }, 'Reject'),
+// ]),
+// showRejectAll ? h('.flex-row.flex-space-around.conf-buttons', {
+// style: {
+// display: 'flex',
+// justifyContent: 'flex-end',
+// margin: '14px 25px',
+// },
+// }, [
+// h('button.cancel.btn-red', {
+// onClick: props.cancelAllTransactions,
+// }, 'Reject All'),
+// ]) : null,
+// ]),
+// ])
+// )
+// }
+ ]),
+
+ h('form#pending-tx-form', {
+ onSubmit: this.onSubmit,
+ }, [
+ // Cancel Button
+ h('div.cancel.btn-light.confirm-screen-cancel-button', {
+ onClick: (event) => this.cancel(event, txMeta),
+ }, 'CANCEL'),
+
+ // Accept Button
+ h('button.confirm-screen-confirm-button', ['CONFIRM']),
+ ]),
+ ])
+ )
+}
+
+ConfirmSendEther.prototype.onSubmit = function (event) {
+ event.preventDefault()
+ const txMeta = this.gatherTxMeta()
+ const valid = this.checkValidity()
+ this.setState({ valid, submitting: true })
+
+ if (valid && this.verifyGasParams()) {
+ this.props.sendTransaction(txMeta, event)
+ } else {
+ this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
+ this.setState({ submitting: false })
+ }
+}
+
+ConfirmSendEther.prototype.cancel = function (event, txMeta) {
+ event.preventDefault()
+ this.props.cancelTransaction(txMeta)
+}
+
+ConfirmSendEther.prototype.checkValidity = function () {
+ const form = this.getFormEl()
+ const valid = form.checkValidity()
+ return valid
+}
+
+ConfirmSendEther.prototype.getFormEl = function () {
+ const form = document.querySelector('form#pending-tx-form')
+ // Stub out form for unit tests:
+ if (!form) {
+ return { checkValidity () { return true } }
+ }
+ return form
+}
+
+// After a customizable state value has been updated,
+ConfirmSendEther.prototype.gatherTxMeta = function () {
+ const props = this.props
+ const state = this.state
+ const txData = clone(state.txData) || clone(props.txData)
+
+ // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`)
+ return txData
+}
+
+ConfirmSendEther.prototype.verifyGasParams = function () {
+ // We call this in case the gas has not been modified at all
+ if (!this.state) { return true }
+ return (
+ this._notZeroOrEmptyString(this.state.gas) &&
+ this._notZeroOrEmptyString(this.state.gasPrice)
+ )
+}
+
+ConfirmSendEther.prototype._notZeroOrEmptyString = function (obj) {
+ return obj !== '' && obj !== '0x0'
+}
+
+ConfirmSendEther.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) {
+ const numBN = new BN(numerator)
+ const denomBN = new BN(denominator)
+ return targetBN.mul(numBN).div(denomBN)
+}
diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js
new file mode 100644
index 000000000..92bba8f62
--- /dev/null
+++ b/ui/app/components/pending-tx/confirm-send-token.js
@@ -0,0 +1,398 @@
+const Component = require('react').Component
+const { connect } = require('react-redux')
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const abi = require('human-standard-token-abi')
+const abiDecoder = require('abi-decoder')
+abiDecoder.addABI(abi)
+const actions = require('../../actions')
+const clone = require('clone')
+const Identicon = require('../identicon')
+const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
+const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
+const { conversionUtil } = require('../../conversion-util')
+
+const MIN_GAS_PRICE_GWEI_BN = new BN(1)
+const GWEI_FACTOR = new BN(1e9)
+const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmSendToken)
+
+function mapStateToProps (state, ownProps) {
+ const { token: { symbol }, txData } = ownProps
+ const { txParams } = txData || {}
+ const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data)
+ const {
+ conversionRate,
+ identities,
+ } = state.metamask
+ const accounts = state.metamask.accounts
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ const tokenExchangeRates = state.metamask.tokenExchangeRates
+ const pair = `${symbol.toLowerCase()}_eth`
+ const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {}
+
+ return {
+ conversionRate,
+ identities,
+ selectedAddress,
+ tokenExchangeRate,
+ tokenData: tokenData || {},
+ }
+}
+
+function mapDispatchToProps (dispatch, ownProps) {
+ const { token: { symbol } } = ownProps
+
+ return {
+ backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)),
+ cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
+ updateTokenExchangeRate: () => dispatch(actions.updateTokenExchangeRate(symbol)),
+ }
+}
+
+inherits(ConfirmSendToken, Component)
+function ConfirmSendToken () {
+ Component.call(this)
+ this.state = {}
+ this.onSubmit = this.onSubmit.bind(this)
+}
+
+ConfirmSendToken.prototype.componentWillMount = function () {
+ this.props.updateTokenExchangeRate()
+}
+
+ConfirmSendToken.prototype.getAmount = function () {
+ const { conversionRate, tokenExchangeRate, token, tokenData } = this.props
+ const { params = [] } = tokenData
+ const { value } = params[1] || {}
+ const { decimals } = token
+ const multiplier = Math.pow(10, Number(decimals || 0))
+ const sendTokenAmount = Number(value / multiplier)
+
+ return {
+ fiat: tokenExchangeRate
+ ? +(sendTokenAmount * tokenExchangeRate * conversionRate).toFixed(2)
+ : null,
+ token: +sendTokenAmount.toFixed(decimals),
+ }
+
+}
+
+ConfirmSendToken.prototype.getGasFee = function () {
+ const { conversionRate, tokenExchangeRate, token } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+ const { decimals } = token
+
+ // Gas
+ const gas = txParams.gas
+ const gasBn = hexToBn(gas)
+
+ // Gas Price
+ const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
+ const gasPriceBn = hexToBn(gasPrice)
+ const txFeeBn = gasBn.mul(gasPriceBn)
+
+
+ const USD = conversionUtil(txFeeBn, {
+ fromNumericBase: 'BN',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ fromCurrency: 'ETH',
+ toCurrency: 'USD',
+ numberOfDecimals: 2,
+ conversionRate,
+ })
+ const ETH = conversionUtil(txFeeBn, {
+ fromNumericBase: 'BN',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ fromCurrency: 'ETH',
+ toCurrency: 'ETH',
+ numberOfDecimals: 6,
+ conversionRate,
+ })
+
+ return {
+ fiat: +Number(USD).toFixed(2),
+ eth: ETH,
+ token: tokenExchangeRate
+ ? +(ETH * tokenExchangeRate).toFixed(decimals)
+ : null,
+ }
+}
+
+ConfirmSendToken.prototype.getData = function () {
+ const { identities, tokenData } = this.props
+ const { params = [] } = tokenData
+ const { value } = params[0] || {}
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ return {
+ from: {
+ address: txParams.from,
+ name: identities[txParams.from].name,
+ },
+ to: {
+ address: txParams.to,
+ name: identities[value] ? identities[value].name : 'New Recipient',
+ },
+ memo: txParams.memo || '',
+ }
+}
+
+ConfirmSendToken.prototype.renderHeroAmount = function () {
+ const { token: { symbol } } = this.props
+ const { fiat: fiatAmount, token: tokenAmount } = this.getAmount()
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+ const { memo = '' } = txParams
+
+ return fiatAmount
+ ? (
+ h('div.confirm-send-token__hero-amount-wrapper', [
+ h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`),
+ h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'),
+ h('div.flex-center.confirm-memo-wrapper', [
+ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]),
+ ]),
+ ])
+ )
+ : (
+ h('div.confirm-send-token__hero-amount-wrapper', [
+ h('h3.flex-center.confirm-screen-send-amount', tokenAmount),
+ h('h3.flex-center.confirm-screen-send-amount-currency', symbol),
+ h('div.flex-center.confirm-memo-wrapper', [
+ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]),
+ ]),
+ ])
+ )
+}
+
+ConfirmSendToken.prototype.renderGasFee = function () {
+ const { token: { symbol } } = this.props
+ const { fiat: fiatGas, token: tokenGas, eth: ethGas } = this.getGasFee()
+
+ return (
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `$${fiatGas} USD`),
+
+ h(
+ 'div.confirm-screen-row-detail',
+ tokenGas ? `${tokenGas} ${symbol}` : `${ethGas} ETH`
+ ),
+ ]),
+ ])
+ )
+}
+
+ConfirmSendToken.prototype.renderTotalPlusGas = function () {
+ const { token: { symbol } } = this.props
+ const { fiat: fiatAmount, token: tokenAmount } = this.getAmount()
+ const { fiat: fiatGas, token: tokenGas } = this.getGasFee()
+
+ return fiatAmount && fiatGas
+ ? (
+ h('section.flex-row.flex-center.confirm-screen-total-box ', [
+ h('div.confirm-screen-section-column', [
+ h('span.confirm-screen-label', [ 'Total ' ]),
+ h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]),
+ ]),
+
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`),
+ h('div.confirm-screen-row-detail', `${tokenAmount + tokenGas} ${symbol}`),
+ ]),
+ ])
+ )
+ : (
+ h('section.flex-row.flex-center.confirm-screen-total-box ', [
+ h('div.confirm-screen-section-column', [
+ h('span.confirm-screen-label', [ 'Total ' ]),
+ h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]),
+ ]),
+
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `${tokenAmount} ${symbol}`),
+ h('div.confirm-screen-row-detail', `+ ${fiatGas} USD Gas`),
+ ]),
+ ])
+ )
+}
+
+ConfirmSendToken.prototype.render = function () {
+ const { backToAccountDetail, selectedAddress } = this.props
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ const {
+ from: {
+ address: fromAddress,
+ name: fromName,
+ },
+ to: {
+ address: toAddress,
+ name: toName,
+ },
+ } = this.getData()
+
+ this.inputs = []
+
+ return (
+ h('div.confirm-screen-container', {
+ style: { minWidth: '355px' },
+ }, [
+ // Main Send token Card
+ h('div.confirm-screen-wrapper.flex-column.flex-grow', [
+ h('h3.flex-center.confirm-screen-header', [
+ h('button.confirm-screen-back-button', {
+ onClick: () => backToAccountDetail(selectedAddress),
+ }, 'BACK'),
+ h('div.confirm-screen-title', 'Confirm Transaction'),
+ h('div.confirm-screen-header-tip'),
+ ]),
+ h('div.flex-row.flex-center.confirm-screen-identicons', [
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: fromAddress,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', fromName),
+ // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)),
+ ]),
+ h('i.fa.fa-arrow-right.fa-lg'),
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: txParams.to,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', toName),
+ // h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)),
+ ]),
+ ]),
+
+ // h('h3.flex-center.confirm-screen-sending-to-message', {
+ // style: {
+ // textAlign: 'center',
+ // fontSize: '16px',
+ // },
+ // }, [
+ // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`,
+ // ]),
+
+ this.renderHeroAmount(),
+
+ h('div.confirm-screen-rows', [
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', fromName),
+ h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`),
+ ]),
+ ]),
+
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', toName),
+ h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`),
+ ]),
+ ]),
+
+ this.renderGasFee(),
+
+ this.renderTotalPlusGas(),
+
+ ]),
+ ]),
+
+ h('form#pending-tx-form', {
+ onSubmit: this.onSubmit,
+ }, [
+ // Cancel Button
+ h('div.cancel.btn-light.confirm-screen-cancel-button', {
+ onClick: (event) => this.cancel(event, txMeta),
+ }, 'CANCEL'),
+
+ // Accept Button
+ h('button.confirm-screen-confirm-button', ['CONFIRM']),
+ ]),
+
+
+ ])
+ )
+}
+
+ConfirmSendToken.prototype.onSubmit = function (event) {
+ event.preventDefault()
+ const txMeta = this.gatherTxMeta()
+ const valid = this.checkValidity()
+ this.setState({ valid, submitting: true })
+
+ if (valid && this.verifyGasParams()) {
+ this.props.sendTransaction(txMeta, event)
+ } else {
+ this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
+ this.setState({ submitting: false })
+ }
+}
+
+ConfirmSendToken.prototype.cancel = function (event, txMeta) {
+ event.preventDefault()
+ this.props.cancelTransaction(txMeta)
+}
+
+ConfirmSendToken.prototype.checkValidity = function () {
+ const form = this.getFormEl()
+ const valid = form.checkValidity()
+ return valid
+}
+
+ConfirmSendToken.prototype.getFormEl = function () {
+ const form = document.querySelector('form#pending-tx-form')
+ // Stub out form for unit tests:
+ if (!form) {
+ return { checkValidity () { return true } }
+ }
+ return form
+}
+
+// After a customizable state value has been updated,
+ConfirmSendToken.prototype.gatherTxMeta = function () {
+ const props = this.props
+ const state = this.state
+ const txData = clone(state.txData) || clone(props.txData)
+
+ // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`)
+ return txData
+}
+
+ConfirmSendToken.prototype.verifyGasParams = function () {
+ // We call this in case the gas has not been modified at all
+ if (!this.state) { return true }
+ return (
+ this._notZeroOrEmptyString(this.state.gas) &&
+ this._notZeroOrEmptyString(this.state.gasPrice)
+ )
+}
+
+ConfirmSendToken.prototype._notZeroOrEmptyString = function (obj) {
+ return obj !== '' && obj !== '0x0'
+}
+
+ConfirmSendToken.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) {
+ const numBN = new BN(numerator)
+ const denomBN = new BN(denominator)
+ return targetBN.mul(numBN).div(denomBN)
+}
diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js
new file mode 100644
index 000000000..770fb1dfd
--- /dev/null
+++ b/ui/app/components/pending-tx/index.js
@@ -0,0 +1,148 @@
+const Component = require('react').Component
+const { connect } = require('react-redux')
+const h = require('react-hyperscript')
+const clone = require('clone')
+const abi = require('human-standard-token-abi')
+const abiDecoder = require('abi-decoder')
+abiDecoder.addABI(abi)
+const inherits = require('util').inherits
+const actions = require('../../actions')
+const util = require('../../util')
+const ConfirmSendEther = require('./confirm-send-ether')
+const ConfirmSendToken = require('./confirm-send-token')
+const ConfirmDeployContract = require('./confirm-deploy-contract')
+
+const TX_TYPES = {
+ DEPLOY_CONTRACT: 'deploy_contract',
+ SEND_ETHER: 'send_ether',
+ SEND_TOKEN: 'send_token',
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(PendingTx)
+
+function mapStateToProps (state) {
+ const {
+ conversionRate,
+ identities,
+ } = state.metamask
+ const accounts = state.metamask.accounts
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ return {
+ conversionRate,
+ identities,
+ selectedAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
+ backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)),
+ cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
+ }
+}
+
+inherits(PendingTx, Component)
+function PendingTx () {
+ Component.call(this)
+ this.state = {
+ isFetching: true,
+ transactionType: '',
+ tokenAddress: '',
+ tokenSymbol: '',
+ tokenDecimals: '',
+ }
+}
+
+PendingTx.prototype.componentWillMount = async function () {
+ const txMeta = this.gatherTxMeta()
+ const txParams = txMeta.txParams || {}
+
+ this.props.setCurrentCurrencyToUSD()
+
+ if (!txParams.to) {
+ return this.setState({
+ transactionType: TX_TYPES.DEPLOY_CONTRACT,
+ isFetching: false,
+ })
+ }
+
+ try {
+ const token = util.getContractAtAddress(txParams.to)
+ const results = await Promise.all([
+ token.symbol(),
+ token.decimals(),
+ ])
+
+ const [ symbol, decimals ] = results
+
+ if (symbol[0] && decimals[0]) {
+ this.setState({
+ transactionType: TX_TYPES.SEND_TOKEN,
+ tokenAddress: txParams.to,
+ tokenSymbol: symbol[0],
+ tokenDecimals: decimals[0],
+ isFetching: false,
+ })
+ } else {
+ this.setState({
+ transactionType: TX_TYPES.SEND_ETHER,
+ isFetching: false,
+ })
+ }
+ } catch (e) {
+ this.setState({
+ transactionType: TX_TYPES.SEND_ETHER,
+ isFetching: false,
+ })
+ }
+}
+
+PendingTx.prototype.gatherTxMeta = function () {
+ const props = this.props
+ const state = this.state
+ const txData = clone(state.txData) || clone(props.txData)
+
+ return txData
+}
+
+PendingTx.prototype.render = function () {
+ const {
+ isFetching,
+ transactionType,
+ tokenAddress,
+ tokenSymbol,
+ tokenDecimals,
+ } = this.state
+
+ const { sendTransaction } = this.props
+
+ if (isFetching) {
+ return h('noscript')
+ }
+
+ switch (transactionType) {
+ case TX_TYPES.SEND_ETHER:
+ return h(ConfirmSendEther, {
+ txData: this.gatherTxMeta(),
+ sendTransaction,
+ })
+ case TX_TYPES.SEND_TOKEN:
+ return h(ConfirmSendToken, {
+ txData: this.gatherTxMeta(),
+ sendTransaction,
+ token: {
+ address: tokenAddress,
+ symbol: tokenSymbol,
+ decimals: tokenDecimals,
+ },
+ })
+ case TX_TYPES.DEPLOY_CONTRACT:
+ return h(ConfirmDeployContract, {
+ txData: this.gatherTxMeta(),
+ sendTransaction,
+ })
+ default:
+ return h('noscript')
+ }
+}
diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js
index 06b9aed9b..cc723df14 100644
--- a/ui/app/components/qr-code.js
+++ b/ui/app/components/qr-code.js
@@ -4,13 +4,13 @@ const qrCode = require('qrcode-npm').qrcode
const inherits = require('util').inherits
const connect = require('react-redux').connect
const isHexPrefixed = require('ethereumjs-util').isHexPrefixed
-const CopyButton = require('./copyButton')
+const ReadOnlyInput = require('./readonly-input')
module.exports = connect(mapStateToProps)(QrCodeView)
function mapStateToProps (state) {
return {
- Qr: state.appState.Qr,
+ // Qr code is not fetched from state. 'message' and 'data' props are passed instead.
buyView: state.appState.buyView,
warning: state.appState.warning,
}
@@ -29,46 +29,29 @@ QrCodeView.prototype.render = function () {
const qrImage = qrCode(4, 'M')
qrImage.addData(address)
qrImage.make()
- return h('.main-container.flex-column', {
- key: 'qr',
+ return h('.div.flex-column.flex-center', {
style: {
- justifyContent: 'center',
- paddingBottom: '45px',
- paddingLeft: '45px',
- paddingRight: '45px',
- alignItems: 'center',
},
}, [
Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('.qr-header', Qr.message),
this.props.warning ? this.props.warning && h('span.error.flex-center', {
style: {
- textAlign: 'center',
- width: '229px',
- height: '82px',
},
},
this.props.warning) : null,
- h('#qr-container.flex-column', {
- style: {
- marginTop: '25px',
- marginBottom: '15px',
- },
+ h('.div.qr-wrapper', {
+ style: {},
dangerouslySetInnerHTML: {
__html: qrImage.createTableTag(4),
},
}),
- h('.flex-row', [
- h('h3.ellip-address', {
- style: {
- width: '247px',
- },
- }, Qr.data),
- h(CopyButton, {
- value: Qr.data,
- }),
- ]),
+ h(ReadOnlyInput, {
+ wrapperClass: 'ellip-address-wrapper',
+ inputClass: 'qr-ellip-address',
+ value: Qr.data,
+ }),
])
}
diff --git a/ui/app/components/readonly-input.js b/ui/app/components/readonly-input.js
new file mode 100644
index 000000000..fcf05fb9e
--- /dev/null
+++ b/ui/app/components/readonly-input.js
@@ -0,0 +1,33 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = ReadOnlyInput
+
+inherits(ReadOnlyInput, Component)
+function ReadOnlyInput () {
+ Component.call(this)
+}
+
+ReadOnlyInput.prototype.render = function () {
+ const {
+ wrapperClass = '',
+ inputClass = '',
+ value,
+ textarea,
+ onClick,
+ } = this.props
+
+ const inputType = textarea ? 'textarea' : 'input'
+
+ return h('div', {className: wrapperClass}, [
+ h(inputType, {
+ className: inputClass,
+ value,
+ readOnly: true,
+ onFocus: event => event.target.select(),
+ onClick,
+ }),
+ ])
+}
+
diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js
new file mode 100644
index 000000000..a95a0a6d8
--- /dev/null
+++ b/ui/app/components/send-token/index.js
@@ -0,0 +1,440 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const classnames = require('classnames')
+const abi = require('ethereumjs-abi')
+const inherits = require('util').inherits
+const actions = require('../../actions')
+const selectors = require('../../selectors')
+const { isValidAddress, allNull } = require('../../util')
+
+// const BalanceComponent = require('./balance-component')
+const Identicon = require('../identicon')
+const TokenBalance = require('../token-balance')
+const CurrencyToggle = require('../send/currency-toggle')
+const GasTooltip = require('../send/gas-tooltip')
+const GasFeeDisplay = require('../send/gas-fee-display')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(SendTokenScreen)
+
+function mapStateToProps (state) {
+ // const sidebarOpen = state.appState.sidebarOpen
+
+ const { warning } = state.appState
+ const identities = state.metamask.identities
+ const addressBook = state.metamask.addressBook
+ const conversionRate = state.metamask.conversionRate
+ const currentBlockGasLimit = state.metamask.currentBlockGasLimit
+ const accounts = state.metamask.accounts
+ const selectedTokenAddress = state.metamask.selectedTokenAddress
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ const selectedToken = selectors.getSelectedToken(state)
+ const tokenExchangeRates = state.metamask.tokenExchangeRates
+ const pair = `${selectedToken.symbol.toLowerCase()}_eth`
+ const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {}
+
+ return {
+ selectedAddress,
+ selectedTokenAddress,
+ identities,
+ addressBook,
+ conversionRate,
+ tokenExchangeRate,
+ currentBlockGasLimit,
+ selectedToken,
+ warning,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)),
+ hideWarning: () => dispatch(actions.hideWarning()),
+ addToAddressBook: (recipient, nickname) => dispatch(
+ actions.addToAddressBook(recipient, nickname)
+ ),
+ signTx: txParams => dispatch(actions.signTx(txParams)),
+ signTokenTx: (tokenAddress, toAddress, amount, txData) => (
+ dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData))
+ ),
+ updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)),
+ estimateGas: params => dispatch(actions.estimateGas(params)),
+ getGasPrice: () => dispatch(actions.getGasPrice()),
+ }
+}
+
+inherits(SendTokenScreen, Component)
+function SendTokenScreen () {
+ Component.call(this)
+ this.state = {
+ to: '',
+ amount: '0x0',
+ amountToSend: '0x0',
+ selectedCurrency: 'USD',
+ isGasTooltipOpen: false,
+ gasPrice: null,
+ gasLimit: null,
+ errors: {},
+ }
+}
+
+SendTokenScreen.prototype.componentWillMount = function () {
+ const {
+ updateTokenExchangeRate,
+ selectedToken: { symbol },
+ getGasPrice,
+ estimateGas,
+ selectedAddress,
+ } = this.props
+
+ updateTokenExchangeRate(symbol)
+
+ const data = Array.prototype.map.call(
+ abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']),
+ x => ('00' + x.toString(16)).slice(-2)
+ ).join('')
+
+ console.log(data)
+ Promise.all([
+ getGasPrice(),
+ estimateGas({
+ from: selectedAddress,
+ value: '0x0',
+ gas: '746a528800',
+ data,
+ }),
+ ])
+ .then(([blockGasPrice, estimatedGas]) => {
+ console.log({ blockGasPrice, estimatedGas})
+ this.setState({
+ gasPrice: blockGasPrice,
+ gasLimit: estimatedGas,
+ })
+ })
+}
+
+SendTokenScreen.prototype.validate = function () {
+ const {
+ to,
+ amount: stringAmount,
+ gasPrice: hexGasPrice,
+ gasLimit: hexGasLimit,
+ } = this.state
+
+ const gasPrice = parseInt(hexGasPrice, 16)
+ const gasLimit = parseInt(hexGasLimit, 16) / 1000000000
+ const amount = Number(stringAmount)
+
+ const errors = {
+ to: !to ? 'Required' : null,
+ amount: !amount ? 'Required' : null,
+ gasPrice: !gasPrice ? 'Gas Price Required' : null,
+ gasLimit: !gasLimit ? 'Gas Limit Required' : null,
+ }
+
+ if (to && !isValidAddress(to)) {
+ errors.to = 'Invalid address'
+ }
+
+ const isValid = Object.entries(errors).every(([key, value]) => value === null)
+ return {
+ isValid,
+ errors: isValid ? {} : errors,
+ }
+}
+
+SendTokenScreen.prototype.setErrorsFor = function (field) {
+ const { balance, selectedToken } = this.props
+ const { errors: previousErrors } = this.state
+
+ const {
+ isValid,
+ errors: newErrors
+ } = this.validate()
+
+ const nextErrors = Object.assign({}, previousErrors, {
+ [field]: newErrors[field] || null
+ })
+
+ if (!isValid) {
+ this.setState({
+ errors: nextErrors,
+ isValid,
+ })
+ }
+}
+
+SendTokenScreen.prototype.clearErrorsFor = function (field) {
+ const { errors: previousErrors } = this.state
+ const nextErrors = Object.assign({}, previousErrors, {
+ [field]: null
+ })
+
+ this.setState({
+ errors: nextErrors,
+ isValid: allNull(nextErrors),
+ })
+}
+
+SendTokenScreen.prototype.getAmountToSend = function (amount, selectedToken) {
+ const { decimals } = selectedToken || {}
+ const multiplier = Math.pow(10, Number(decimals || 0))
+ const sendAmount = '0x' + Number(amount * multiplier).toString(16)
+ return sendAmount
+}
+
+SendTokenScreen.prototype.submit = function () {
+ const {
+ to,
+ amount,
+ gasPrice,
+ gasLimit,
+ } = this.state
+
+ const {
+ identities,
+ selectedAddress,
+ selectedTokenAddress,
+ hideWarning,
+ addToAddressBook,
+ signTokenTx,
+ selectedToken,
+ } = this.props
+
+ const { nickname = ' ' } = identities[to] || {}
+
+ hideWarning()
+ addToAddressBook(to, nickname)
+
+ const txParams = {
+ from: selectedAddress,
+ value: '0',
+ gas: gasLimit,
+ gasPrice: gasPrice,
+ }
+
+ const sendAmount = this.getAmountToSend(amount, selectedToken)
+
+ signTokenTx(selectedTokenAddress, to, sendAmount, txParams)
+}
+
+SendTokenScreen.prototype.renderToAddressInput = function () {
+ const {
+ identities,
+ addressBook,
+ } = this.props
+
+ const {
+ to,
+ errors: { to: errorMessage },
+ } = this.state
+
+ return h('div', {
+ className: classnames('send-screen-input-wrapper', {
+ 'send-screen-input-wrapper--error': errorMessage,
+ }),
+ }, [
+ h('div', ['To:']),
+ h('input.large-input.send-screen-input', {
+ name: 'address',
+ list: 'addresses',
+ placeholder: 'Address',
+ value: to,
+ onChange: e => this.setState({
+ to: e.target.value,
+ errors: {},
+ }),
+ onBlur: () => {
+ this.setErrorsFor('to')
+ },
+ onFocus: event => {
+ if (to) event.target.select()
+ this.clearErrorsFor('to')
+ },
+ }),
+ h('datalist#addresses', [
+ // Corresponds to the addresses owned.
+ Object.entries(identities).map(([key, { address, name }]) => {
+ return h('option', {
+ value: address,
+ label: name,
+ key: address,
+ })
+ }),
+ addressBook.map(({ address, name }) => {
+ return h('option', {
+ value: address,
+ label: name,
+ key: address,
+ })
+ }),
+ ]),
+ h('div.send-screen-input-wrapper__error-message', [ errorMessage ]),
+ ])
+}
+
+SendTokenScreen.prototype.renderAmountInput = function () {
+ const {
+ selectedCurrency,
+ amount,
+ errors: { amount: errorMessage },
+ } = this.state
+
+ const {
+ tokenExchangeRate,
+ selectedToken: {symbol},
+ } = this.props
+
+ return h('div.send-screen-input-wrapper', {
+ className: classnames('send-screen-input-wrapper', {
+ 'send-screen-input-wrapper--error': errorMessage,
+ }),
+ }, [
+ h('div.send-screen-amount-labels', [
+ h('span', ['Amount']),
+ h(CurrencyToggle, {
+ currentCurrency: tokenExchangeRate ? selectedCurrency : 'USD',
+ currencies: tokenExchangeRate ? [ symbol, 'USD' ] : [],
+ onClick: currency => this.setState({ selectedCurrency: currency }),
+ }),
+ ]),
+ h('input.large-input.send-screen-input', {
+ placeholder: `0 ${symbol}`,
+ type: 'number',
+ value: amount,
+ onChange: e => this.setState({
+ amount: e.target.value,
+ }),
+ onBlur: () => {
+ this.setErrorsFor('amount')
+ },
+ onFocus: () => this.clearErrorsFor('amount'),
+ }),
+ h('div.send-screen-input-wrapper__error-message', [ errorMessage ]),
+ ])
+}
+
+SendTokenScreen.prototype.renderGasInput = function () {
+ const {
+ isGasTooltipOpen,
+ gasPrice,
+ gasLimit,
+ selectedCurrency,
+ errors: {
+ gasPrice: gasPriceErrorMessage,
+ gasLimit: gasLimitErrorMessage,
+ },
+ } = this.state
+
+ const {
+ conversionRate,
+ tokenExchangeRate,
+ currentBlockGasLimit,
+ } = this.props
+
+ return h('div.send-screen-input-wrapper', {
+ className: classnames('send-screen-input-wrapper', {
+ 'send-screen-input-wrapper--error': gasPriceErrorMessage || gasLimitErrorMessage,
+ }),
+ }, [
+ isGasTooltipOpen && h(GasTooltip, {
+ className: 'send-tooltip',
+ gasPrice: gasPrice || '0x0',
+ gasLimit: gasLimit || '0x0',
+ onClose: () => this.setState({ isGasTooltipOpen: false }),
+ onFeeChange: ({ gasLimit, gasPrice }) => {
+ this.setState({ gasLimit, gasPrice, errors: {} })
+ },
+ onBlur: () => {
+ this.setErrorsFor('gasLimit')
+ this.setErrorsFor('gasPrice')
+ },
+ onFocus: () => {
+ this.clearErrorsFor('gasLimit')
+ this.clearErrorsFor('gasPrice')
+ },
+ }),
+
+ h('div.send-screen-gas-labels', {}, [
+ h('span', [ h('i.fa.fa-bolt'), 'Gas fee:']),
+ h('span', ['What\'s this?']),
+ ]),
+ h('div.large-input.send-screen-gas-input', [
+ h(GasFeeDisplay, {
+ conversionRate,
+ tokenExchangeRate,
+ gasPrice: gasPrice || '0x0',
+ activeCurrency: selectedCurrency,
+ gas: gasLimit || '0x0',
+ blockGasLimit: currentBlockGasLimit,
+ }),
+ h(
+ 'div.send-screen-gas-input-customize',
+ { onClick: () => this.setState({ isGasTooltipOpen: !isGasTooltipOpen }) },
+ ['Customize']
+ ),
+ ]),
+ h('div.send-screen-input-wrapper__error-message', [
+ gasPriceErrorMessage || gasLimitErrorMessage,
+ ]),
+ ])
+}
+
+SendTokenScreen.prototype.renderMemoInput = function () {
+ return h('div.send-screen-input-wrapper', [
+ h('div', {}, ['Transaction memo (optional)']),
+ h(
+ 'input.large-input.send-screen-input',
+ { onChange: e => this.setState({ memo: e.target.value }) }
+ ),
+ ])
+}
+
+SendTokenScreen.prototype.renderButtons = function () {
+ const { selectedAddress, backToAccountDetail } = this.props
+ const { isValid } = this.validate()
+
+ return h('div.send-token__button-group', [
+ h('button.send-token__button-next.btn-secondary', {
+ className: !isValid && 'send-screen__send-button__disabled',
+ onClick: () => isValid && this.submit(),
+ }, ['Next']),
+ h('button.send-token__button-cancel.btn-tertiary', {
+ onClick: () => backToAccountDetail(selectedAddress),
+ }, ['Cancel']),
+ ])
+}
+
+SendTokenScreen.prototype.render = function () {
+ const {
+ selectedTokenAddress,
+ selectedToken,
+ warning,
+ } = this.props
+
+ return h('div.send-token', [
+ h('div.send-token__content', [
+ h(Identicon, {
+ diameter: 75,
+ address: selectedTokenAddress,
+ }),
+ h('div.send-token__title', ['Send Tokens']),
+ h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']),
+ h('div.send-token__balance-text', ['Your Token Balance is:']),
+ h('div.send-token__token-balance', [
+ h(TokenBalance, { token: selectedToken, balanceOnly: true }),
+ ]),
+ h('div.send-token__token-symbol', [selectedToken.symbol]),
+ this.renderToAddressInput(),
+ this.renderAmountInput(),
+ this.renderGasInput(),
+ this.renderMemoInput(),
+ warning && h('div.send-screen-input-wrapper--error', {},
+ h('div.send-screen-input-wrapper__error-message', [
+ warning,
+ ])
+ ),
+ ]),
+ this.renderButtons(),
+ ])
+}
diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js
new file mode 100644
index 000000000..64acde767
--- /dev/null
+++ b/ui/app/components/send/account-list-item.js
@@ -0,0 +1,66 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const connect = require('react-redux').connect
+const Identicon = require('../identicon')
+const CurrencyDisplay = require('./currency-display')
+const { conversionRateSelector } = require('../../selectors')
+
+inherits(AccountListItem, Component)
+function AccountListItem () {
+ Component.call(this)
+}
+
+function mapStateToProps(state) {
+ return {
+ conversionRate: conversionRateSelector(state)
+ }
+}
+
+module.exports = connect(mapStateToProps)(AccountListItem)
+
+AccountListItem.prototype.render = function () {
+ const {
+ account,
+ handleClick,
+ icon = null,
+ conversionRate,
+ } = this.props
+
+ const { name, address, balance } = account
+
+ return h('div.account-list-item', {
+ onClick: () => handleClick({ name, address, balance }),
+ }, [
+
+ h('div.account-list-item__top-row', {}, [
+
+ h(
+ Identicon,
+ {
+ address,
+ diameter: 18,
+ className: 'account-list-item__identicon',
+ },
+ ),
+
+ h('div.account-list-item__account-name', {}, name),
+
+ icon && h('div.account-list-item__icon', [icon]),
+
+ ]),
+
+ h(CurrencyDisplay, {
+ primaryCurrency: 'ETH',
+ convertedCurrency: 'USD',
+ value: balance,
+ conversionRate,
+ convertedPrefix: '$',
+ readOnly: true,
+ className: 'account-list-item__account-balances',
+ primaryBalanceClassName: 'account-list-item__account-primary-balance',
+ convertedBalanceClassName: 'account-list-item__account-secondary-balance',
+ }, name),
+
+ ])
+}
\ No newline at end of file
diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js
new file mode 100644
index 000000000..f7fbb2379
--- /dev/null
+++ b/ui/app/components/send/currency-display.js
@@ -0,0 +1,126 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('../identicon')
+const { conversionUtil } = require('../../conversion-util')
+
+module.exports = CurrencyDisplay
+
+inherits(CurrencyDisplay, Component)
+function CurrencyDisplay () {
+ Component.call(this)
+
+ this.state = {
+ value: null,
+ }
+}
+
+function isValidInput (text) {
+ const re = /^([1-9]\d*|0)(\.|\.\d*)?$/
+ return re.test(text)
+}
+
+function resetCaretIfPastEnd (value, event) {
+ const caretPosition = event.target.selectionStart
+
+ if (caretPosition > value.length) {
+ event.target.setSelectionRange(value.length, value.length)
+ }
+}
+
+function toHexWei (value) {
+ return conversionUtil(value, {
+ fromNumericBase: 'dec',
+ toNumericBase: 'hex',
+ toDenomination: 'WEI',
+ })
+}
+
+CurrencyDisplay.prototype.render = function () {
+ const {
+ className = 'currency-display',
+ primaryBalanceClassName = 'currency-display__input',
+ convertedBalanceClassName = 'currency-display__converted-value',
+ conversionRate,
+ primaryCurrency,
+ convertedCurrency,
+ convertedPrefix = '',
+ placeholder = '0',
+ readOnly = false,
+ inError = false,
+ value: initValue,
+ handleChange,
+ validate,
+ } = this.props
+ const { value } = this.state
+
+ const initValueToRender = conversionUtil(initValue, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromDenomination: 'WEI',
+ numberOfDecimals: 6,
+ conversionRate,
+ })
+
+ const convertedValue = conversionUtil(value || initValueToRender, {
+ fromNumericBase: 'dec',
+ fromCurrency: primaryCurrency,
+ toCurrency: convertedCurrency,
+ numberOfDecimals: 2,
+ conversionRate,
+ })
+
+ return h('div', {
+ className,
+ style: {
+ borderColor: inError ? 'red' : null,
+ },
+ }, [
+
+ h('div.currency-display__primary-row', [
+
+ h('div.currency-display__input-wrapper', [
+
+ h('input', {
+ className: primaryBalanceClassName,
+ value: `${value || initValueToRender} ${primaryCurrency}`,
+ placeholder: `${0} ${primaryCurrency}`,
+ readOnly,
+ onChange: (event) => {
+ let newValue = event.target.value.split(' ')[0]
+
+ if (newValue === '') {
+ this.setState({ value: '0' })
+ }
+ else if (newValue.match(/^0[1-9]$/)) {
+ this.setState({ value: newValue.match(/[1-9]/)[0] })
+ }
+ else if (newValue && !isValidInput(newValue)) {
+ event.preventDefault()
+ }
+ else {
+ this.setState({ value: newValue })
+ }
+ },
+ onBlur: event => !readOnly && handleChange(toHexWei(event.target.value.split(' ')[0])),
+ onKeyUp: event => {
+ if (!readOnly) {
+ validate(toHexWei(value || initValueToRender))
+ resetCaretIfPastEnd(value || initValueToRender, event)
+ }
+ },
+ onClick: event => !readOnly && resetCaretIfPastEnd(value || initValueToRender, event),
+ }),
+
+ ]),
+
+ ]),
+
+ h('div', {
+ className: convertedBalanceClassName,
+ }, `${convertedPrefix}${convertedValue} ${convertedCurrency}`),
+
+ ])
+
+}
+
diff --git a/ui/app/components/send/currency-toggle.js b/ui/app/components/send/currency-toggle.js
new file mode 100644
index 000000000..7aaccd490
--- /dev/null
+++ b/ui/app/components/send/currency-toggle.js
@@ -0,0 +1,44 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const classnames = require('classnames')
+
+module.exports = CurrencyToggle
+
+inherits(CurrencyToggle, Component)
+function CurrencyToggle () {
+ Component.call(this)
+}
+
+const defaultCurrencies = [ 'ETH', 'USD' ]
+
+CurrencyToggle.prototype.renderToggles = function () {
+ const { onClick, activeCurrency } = this.props
+ const [currencyA, currencyB] = this.props.currencies || defaultCurrencies
+
+ return [
+ h('span', {
+ className: classnames('currency-toggle__item', {
+ 'currency-toggle__item--selected': currencyA === activeCurrency,
+ }),
+ onClick: () => onClick(currencyA),
+ }, [ currencyA ]),
+ '<>',
+ h('span', {
+ className: classnames('currency-toggle__item', {
+ 'currency-toggle__item--selected': currencyB === activeCurrency,
+ }),
+ onClick: () => onClick(currencyB),
+ }, [ currencyB ]),
+ ]
+}
+
+CurrencyToggle.prototype.render = function () {
+ const currencies = this.props.currencies || defaultCurrencies
+
+ return h('span.currency-toggle', currencies.length
+ ? this.renderToggles()
+ : []
+ )
+}
+
diff --git a/ui/app/components/send/eth-fee-display.js b/ui/app/components/send/eth-fee-display.js
new file mode 100644
index 000000000..8b4cec16c
--- /dev/null
+++ b/ui/app/components/send/eth-fee-display.js
@@ -0,0 +1,37 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const EthBalance = require('../eth-balance')
+const { getTxFeeBn } = require('../../util')
+
+module.exports = EthFeeDisplay
+
+inherits(EthFeeDisplay, Component)
+function EthFeeDisplay () {
+ Component.call(this)
+}
+
+EthFeeDisplay.prototype.render = function () {
+ const {
+ activeCurrency,
+ conversionRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ } = this.props
+
+ return h(EthBalance, {
+ value: getTxFeeBn(gas, gasPrice, blockGasLimit),
+ currentCurrency: activeCurrency,
+ conversionRate,
+ showFiat: false,
+ hideTooltip: true,
+ styleOveride: {
+ color: '#5d5d5d',
+ fontSize: '16px',
+ fontFamily: 'DIN OT',
+ lineHeight: '22.4px'
+ }
+ })
+}
+
diff --git a/ui/app/components/send/from-dropdown.js b/ui/app/components/send/from-dropdown.js
new file mode 100644
index 000000000..6f2b9da68
--- /dev/null
+++ b/ui/app/components/send/from-dropdown.js
@@ -0,0 +1,74 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('../identicon')
+const AccountListItem = require('./account-list-item')
+
+module.exports = FromDropdown
+
+inherits(FromDropdown, Component)
+function FromDropdown () {
+ Component.call(this)
+}
+
+FromDropdown.prototype.getListItemIcon = function (currentAccount, selectedAccount) {
+ const listItemIcon = h(`i.fa.fa-check.fa-lg`, { style: { color: '#02c9b1' } })
+
+ return currentAccount.address === selectedAccount.address
+ ? listItemIcon
+ : null
+}
+
+FromDropdown.prototype.renderDropdown = function () {
+ const {
+ accounts,
+ selectedAccount,
+ closeDropdown,
+ onSelect,
+ } = this.props
+
+ return h('div', {}, [
+
+ h('div.send-v2__from-dropdown__close-area', {
+ onClick: closeDropdown,
+ }),
+
+ h('div.send-v2__from-dropdown__list', {}, [
+
+ ...accounts.map(account => h(AccountListItem, {
+ account,
+ handleClick: () => {
+ onSelect(account)
+ closeDropdown()
+ },
+ icon: this.getListItemIcon(account, selectedAccount),
+ }))
+
+ ]),
+
+ ])
+}
+
+FromDropdown.prototype.render = function () {
+ const {
+ accounts,
+ selectedAccount,
+ openDropdown,
+ closeDropdown,
+ dropdownOpen,
+ } = this.props
+
+ return h('div.send-v2__from-dropdown', {}, [
+
+ h(AccountListItem, {
+ account: selectedAccount,
+ handleClick: openDropdown,
+ icon: h(`i.fa.fa-caret-down.fa-lg`, { style: { color: '#dedede' } })
+ }),
+
+ dropdownOpen && this.renderDropdown(),
+
+ ])
+
+}
+
diff --git a/ui/app/components/send/gas-fee-display-v2.js b/ui/app/components/send/gas-fee-display-v2.js
new file mode 100644
index 000000000..7c3913c7f
--- /dev/null
+++ b/ui/app/components/send/gas-fee-display-v2.js
@@ -0,0 +1,42 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const CurrencyDisplay = require('./currency-display')
+
+module.exports = GasFeeDisplay
+
+inherits(GasFeeDisplay, Component)
+function GasFeeDisplay () {
+ Component.call(this)
+}
+
+GasFeeDisplay.prototype.render = function () {
+ const {
+ conversionRate,
+ gasTotal,
+ onClick,
+ } = this.props
+
+ return h('div', [
+
+ gasTotal
+ ? h(CurrencyDisplay, {
+ primaryCurrency: 'ETH',
+ convertedCurrency: 'USD',
+ value: gasTotal,
+ conversionRate,
+ convertedPrefix: '$',
+ readOnly: true,
+ })
+ : h('div.currency-display', 'Loading...')
+ ,
+
+ h('div.send-v2__sliders-icon-container', {
+ onClick,
+ }, [
+ h('i.fa.fa-sliders.send-v2__sliders-icon'),
+ ])
+
+ ])
+}
+
diff --git a/ui/app/components/send/gas-fee-display.js b/ui/app/components/send/gas-fee-display.js
new file mode 100644
index 000000000..a9a3f3f49
--- /dev/null
+++ b/ui/app/components/send/gas-fee-display.js
@@ -0,0 +1,62 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const USDFeeDisplay = require('./usd-fee-display')
+const EthFeeDisplay = require('./eth-fee-display')
+const { getTxFeeBn, formatBalance, shortenBalance } = require('../../util')
+
+module.exports = GasFeeDisplay
+
+inherits(GasFeeDisplay, Component)
+function GasFeeDisplay () {
+ Component.call(this)
+}
+
+GasFeeDisplay.prototype.getTokenValue = function () {
+ const {
+ tokenExchangeRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ } = this.props
+
+ const value = formatBalance(getTxFeeBn(gas, gasPrice, blockGasLimit), 6, true)
+ const [ethNumber] = value.split(' ')
+
+ return shortenBalance(Number(ethNumber) / tokenExchangeRate, 6)
+}
+
+GasFeeDisplay.prototype.render = function () {
+ const {
+ activeCurrency,
+ conversionRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ } = this.props
+
+ switch (activeCurrency) {
+ case 'USD':
+ return h(USDFeeDisplay, {
+ activeCurrency,
+ conversionRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ })
+ case 'ETH':
+ return h(EthFeeDisplay, {
+ activeCurrency,
+ conversionRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ })
+ default:
+ return h('div.token-gas', [
+ h('div.token-gas__amount', this.getTokenValue()),
+ h('div.token-gas__symbol', activeCurrency),
+ ])
+ }
+}
+
diff --git a/ui/app/components/send/gas-tooltip.js b/ui/app/components/send/gas-tooltip.js
new file mode 100644
index 000000000..46aff3499
--- /dev/null
+++ b/ui/app/components/send/gas-tooltip.js
@@ -0,0 +1,100 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const InputNumber = require('../input-number.js')
+
+module.exports = GasTooltip
+
+inherits(GasTooltip, Component)
+function GasTooltip () {
+ Component.call(this)
+ this.state = {
+ gasLimit: 0,
+ gasPrice: 0,
+ }
+
+ this.updateGasPrice = this.updateGasPrice.bind(this)
+ this.updateGasLimit = this.updateGasLimit.bind(this)
+ this.onClose = this.onClose.bind(this)
+}
+
+GasTooltip.prototype.componentWillMount = function () {
+ const { gasPrice = 0, gasLimit = 0} = this.props
+
+ this.setState({
+ gasPrice: parseInt(gasPrice, 16) / 1000000000,
+ gasLimit: parseInt(gasLimit, 16),
+ })
+}
+
+GasTooltip.prototype.updateGasPrice = function (newPrice) {
+ const { onFeeChange } = this.props
+ const { gasLimit } = this.state
+
+ this.setState({ gasPrice: newPrice })
+ onFeeChange({
+ gasLimit: gasLimit.toString(16),
+ gasPrice: (newPrice * 1000000000).toString(16),
+ })
+}
+
+GasTooltip.prototype.updateGasLimit = function (newLimit) {
+ const { onFeeChange } = this.props
+ const { gasPrice } = this.state
+
+ this.setState({ gasLimit: newLimit })
+ onFeeChange({
+ gasLimit: newLimit.toString(16),
+ gasPrice: (gasPrice * 1000000000).toString(16),
+ })
+}
+
+GasTooltip.prototype.onClose = function (e) {
+ e.stopPropagation()
+ this.props.onClose()
+}
+
+GasTooltip.prototype.render = function () {
+ const { gasPrice, gasLimit } = this.state
+
+ return h('div.gas-tooltip', {}, [
+ h('div.gas-tooltip-close-area', {
+ onClick: this.onClose,
+ }),
+ h('div.customize-gas-tooltip-container', {}, [
+ h('div.customize-gas-tooltip', {}, [
+ h('div.gas-tooltip-header.gas-tooltip-label', {}, ['Customize Gas']),
+ h('div.gas-tooltip-input-label', {}, [
+ h('span.gas-tooltip-label', {}, ['Gas Price']),
+ h('i.fa.fa-info-circle'),
+ ]),
+ h(InputNumber, {
+ unitLabel: 'GWEI',
+ step: 1,
+ min: 0,
+ placeholder: '0',
+ value: gasPrice,
+ onChange: (newPrice) => this.updateGasPrice(newPrice),
+ }),
+ h('div.gas-tooltip-input-label', {
+ style: {
+ 'marginTop': '81px',
+ },
+ }, [
+ h('span.gas-tooltip-label', {}, ['Gas Limit']),
+ h('i.fa.fa-info-circle'),
+ ]),
+ h(InputNumber, {
+ unitLabel: 'UNITS',
+ step: 1,
+ min: 0,
+ placeholder: '0',
+ value: gasLimit,
+ onChange: (newLimit) => this.updateGasLimit(newLimit),
+ }),
+ ]),
+ h('div.gas-tooltip-arrow', {}),
+ ]),
+ ])
+}
+
diff --git a/ui/app/components/send/memo-textarea.js b/ui/app/components/send/memo-textarea.js
new file mode 100644
index 000000000..4005b9493
--- /dev/null
+++ b/ui/app/components/send/memo-textarea.js
@@ -0,0 +1,33 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('../identicon')
+
+module.exports = MemoTextArea
+
+inherits(MemoTextArea, Component)
+function MemoTextArea () {
+ Component.call(this)
+}
+
+MemoTextArea.prototype.render = function () {
+ const { memo, identities, onChange } = this.props
+
+ return h('div.send-v2__memo-text-area', [
+
+ h('textarea.send-v2__memo-text-area__input', {
+ placeholder: 'Optional',
+ value: memo,
+ onChange,
+ // onBlur: () => {
+ // this.setErrorsFor('memo')
+ // },
+ onFocus: event => {
+ // this.clearErrorsFor('memo')
+ },
+ }),
+
+ ])
+
+}
+
diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js
new file mode 100644
index 000000000..ebe2b878b
--- /dev/null
+++ b/ui/app/components/send/send-v2-container.js
@@ -0,0 +1,82 @@
+const connect = require('react-redux').connect
+const actions = require('../../actions')
+const abi = require('ethereumjs-abi')
+const SendEther = require('../../send-v2')
+
+const { multiplyCurrencies } = require('../../conversion-util')
+
+const {
+ accountsWithSendEtherInfoSelector,
+ getCurrentAccountWithSendEtherInfo,
+ conversionRateSelector,
+ getSelectedToken,
+ getSelectedTokenExchangeRate,
+ getSelectedAddress,
+ getGasPrice,
+ getGasLimit,
+ getAddressBook,
+ getSendFrom,
+} = require('../../selectors')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(SendEther)
+
+function mapStateToProps (state) {
+ const fromAccounts = accountsWithSendEtherInfoSelector(state)
+ const selectedAddress = getSelectedAddress(state)
+ const selectedToken = getSelectedToken(state)
+ const tokenExchangeRates = state.metamask.tokenExchangeRates
+ const selectedTokenExchangeRate = getSelectedTokenExchangeRate(state)
+ const conversionRate = conversionRateSelector(state)
+
+ let data;
+ let primaryCurrency;
+ let tokenToUSDRate;
+ if (selectedToken) {
+ data = Array.prototype.map.call(
+ abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']),
+ x => ('00' + x.toString(16)).slice(-2)
+ ).join('')
+
+ primaryCurrency = selectedToken.symbol
+
+ tokenToUSDRate = multiplyCurrencies(
+ conversionRate,
+ selectedTokenExchangeRate,
+ { toNumericBase: 'dec' }
+ )
+ }
+
+ return {
+ ...state.metamask.send,
+ from: getSendFrom(state) || getCurrentAccountWithSendEtherInfo(state),
+ fromAccounts,
+ toAccounts: [...fromAccounts, ...getAddressBook(state)],
+ conversionRate,
+ selectedToken,
+ primaryCurrency,
+ data,
+ amountConversionRate: selectedToken ? tokenToUSDRate : conversionRate,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showCustomizeGasModal: () => dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })),
+ estimateGas: params => dispatch(actions.estimateGas(params)),
+ getGasPrice: () => dispatch(actions.getGasPrice()),
+ updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)),
+ signTokenTx: (tokenAddress, toAddress, amount, txData) => (
+ dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData))
+ ),
+ signTx: txParams => dispatch(actions.signTx(txParams)),
+ setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)),
+ addToAddressBook: address => dispatch(actions.addToAddressBook(address)),
+ updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)),
+ updateSendFrom: newFrom => dispatch(actions.updateSendFrom(newFrom)),
+ updateSendTo: newTo => dispatch(actions.updateSendTo(newTo)),
+ updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
+ updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
+ updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)),
+ goHome: () => dispatch(actions.goHome()),
+ }
+}
diff --git a/ui/app/components/send/to-autocomplete.js b/ui/app/components/send/to-autocomplete.js
new file mode 100644
index 000000000..686a7a23e
--- /dev/null
+++ b/ui/app/components/send/to-autocomplete.js
@@ -0,0 +1,55 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('../identicon')
+
+module.exports = ToAutoComplete
+
+inherits(ToAutoComplete, Component)
+function ToAutoComplete () {
+ Component.call(this)
+}
+
+ToAutoComplete.prototype.render = function () {
+ const { to, accounts, onChange, inError } = this.props
+
+ return h('div.send-v2__to-autocomplete', [
+
+ h('input.send-v2__to-autocomplete__input', {
+ name: 'address',
+ list: 'addresses',
+ placeholder: 'Recipient Address',
+ className: inError ? `send-v2__error-border` : '',
+ value: to,
+ onChange,
+ onFocus: event => {
+ to && event.target.select()
+ },
+ style: {
+ borderColor: inError ? 'red' : null,
+ }
+ }),
+
+ h('datalist#addresses', [
+ // Corresponds to the addresses owned.
+ ...Object.entries(accounts).map(([key, { address, name }]) => {
+ return h('option', {
+ value: address,
+ label: name,
+ key: address,
+ })
+ }),
+ // Corresponds to previously sent-to addresses.
+ // ...addressBook.map(({ address, name }) => {
+ // return h('option', {
+ // value: address,
+ // label: name,
+ // key: address,
+ // })
+ // }),
+ ]),
+
+ ])
+
+}
+
diff --git a/ui/app/components/send/usd-fee-display.js b/ui/app/components/send/usd-fee-display.js
new file mode 100644
index 000000000..6ee38f1b5
--- /dev/null
+++ b/ui/app/components/send/usd-fee-display.js
@@ -0,0 +1,35 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const FiatValue = require('../fiat-value')
+const { getTxFeeBn } = require('../../util')
+
+module.exports = USDFeeDisplay
+
+inherits(USDFeeDisplay, Component)
+function USDFeeDisplay () {
+ Component.call(this)
+}
+
+USDFeeDisplay.prototype.render = function () {
+ const {
+ activeCurrency,
+ conversionRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ } = this.props
+
+ return h(FiatValue, {
+ value: getTxFeeBn(gas, gasPrice, blockGasLimit),
+ conversionRate,
+ currentCurrency: activeCurrency,
+ style: {
+ color: '#5d5d5d',
+ fontSize: '16px',
+ fontFamily: 'DIN OT',
+ lineHeight: '22.4px'
+ }
+ })
+}
+
diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js
index 901a4a956..96a86d3b1 100644
--- a/ui/app/components/shapeshift-form.js
+++ b/ui/app/components/shapeshift-form.js
@@ -131,8 +131,8 @@ ShapeshiftForm.prototype.renderMain = function () {
},
}, [
this.props.warning
- ? this.props.warning
- && h('span.error.flex-center', {
+ ? this.props.warning &&
+ h('span.error.flex-center', {
style: {
textAlign: 'center',
width: '229px',
diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js
index b555dee84..43973de63 100644
--- a/ui/app/components/shift-list-item.js
+++ b/ui/app/components/shift-list-item.js
@@ -29,7 +29,7 @@ function ShiftListItem () {
ShiftListItem.prototype.render = function () {
return (
- h('.transaction-list-item.flex-row', {
+ h('div.tx-list-item.tx-list-clickable', {
style: {
paddingTop: '20px',
paddingBottom: '20px',
diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js
new file mode 100644
index 000000000..2f71c0687
--- /dev/null
+++ b/ui/app/components/token-balance.js
@@ -0,0 +1,113 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const TokenTracker = require('eth-token-tracker')
+const connect = require('react-redux').connect
+const selectors = require('../selectors')
+
+function mapStateToProps (state) {
+ return {
+ userAddress: selectors.getSelectedAddress(state),
+ }
+}
+
+module.exports = connect(mapStateToProps)(TokenBalance)
+
+
+inherits(TokenBalance, Component)
+function TokenBalance () {
+ this.state = {
+ string: '',
+ symbol: '',
+ isLoading: true,
+ error: null,
+ }
+ Component.call(this)
+}
+
+TokenBalance.prototype.render = function () {
+ const state = this.state
+ const { symbol, string, isLoading } = state
+ const { balanceOnly } = this.props
+
+ return isLoading
+ ? h('span', '')
+ : h('span.token-balance', [
+ h('span.token-balance__amount', string),
+ !balanceOnly && h('span.token-balance__symbol', symbol),
+ ])
+}
+
+TokenBalance.prototype.componentDidMount = function () {
+ this.createFreshTokenTracker()
+}
+
+TokenBalance.prototype.createFreshTokenTracker = function () {
+ if (this.tracker) {
+ // Clean up old trackers when refreshing:
+ this.tracker.stop()
+ this.tracker.removeListener('update', this.balanceUpdater)
+ this.tracker.removeListener('error', this.showError)
+ }
+
+ if (!global.ethereumProvider) return
+ const { userAddress, token } = this.props
+
+ this.tracker = new TokenTracker({
+ userAddress,
+ provider: global.ethereumProvider,
+ tokens: [token],
+ pollingInterval: 8000,
+ })
+
+
+ // Set up listener instances for cleaning up
+ this.balanceUpdater = this.updateBalance.bind(this)
+ this.showError = error => {
+ this.setState({ error, isLoading: false })
+ }
+ this.tracker.on('update', this.balanceUpdater)
+ this.tracker.on('error', this.showError)
+
+ this.tracker.updateBalances()
+ .then(() => {
+ this.updateBalance(this.tracker.serialize())
+ })
+ .catch((reason) => {
+ log.error(`Problem updating balances`, reason)
+ this.setState({ isLoading: false })
+ })
+}
+
+TokenBalance.prototype.componentDidUpdate = function (nextProps) {
+ const {
+ userAddress: oldAddress,
+ token: { address: oldTokenAddress },
+ } = this.props
+ const {
+ userAddress: newAddress,
+ token: { address: newTokenAddress },
+ } = nextProps
+
+ if ((!oldAddress || !newAddress) && (!oldTokenAddress || !newTokenAddress)) return
+ if ((oldAddress === newAddress) && (oldTokenAddress === newTokenAddress)) return
+
+ this.setState({ isLoading: true })
+ this.createFreshTokenTracker()
+}
+
+TokenBalance.prototype.updateBalance = function (tokens = []) {
+ const [{ string, symbol }] = tokens
+
+ this.setState({
+ string,
+ symbol,
+ isLoading: false,
+ })
+}
+
+TokenBalance.prototype.componentWillUnmount = function () {
+ if (!this.tracker) return
+ this.tracker.stop()
+}
+
diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js
index 19d7139bb..ad431df69 100644
--- a/ui/app/components/token-cell.js
+++ b/ui/app/components/token-cell.js
@@ -1,35 +1,127 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
+const connect = require('react-redux').connect
const Identicon = require('./identicon')
const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
+const selectors = require('../selectors')
+const actions = require('../actions')
+const { conversionUtil } = require('../conversion-util')
-module.exports = TokenCell
+const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js')
+
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ selectedTokenAddress: state.metamask.selectedTokenAddress,
+ userAddress: selectors.getSelectedAddress(state),
+ tokenExchangeRates: state.metamask.tokenExchangeRates,
+ ethToUSDRate: state.metamask.conversionRate,
+ sidebarOpen: state.appState.sidebarOpen,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ setSelectedToken: address => dispatch(actions.setSelectedToken(address)),
+ updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)),
+ hideSidebar: () => dispatch(actions.hideSidebar()),
+ }
+}
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(TokenCell)
inherits(TokenCell, Component)
function TokenCell () {
Component.call(this)
+
+ this.state = {
+ tokenMenuOpen: false,
+ }
+}
+
+TokenCell.prototype.componentWillMount = function () {
+ const {
+ updateTokenExchangeRate,
+ symbol,
+ } = this.props
+
+ updateTokenExchangeRate(symbol)
}
TokenCell.prototype.render = function () {
+ const { tokenMenuOpen } = this.state
const props = this.props
- const { address, symbol, string, network, userAddress } = props
+ const {
+ address,
+ symbol,
+ string,
+ network,
+ setSelectedToken,
+ selectedTokenAddress,
+ tokenExchangeRates,
+ ethToUSDRate,
+ hideSidebar,
+ sidebarOpen,
+ // userAddress,
+ } = props
+
+ const pair = `${symbol.toLowerCase()}_eth`;
+ let currentTokenToEthRate;
+ let currentTokenInUSD;
+ let formattedUSD = ''
+
+ if (tokenExchangeRates[pair]) {
+ currentTokenToEthRate = tokenExchangeRates[pair].rate;
+ currentTokenInUSD = conversionUtil(string, {
+ fromNumericBase: 'dec',
+ fromCurrency: symbol,
+ toCurrency: 'USD',
+ numberOfDecimals: 2,
+ conversionRate: currentTokenToEthRate,
+ ethToUSDRate,
+ })
+ formattedUSD = `$${currentTokenInUSD} USD`;
+ }
+
return (
- h('li.token-cell', {
- style: { cursor: network === '1' ? 'pointer' : 'default' },
- onClick: this.view.bind(this, address, userAddress, network),
+ h('div.token-list-item', {
+ className: `token-list-item ${selectedTokenAddress === address ? 'token-list-item--active' : ''}`,
+ // style: { cursor: network === '1' ? 'pointer' : 'default' },
+ // onClick: this.view.bind(this, address, userAddress, network),
+ onClick: () => {
+ setSelectedToken(address)
+ selectedTokenAddress !== address && sidebarOpen && hideSidebar()
+ },
}, [
h(Identicon, {
- diameter: 50,
+ className: 'token-list-item__identicon',
+ diameter: 45,
address,
network,
}),
- h('h3', `${string || 0} ${symbol}`),
+ h('h.token-list-item__balance-wrapper', null, [
+ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`),
- h('span', { style: { flex: '1 0 auto' } }),
+ h('div.token-list-item__fiat-amount', {
+ style: {},
+ }, formattedUSD),
+ ]),
+
+ h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', {
+ onClick: (e) => {
+ e.stopPropagation()
+ this.setState({ tokenMenuOpen: true })
+ },
+ }),
+
+ tokenMenuOpen && h(TokenMenuDropdown, {
+ onClose: () => this.setState({ tokenMenuOpen: false }),
+ token: { symbol, address },
+ }),
/*
h('button', {
diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js
index 998ec901d..4959f1cd5 100644
--- a/ui/app/components/token-list.js
+++ b/ui/app/components/token-list.js
@@ -3,8 +3,29 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const TokenTracker = require('eth-token-tracker')
const TokenCell = require('./token-cell.js')
+const normalizeAddress = require('eth-sig-util').normalize
+const connect = require('react-redux').connect
+const selectors = require('../selectors')
-module.exports = TokenList
+function mapStateToProps (state) {
+ return {
+ network: state.metamask.network,
+ tokens: state.metamask.tokens,
+ userAddress: selectors.getSelectedAddress(state),
+ }
+}
+
+const defaultTokens = []
+const contracts = require('eth-contract-metadata')
+for (const address in contracts) {
+ const contract = contracts[address]
+ if (contract.erc20) {
+ contract.address = address
+ defaultTokens.push(contract)
+ }
+}
+
+module.exports = connect(mapStateToProps)(TokenList)
inherits(TokenList, Component)
function TokenList () {
@@ -19,10 +40,9 @@ function TokenList () {
TokenList.prototype.render = function () {
const state = this.state
const { tokens, isLoading, error } = state
- const { userAddress, network } = this.props
if (isLoading) {
- return this.message('Loading')
+ return this.message('Loading Tokens...')
}
if (error) {
@@ -47,87 +67,8 @@ TokenList.prototype.render = function () {
])
}
- const tokenViews = tokens.map((tokenData) => {
- tokenData.network = network
- tokenData.userAddress = userAddress
- return h(TokenCell, tokenData)
- })
+ return h('div', tokens.map((tokenData) => h(TokenCell, tokenData)))
- return h('.full-flex-height', [
- this.renderTokenStatusBar(),
-
- h('ol.full-flex-height.flex-column', {
- style: {
- overflowY: 'auto',
- display: 'flex',
- flexDirection: 'column',
- },
- }, [
- h('style', `
-
- li.token-cell {
- display: flex;
- flex-direction: row;
- align-items: center;
- padding: 10px;
- min-height: 50px;
- }
-
- li.token-cell > h3 {
- margin-left: 12px;
- }
-
- li.token-cell:hover {
- background: white;
- cursor: pointer;
- }
-
- `),
- ...tokenViews,
- h('.flex-grow'),
- ]),
- ])
-}
-
-TokenList.prototype.renderTokenStatusBar = function () {
- const { tokens } = this.state
-
- let msg
- if (tokens.length === 1) {
- msg = `You own 1 token`
- } else if (tokens.length > 1) {
- msg = `You own ${tokens.length} tokens`
- } else {
- msg = `No tokens found`
- }
-
- return h('div', {
- style: {
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- minHeight: '70px',
- padding: '10px',
- },
- }, [
- h('span', msg),
- h('button', {
- key: 'reveal-account-bar',
- onClick: (event) => {
- event.preventDefault()
- this.props.addToken()
- },
- style: {
- display: 'flex',
- height: '40px',
- padding: '10px',
- justifyContent: 'center',
- alignItems: 'center',
- },
- }, [
- 'ADD TOKEN',
- ]),
- ])
}
TokenList.prototype.message = function (body) {
@@ -156,6 +97,7 @@ TokenList.prototype.createFreshTokenTracker = function () {
if (!global.ethereumProvider) return
const { userAddress } = this.props
+
this.tracker = new TokenTracker({
userAddress,
provider: global.ethereumProvider,
@@ -182,15 +124,30 @@ TokenList.prototype.createFreshTokenTracker = function () {
})
}
-TokenList.prototype.componentWillUpdate = function (nextProps) {
- if (nextProps.network === 'loading') return
- const oldNet = this.props.network
- const newNet = nextProps.network
+TokenList.prototype.componentDidUpdate = function (nextProps) {
+ const {
+ network: oldNet,
+ userAddress: oldAddress,
+ tokens,
+ } = this.props
+ const {
+ network: newNet,
+ userAddress: newAddress,
+ tokens: newTokens,
+ } = nextProps
- if (oldNet && newNet && newNet !== oldNet) {
- this.setState({ isLoading: true })
- this.createFreshTokenTracker()
- }
+ const isLoading = newNet === 'loading'
+ const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress
+ const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet
+ const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork
+
+ const oldTokensLength = tokens ? tokens.length : 0
+ const tokensLengthUnchanged = oldTokensLength === newTokens.length
+
+ if (tokensLengthUnchanged && shouldUpdateTokens) return
+
+ this.setState({ isLoading: true })
+ this.createFreshTokenTracker()
}
TokenList.prototype.updateBalances = function (tokens) {
@@ -205,3 +162,15 @@ TokenList.prototype.componentWillUnmount = function () {
this.tracker.stop()
}
+function uniqueMergeTokens (tokensA, tokensB = []) {
+ const uniqueAddresses = []
+ const result = []
+ tokensA.concat(tokensB).forEach((token) => {
+ const normal = normalizeAddress(token.address)
+ if (!uniqueAddresses.includes(normal)) {
+ uniqueAddresses.push(normal)
+ result.push(token)
+ }
+ })
+ return result
+}
diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js
index 891d5e227..21f2b8236 100644
--- a/ui/app/components/transaction-list-item.js
+++ b/ui/app/components/transaction-list-item.js
@@ -148,6 +148,12 @@ function renderErrorOrWarning (transaction) {
if (status === 'rejected') {
return h('span.error', ' (Rejected)')
}
+ if (transaction.err || transaction.warning) {
+ const { err, warning = {} } = transaction
+ const errFirst = !!((err && warning) || err)
+ const message = errFirst ? err.message : warning.message
+
+ errFirst ? err.message : warning.message
// show error
if (err) {
diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js
new file mode 100644
index 000000000..8422c02b9
--- /dev/null
+++ b/ui/app/components/tx-list-item.js
@@ -0,0 +1,187 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const connect = require('react-redux').connect
+const inherits = require('util').inherits
+const classnames = require('classnames')
+const abi = require('human-standard-token-abi')
+const abiDecoder = require('abi-decoder')
+abiDecoder.addABI(abi)
+const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
+const Identicon = require('./identicon')
+
+const { conversionUtil } = require('../conversion-util')
+
+module.exports = connect(mapStateToProps)(TxListItem)
+
+function mapStateToProps (state) {
+ return {
+ tokens: state.metamask.tokens,
+ }
+}
+
+inherits(TxListItem, Component)
+function TxListItem () {
+ Component.call(this)
+}
+
+TxListItem.prototype.getAddressText = function () {
+ const {
+ address,
+ txParams = {},
+ } = this.props
+
+ const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
+ const { name: txDataName, params = [] } = decodedData || {}
+ const { value } = params[0] || {}
+
+ switch (txDataName) {
+ case 'transfer':
+ return `${value.slice(0, 10)}...${value.slice(-4)}`
+ default:
+ return address
+ ? `${address.slice(0, 10)}...${address.slice(-4)}`
+ : 'Contract Published'
+ }
+}
+
+TxListItem.prototype.getSendEtherTotal = function () {
+ const {
+ transactionAmount,
+ conversionRate,
+ address,
+ } = this.props
+
+ if (!address) {
+ return {}
+ }
+
+ const totalInUSD = conversionUtil(transactionAmount, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromCurrency: 'ETH',
+ toCurrency: 'USD',
+ fromDenomination: 'WEI',
+ numberOfDecimals: 2,
+ conversionRate,
+ })
+ const totalInETH = conversionUtil(transactionAmount, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ fromCurrency: 'ETH',
+ toCurrency: 'ETH',
+ fromDenomination: 'WEI',
+ conversionRate,
+ numberOfDecimals: 6,
+ })
+
+ return {
+ total: `${totalInETH} ETH`,
+ fiatTotal: `$${totalInUSD} USD`,
+ }
+}
+
+TxListItem.prototype.getSendTokenTotal = function () {
+ const {
+ txParams = {},
+ tokens,
+ } = this.props
+
+ const toAddress = txParams.to
+ const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
+ const { params = [] } = decodedData || {}
+ const { value } = params[1] || {}
+ const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {}
+
+ const multiplier = Math.pow(10, Number(decimals || 0))
+ const total = Number(value / multiplier)
+
+ return {
+ total: `${total} ${symbol}`,
+ }
+}
+
+TxListItem.prototype.render = function () {
+ const {
+ transactionStatus,
+ onClick,
+ transActionId,
+ dateString,
+ address,
+ className,
+ txParams = {},
+ } = this.props
+
+ const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
+ const { name: txDataName } = decodedData || {}
+
+ const { total, fiatTotal } = txDataName === 'transfer'
+ ? this.getSendTokenTotal()
+ : this.getSendEtherTotal()
+
+ return h(`div${className || ''}`, {
+ key: transActionId,
+ onClick: () => onClick && onClick(transActionId),
+ }, [
+ h(`div.flex-column.tx-list-item-wrapper`, {}, [
+
+ h('div.tx-list-date-wrapper', {
+ style: {},
+ }, [
+ h('span.tx-list-date', {}, [
+ dateString,
+ ]),
+ ]),
+
+ h('div.flex-row.tx-list-content-wrapper', {
+ style: {},
+ }, [
+
+ h('div.tx-list-identicon-wrapper', {
+ style: {},
+ }, [
+ h(Identicon, {
+ address,
+ diameter: 28,
+ }),
+ ]),
+
+ h('div.tx-list-account-and-status-wrapper', {}, [
+ h('div.tx-list-account-wrapper', {
+ style: {},
+ }, [
+ h('span.tx-list-account', {}, [
+ this.getAddressText(address),
+ ]),
+ ]),
+
+ h('div.tx-list-status-wrapper', {
+ style: {},
+ }, [
+ h('span', {
+ className: classnames('tx-list-status', {
+ 'tx-list-status--rejected': transactionStatus === 'rejected',
+ 'tx-list-status--failed': transactionStatus === 'failed',
+ }),
+ },
+ transactionStatus,
+ ),
+ ]),
+ ]),
+
+ h('div.flex-column.tx-list-details-wrapper', {
+ style: {},
+ }, [
+
+ h('span', {
+ className: classnames('tx-list-value', {
+ 'tx-list-value--confirmed': transactionStatus === 'confirmed',
+ }),
+ }, total),
+
+ h('span.tx-list-fiat-value', fiatTotal),
+
+ ]),
+ ]),
+ ]) // holding on icon from design
+ ])
+}
diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js
new file mode 100644
index 000000000..a02849d0e
--- /dev/null
+++ b/ui/app/components/tx-list.js
@@ -0,0 +1,135 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const prefixForNetwork = require('../../lib/etherscan-prefix-for-network')
+const selectors = require('../selectors')
+const TxListItem = require('./tx-list-item')
+const ShiftListItem = require('./shift-list-item')
+const { formatBalance, formatDate } = require('../util')
+const { showConfTxPage } = require('../actions')
+const classnames = require('classnames')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(TxList)
+
+function mapStateToProps (state) {
+ return {
+ txsToRender: selectors.transactionsSelector(state),
+ conversionRate: selectors.conversionRateSelector(state),
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showConfTxPage: ({ id }) => dispatch(showConfTxPage({ id }))
+ }
+}
+
+inherits(TxList, Component)
+function TxList () {
+ Component.call(this)
+}
+
+TxList.prototype.render = function () {
+
+ const { txsToRender, showConfTxPage } = this.props
+
+ return h('div.flex-column.tx-list-container', {}, [
+
+ h('div.flex-row.tx-list-header-wrapper', [
+ h('div.flex-row.tx-list-header', [
+ h('div', 'transactions'),
+ ]),
+ ]),
+
+ this.renderTransaction(),
+
+ ])
+}
+
+TxList.prototype.renderTransaction = function () {
+ const { txsToRender, conversionRate } = this.props
+ return txsToRender.length
+ ? txsToRender.map((transaction, i) => this.renderTransactionListItem(transaction, conversionRate))
+ : [h(
+ 'div.tx-list-item.tx-list-item--empty',
+ { key: 'tx-list-none' },
+ [ 'No Transactions' ],
+ )]
+}
+
+// TODO: Consider moving TxListItem into a separate component
+TxList.prototype.renderTransactionListItem = function (transaction, conversionRate) {
+ // console.log({transaction})
+ // refer to transaction-list.js:line 58
+
+ if (transaction.key === 'shapeshift') {
+ return h(ShiftListItem, transaction)
+ }
+
+ const props = {
+ dateString: formatDate(transaction.time),
+ address: transaction.txParams.to,
+ transactionStatus: transaction.status,
+ transactionAmount: transaction.txParams.value,
+ transActionId: transaction.id,
+ transactionHash: transaction.hash,
+ transactionNetworkId: transaction.metamaskNetworkId,
+ }
+
+ const {
+ address,
+ transactionStatus,
+ transactionAmount,
+ dateString,
+ transActionId,
+ transactionHash,
+ transactionNetworkId,
+ } = props
+ const { showConfTxPage } = this.props
+
+ const opts = {
+ key: transActionId || transactionHash,
+ txParams: transaction.txParams,
+ transactionStatus,
+ transActionId,
+ key: transActionId,
+ dateString,
+ address,
+ transactionAmount,
+ transactionHash,
+ conversionRate,
+ }
+
+ const isUnapproved = transactionStatus === 'unapproved';
+
+ if (isUnapproved) {
+ opts.onClick = () => showConfTxPage({id: transActionId})
+ opts.transactionStatus = 'Not Started'
+ } else if (transactionHash) {
+ opts.onClick = () => this.view(transactionHash, transactionNetworkId)
+ }
+
+ opts.className = classnames('.tx-list-item', {
+ '.tx-list-pending-item-container': isUnapproved,
+ '.tx-list-clickable': Boolean(transactionHash) || isUnapproved,
+ })
+
+ return h(TxListItem, opts)
+}
+
+TxList.prototype.view = function (txHash, network) {
+ const url = etherscanLinkFor(txHash, network)
+ if (url) {
+ navigateTo(url)
+ }
+}
+
+function navigateTo (url) {
+ global.platform.openWindow({ url })
+}
+
+function etherscanLinkFor (txHash, network) {
+ const prefix = prefixForNetwork(network)
+ return `https://${prefix}etherscan.io/tx/${txHash}`
+}
diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js
new file mode 100644
index 000000000..59f55d485
--- /dev/null
+++ b/ui/app/components/tx-view.js
@@ -0,0 +1,148 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const ethUtil = require('ethereumjs-util')
+const inherits = require('util').inherits
+const actions = require('../actions')
+const selectors = require('../selectors')
+
+const BalanceComponent = require('./balance-component')
+const TxList = require('./tx-list')
+const Identicon = require('./identicon')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView)
+
+function mapStateToProps (state) {
+ const sidebarOpen = state.appState.sidebarOpen
+
+ const identities = state.metamask.identities
+ const accounts = state.metamask.accounts
+ const network = state.metamask.network
+ const selectedTokenAddress = state.metamask.selectedTokenAddress
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress)
+ const identity = identities[selectedAddress]
+
+ return {
+ sidebarOpen,
+ selectedAddress,
+ checksumAddress,
+ selectedTokenAddress,
+ selectedToken: selectors.getSelectedToken(state),
+ identity,
+ network,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showSidebar: () => { dispatch(actions.showSidebar()) },
+ hideSidebar: () => { dispatch(actions.hideSidebar()) },
+ showModal: (payload) => { dispatch(actions.showModal(payload)) },
+ showSendPage: () => { dispatch(actions.showSendPage()) },
+ showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) },
+ }
+}
+
+inherits(TxView, Component)
+function TxView () {
+ Component.call(this)
+}
+
+TxView.prototype.renderHeroBalance = function () {
+ const { selectedToken } = this.props
+
+ return h('div.hero-balance', {}, [
+
+ h(BalanceComponent, { token: selectedToken }),
+
+ this.renderButtons(),
+ ])
+}
+
+TxView.prototype.renderButtons = function () {
+ const {selectedToken, showModal, showSendPage, showSendTokenPage } = this.props
+
+ return !selectedToken
+ ? (
+ h('div.flex-row.flex-center.hero-balance-buttons', [
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ },
+ onClick: () => showModal({
+ name: 'BUY',
+ }),
+ }, 'BUY'),
+
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ marginLeft: '0.8em',
+ },
+ onClick: showSendPage,
+ }, 'SEND'),
+ ])
+ )
+ : (
+ h('div.flex-row.flex-center.hero-balance-buttons', [
+ h('button.btn-clear', {
+ style: {
+ textAlign: 'center',
+ marginLeft: '0.8em',
+ },
+ onClick: showSendTokenPage,
+ }, 'SEND'),
+ ])
+ )
+}
+
+TxView.prototype.render = function () {
+ const { selectedAddress, identity, network } = this.props
+
+ return h('div.tx-view.flex-column', {
+ style: {},
+ }, [
+
+ h('div.flex-row.phone-visible', {
+ style: {
+ margin: '1em 0.9em',
+ alignItems: 'center',
+ },
+ onClick: () => {
+ this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar()
+ },
+ }, [
+
+ h('div.fa.fa-bars', {
+ style: {
+ fontSize: '1.3em',
+ },
+ }, []),
+
+ h('.identicon-wrapper.select-none', {
+ style: {
+ marginLeft: '0.9em',
+ },
+ }, [
+ h(Identicon, {
+ diameter: 24,
+ address: selectedAddress,
+ network,
+ }),
+ ]),
+
+ h('span.account-name', {
+ style: {},
+ }, [
+ identity.name,
+ ]),
+
+ ]),
+
+ this.renderHeroBalance(),
+
+ h(TxList),
+
+ ])
+}
diff --git a/ui/app/components/wallet-content-display.js b/ui/app/components/wallet-content-display.js
new file mode 100644
index 000000000..bfa061be4
--- /dev/null
+++ b/ui/app/components/wallet-content-display.js
@@ -0,0 +1,56 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+
+module.exports = WalletContentDisplay
+
+inherits(WalletContentDisplay, Component)
+function WalletContentDisplay () {
+ Component.call(this)
+}
+
+WalletContentDisplay.prototype.render = function () {
+ const { title, amount, fiatValue, active, style } = this.props
+
+ // TODO: Separate component: wallet-content-account
+ return h('div.flex-column', {
+ style: {
+ marginLeft: '1.3em',
+ alignItems: 'flex-start',
+ ...style,
+ },
+ }, [
+
+ h('span', {
+ style: {
+ fontSize: '1.1em',
+ },
+ }, title),
+
+ h('span', {
+ style: {
+ fontSize: '1.8em',
+ margin: '0.4em 0em',
+ },
+ }, amount),
+
+ h('span', {
+ style: {
+ fontSize: '1.3em',
+ },
+ }, fiatValue),
+
+ active && h('div', {
+ style: {
+ position: 'absolute',
+ marginLeft: '-1.3em',
+ height: '6em',
+ width: '0.3em',
+ background: '#D8D8D8', // $alto
+ },
+ }, [
+ ]),
+ ])
+
+}
+
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
new file mode 100644
index 000000000..f06c4d512
--- /dev/null
+++ b/ui/app/components/wallet-view.js
@@ -0,0 +1,179 @@
+const Component = require('react').Component
+const connect = require('react-redux').connect
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const Identicon = require('./identicon')
+const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns
+const actions = require('../actions')
+const BalanceComponent = require('./balance-component')
+const TokenList = require('./token-list')
+const selectors = require('../selectors')
+
+module.exports = connect(mapStateToProps, mapDispatchToProps)(WalletView)
+
+function mapStateToProps (state) {
+
+ return {
+ network: state.metamask.network,
+ sidebarOpen: state.appState.sidebarOpen,
+ identities: state.metamask.identities,
+ accounts: state.metamask.accounts,
+ tokens: state.metamask.tokens,
+ selectedAddress: selectors.getSelectedAddress(state),
+ selectedIdentity: selectors.getSelectedIdentity(state),
+ selectedAccount: selectors.getSelectedAccount(state),
+ selectedTokenAddress: state.metamask.selectedTokenAddress,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showSendPage: () => { dispatch(actions.showSendPage()) },
+ hideSidebar: () => { dispatch(actions.hideSidebar()) },
+ unsetSelectedToken: () => dispatch(actions.setSelectedToken()),
+ }
+}
+
+inherits(WalletView, Component)
+function WalletView () {
+ Component.call(this)
+}
+
+WalletView.prototype.renderWalletBalance = function () {
+ const {
+ selectedTokenAddress,
+ selectedAccount,
+ unsetSelectedToken,
+ hideSidebar,
+ sidebarOpen,
+ } = this.props
+
+ const selectedClass = selectedTokenAddress
+ ? ''
+ : 'wallet-balance-wrapper--active'
+ const className = `flex-column wallet-balance-wrapper ${selectedClass}`
+
+ return h('div', { className }, [
+ h('div.wallet-balance',
+ {
+ onClick: () => {
+ unsetSelectedToken()
+ selectedTokenAddress && sidebarOpen && hideSidebar()
+ },
+ },
+ [
+ h(BalanceComponent, {
+ balanceValue: selectedAccount.balance,
+ style: {},
+ }),
+ ]
+ ),
+ ])
+}
+
+WalletView.prototype.render = function () {
+ const {
+ network, responsiveDisplayClassname, identities,
+ selectedAddress, accounts,
+ selectedIdentity,
+ } = this.props
+ // temporary logs + fake extra wallets
+ // console.log('walletview, selectedAccount:', selectedAccount)
+
+ return h('div.wallet-view.flex-column' + (responsiveDisplayClassname || ''), {
+ style: {},
+ }, [
+
+ // TODO: Separate component: wallet account details
+ h('div.flex-column.wallet-view-account-details', {
+ style: {},
+ }, [
+
+ h('div.flex-row.account-options-menu', {
+ style: {
+ position: 'relative',
+ },
+ }, [
+
+ h(AccountDropdowns, {
+ selected: selectedAddress,
+ network,
+ identities,
+ useCssTransition: true,
+ enableAccountOptions: true,
+ dropdownWrapperStyle: {
+ padding: '1px 15px',
+ marginLeft: '-25px',
+ position: 'absolute',
+ width: '122%', // TODO, refactor all of this component out into media queries
+ },
+ menuItemStyles: {
+ padding: '0px 0px',
+ margin: '22px 0px',
+ },
+ }, []),
+
+ ]),
+
+ h('div.flex-column.flex-center', {
+ }, [
+ h('div', {
+ style: {
+ position: 'relative',
+ },
+ }, [
+ h(AccountDropdowns, {
+ accounts,
+ style: {
+ position: 'absolute',
+ left: 'calc(50% + 28px + 5.5px)',
+ top: '14px',
+ },
+ innerStyle: {
+ padding: '10px 16px',
+ },
+ useCssTransition: true,
+ selected: selectedAddress,
+ network,
+ identities,
+ }, []),
+ ]),
+
+ h(Identicon, {
+ diameter: 54,
+ address: selectedAddress,
+ }),
+
+ h('span.account-name', {
+ style: {},
+ }, [
+ selectedIdentity.name,
+ ]),
+
+ ]),
+ ]),
+
+ // 'Wallet' - Title
+ // Not visible on mobile
+ h('div.flex-column.wallet-view-title-wrapper', {}, [
+ h('span.wallet-view-title', {}, [
+ 'Wallet',
+ ]),
+ ]),
+
+ this.renderWalletBalance(),
+
+ h(TokenList),
+
+ ])
+}
+
+// TODO: Extra wallets, for dev testing. Remove when PRing to master.
+// const extraWallet = h('div.flex-column.wallet-balance-wrapper', {}, [
+// h('div.wallet-balance', {}, [
+// h(BalanceComponent, {
+// balanceValue: selectedAccount.balance,
+// style: {},
+// }),
+// ]),
+// ])
diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js
index cb1afedfe..f201010fc 100644
--- a/ui/app/conf-tx.js
+++ b/ui/app/conf-tx.js
@@ -3,9 +3,7 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const actions = require('./actions')
-const NetworkIndicator = require('./components/network')
const txHelper = require('../lib/tx-helper')
-const isPopupOrNotification = require('../../app/scripts/lib/is-popup-or-notification')
const PendingTx = require('./components/pending-tx')
const PendingMsg = require('./components/pending-msg')
@@ -13,6 +11,15 @@ const PendingPersonalMsg = require('./components/pending-personal-msg')
const PendingTypedMsg = require('./components/pending-typed-msg')
const Loading = require('./components/loading')
+// const contentDivider = h('div', {
+// style: {
+// marginLeft: '16px',
+// marginRight: '16px',
+// height:'1px',
+// background:'#E7E7E7',
+// },
+// })
+
module.exports = connect(mapStateToProps)(ConfirmTxScreen)
function mapStateToProps (state) {
@@ -42,85 +49,63 @@ function ConfirmTxScreen () {
ConfirmTxScreen.prototype.render = function () {
const props = this.props
- const { network, provider, unapprovedTxs, currentCurrency, computedBalances,
- unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, conversionRate, blockGasLimit } = props
+ const {
+ network,
+ unapprovedTxs,
+ currentCurrency,
+ unapprovedMsgs,
+ unapprovedPersonalMsgs,
+ unapprovedTypedMessages,
+ conversionRate,
+ blockGasLimit,
+ // provider,
+ // computedBalances,
+ } = props
var unconfTxList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network)
var txData = unconfTxList[props.index] || {}
var txParams = txData.params || {}
- var isNotification = isPopupOrNotification() === 'notification'
+
+ // var isNotification = isPopupOrNotification() === 'notification'
+ /*
+ Client is using the flag above to render the following in conf screen
+ // subtitle and nav
+ h('.section-title.flex-row.flex-center', [
+ !isNotification ? h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
+ onClick: this.goHome.bind(this),
+ }) : null,
+ h('h2.page-subtitle', 'Confirm Transaction'),
+ isNotification ? h(NetworkIndicator, {
+ network: network,
+ provider: provider,
+ }) : null,
+ ]),
+ */
log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`)
if (unconfTxList.length === 0) return h(Loading, { isLoading: true })
- const unconfTxListLength = unconfTxList.length
+ return currentTxView({
+ // Properties
+ txData: txData,
+ key: txData.id,
+ selectedAddress: props.selectedAddress,
+ accounts: props.accounts,
+ identities: props.identities,
+ conversionRate,
+ currentCurrency,
+ blockGasLimit,
+ // Actions
+ buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress),
+ sendTransaction: this.sendTransaction.bind(this),
+ cancelTransaction: this.cancelTransaction.bind(this, txData),
+ signMessage: this.signMessage.bind(this, txData),
+ signPersonalMessage: this.signPersonalMessage.bind(this, txData),
+ cancelMessage: this.cancelMessage.bind(this, txData),
+ cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData),
+ })
- return (
-
- h('.flex-column.flex-grow', [
-
- // subtitle and nav
- h('.section-title.flex-row.flex-center', [
- !isNotification ? h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- onClick: this.goHome.bind(this),
- }) : null,
- h('h2.page-subtitle', 'Confirm Transaction'),
- isNotification ? h(NetworkIndicator, {
- network: network,
- provider: provider,
- }) : null,
- ]),
-
- h('h3', {
- style: {
- alignSelf: 'center',
- display: unconfTxList.length > 1 ? 'block' : 'none',
- },
- }, [
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
- style: {
- display: props.index === 0 ? 'none' : 'inline-block',
- },
- onClick: () => props.dispatch(actions.previousTx()),
- }),
- ` ${props.index + 1} of ${unconfTxList.length} `,
- h('i.fa.fa-arrow-right.fa-lg.cursor-pointer', {
- style: {
- display: props.index + 1 === unconfTxList.length ? 'none' : 'inline-block',
- },
- onClick: () => props.dispatch(actions.nextTx()),
- }),
- ]),
-
- warningIfExists(props.warning),
-
- currentTxView({
- // Properties
- txData: txData,
- key: txData.id,
- selectedAddress: props.selectedAddress,
- accounts: props.accounts,
- identities: props.identities,
- conversionRate,
- currentCurrency,
- blockGasLimit,
- unconfTxListLength,
- computedBalances,
- // Actions
- buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress),
- sendTransaction: this.sendTransaction.bind(this),
- cancelTransaction: this.cancelTransaction.bind(this, txData),
- cancelAllTransactions: this.cancelAllTransactions.bind(this, unconfTxList),
- signMessage: this.signMessage.bind(this, txData),
- signPersonalMessage: this.signPersonalMessage.bind(this, txData),
- signTypedMessage: this.signTypedMessage.bind(this, txData),
- cancelMessage: this.cancelMessage.bind(this, txData),
- cancelPersonalMessage: this.cancelPersonalMessage.bind(this, txData),
- cancelTypedMessage: this.cancelTypedMessage.bind(this, txData),
- }),
- ])
- )
}
function currentTxView (opts) {
@@ -145,6 +130,7 @@ function currentTxView (opts) {
return h(PendingTypedMsg, opts)
}
}
+ return h(Loading, { isLoading: true })
}
ConfirmTxScreen.prototype.buyEth = function (address, event) {
@@ -222,14 +208,14 @@ ConfirmTxScreen.prototype.goHome = function (event) {
this.props.dispatch(actions.goHome())
}
-function warningIfExists (warning) {
- if (warning &&
- // Do not display user rejections on this screen:
- warning.indexOf('User denied transaction signature') === -1) {
- return h('.error', {
- style: {
- margin: 'auto',
- },
- }, warning)
- }
-}
+// function warningIfExists (warning) {
+// if (warning &&
+// // Do not display user rejections on this screen:
+// warning.indexOf('User denied transaction signature') === -1) {
+// return h('.error', {
+// style: {
+// margin: 'auto',
+// },
+// }, warning)
+// }
+// }
diff --git a/ui/app/config.js b/ui/app/config.js
index 0fe232c07..282a28301 100644
--- a/ui/app/config.js
+++ b/ui/app/config.js
@@ -30,7 +30,7 @@ ConfigScreen.prototype.render = function () {
var warning = state.warning
return (
- h('.flex-column.flex-grow', [
+ h('.flex-column.flex-grow', { style: { marginTop: '32px' } }, [
// subtitle and nav
h('.section-title.flex-row.flex-center', [
diff --git a/ui/app/conversion-util.js b/ui/app/conversion-util.js
new file mode 100644
index 000000000..1ef276a39
--- /dev/null
+++ b/ui/app/conversion-util.js
@@ -0,0 +1,173 @@
+/* Currency Conversion Utility
+* This utility function can be used for converting currency related values within metamask.
+* The caller should be able to pass it a value, along with information about the value's
+* numeric base, denomination and currency, and the desired numeric base, denomination and
+* currency. It should return a single value.
+*
+* @param {(number | string | BN)} value The value to convert.
+* @param {Object} [options] Options to specify details of the conversion
+* @param {string} [options.fromCurrency = 'ETH' | 'USD'] The currency of the passed value
+* @param {string} [options.toCurrency = 'ETH' | 'USD'] The desired currency of the result
+* @param {string} [options.fromNumericBase = 'hex' | 'dec' | 'BN'] The numeric basic of the passed value.
+* @param {string} [options.toNumericBase = 'hex' | 'dec' | 'BN'] The desired numeric basic of the result.
+* @param {string} [options.fromDenomination = 'WEI'] The denomination of the passed value
+* @param {number} [options.numberOfDecimals] The desired number of in the result
+* @param {number} [options.conversionRate] The rate to use to make the fromCurrency -> toCurrency conversion
+* @param {number} [options.ethToUSDRate] If present, a second conversion - at ethToUSDRate - happens after conversionRate is applied.
+* @returns {(number | string | BN)}
+*
+* The utility passes value along with the options as a single object to the `converter` function.
+* `converter` uses Ramda.js to apply a composition of conditional setters to the `value` property, depending
+* on the accompanying options. Some of these conditional setters are selected via key-value maps, where
+* the keys are specified in the options parameters and the values are setter functions.
+*/
+
+const BigNumber = require('bignumber.js')
+const R = require('ramda')
+const { stripHexPrefix } = require('ethereumjs-util')
+
+BigNumber.config({
+ ROUNDING_MODE: BigNumber.ROUND_HALF_DOWN,
+})
+
+// Big Number Constants
+const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000')
+const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000')
+
+// Individual Setters
+const convert = R.invoker(1, 'times')
+const round = R.invoker(2, 'toFormat')(R.__, BigNumber.ROUND_DOWN)
+const invertConversionRate = conversionRate => () => new BigNumber(1.0).div(conversionRate)
+
+// Setter Maps
+const toBigNumber = {
+ hex: n => new BigNumber(stripHexPrefix(n), 16),
+ dec: n => new BigNumber(n, 10),
+ BN: n => new BigNumber(n.toString(16), 16),
+}
+const toNormalizedDenomination = {
+ WEI: bigNumber => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER),
+ GWEI: bigNumber => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER),
+}
+const toSpecifiedDenomination = {
+ WEI: bigNumber => bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(),
+ GWEI: bigNumber => bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(),
+}
+const baseChange = {
+ hex: n => n.toString(16),
+ dec: n => Number(n).toString(10),
+ BN: n => new BN(n.toString(16)),
+}
+
+// Predicates
+const fromAndToCurrencyPropsNotEqual = R.compose(
+ R.not,
+ R.eqBy(R.__, 'fromCurrency', 'toCurrency'),
+ R.flip(R.prop)
+)
+
+// Lens
+const valuePropertyLens = R.over(R.lensProp('value'))
+const conversionRateLens = R.over(R.lensProp('conversionRate'))
+
+// conditional conversionRate setting wrapper
+const whenPredSetCRWithPropAndSetter = (pred, prop, setter) => R.when(
+ pred,
+ R.converge(
+ conversionRateLens,
+ [R.pipe(R.prop(prop), setter), R.identity]
+ )
+)
+
+// conditional 'value' setting wrappers
+const whenPredSetWithPropAndSetter = (pred, prop, setter) => R.when(
+ pred,
+ R.converge(
+ valuePropertyLens,
+ [R.pipe(R.prop(prop), setter), R.identity]
+ )
+)
+const whenPropApplySetterMap = (prop, setterMap) => whenPredSetWithPropAndSetter(
+ R.prop(prop),
+ prop,
+ R.prop(R.__, setterMap)
+)
+
+// Conversion utility function
+const converter = R.pipe(
+ whenPredSetCRWithPropAndSetter(R.prop('invertConversionRate'), 'conversionRate', invertConversionRate),
+ whenPropApplySetterMap('fromNumericBase', toBigNumber),
+ whenPropApplySetterMap('fromDenomination', toNormalizedDenomination),
+ whenPredSetWithPropAndSetter(fromAndToCurrencyPropsNotEqual, 'conversionRate', convert),
+ whenPropApplySetterMap('toDenomination', toSpecifiedDenomination),
+ whenPredSetWithPropAndSetter(R.prop('ethToUSDRate'), 'ethToUSDRate', convert),
+ whenPredSetWithPropAndSetter(R.prop('numberOfDecimals'), 'numberOfDecimals', round),
+ whenPropApplySetterMap('toNumericBase', baseChange),
+ R.view(R.lensProp('value'))
+);
+
+const conversionUtil = (value, {
+ fromCurrency = null,
+ toCurrency = fromCurrency,
+ fromNumericBase,
+ toNumericBase,
+ fromDenomination,
+ toDenomination,
+ numberOfDecimals,
+ conversionRate,
+ ethToUSDRate,
+ invertConversionRate,
+}) => converter({
+ fromCurrency,
+ toCurrency,
+ fromNumericBase,
+ toNumericBase,
+ fromDenomination,
+ toDenomination,
+ numberOfDecimals,
+ conversionRate,
+ ethToUSDRate,
+ invertConversionRate,
+ value: value || '0',
+});
+
+const addCurrencies = (a, b, options = {}) => {
+ const { toNumericBase, numberOfDecimals } = options
+ const value = (new BigNumber(a)).add(b);
+ return converter({
+ value,
+ toNumericBase,
+ numberOfDecimals,
+ })
+}
+
+const multiplyCurrencies = (a, b, options = {}) => {
+ const {
+ toNumericBase,
+ numberOfDecimals,
+ multiplicandBase,
+ multiplierBase,
+ } = options
+ const value = (new BigNumber(a, multiplicandBase)).times(b, multiplierBase);
+ return converter({
+ value,
+ toNumericBase,
+ numberOfDecimals,
+ })
+}
+
+const conversionGreaterThan = (
+ { ...firstProps },
+ { ...secondProps },
+) => {
+ const firstValue = converter({ ...firstProps })
+ const secondValue = converter({ ...secondProps })
+ return firstValue.gt(secondValue)
+}
+
+module.exports = {
+ conversionUtil,
+ addCurrencies,
+ multiplyCurrencies,
+ conversionGreaterThan,
+}
\ No newline at end of file
diff --git a/ui/app/css/debug.css b/ui/app/css/debug.css
deleted file mode 100644
index 3e125bcd4..000000000
--- a/ui/app/css/debug.css
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-debug / dev
-*/
-
-#app-content {
- border: 2px solid green;
-}
-
-#design-container {
- position: absolute;
- left: 360px;
- top: -42px;
- width: calc(100vw - 360px);
- height: 100vh;
- overflow: scroll;
-}
-
-#design-container img {
- width: 2000px;
- margin-right: 600px;
-}
\ No newline at end of file
diff --git a/ui/app/css/fonts.css b/ui/app/css/fonts.css
deleted file mode 100644
index 3b9f581b9..000000000
--- a/ui/app/css/fonts.css
+++ /dev/null
@@ -1,36 +0,0 @@
-@import url(https://fonts.googleapis.com/css?family=Roboto:300,500);
-@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css);
-
-@font-face {
- font-family: 'Montserrat Regular';
- src: url('/fonts/Montserrat/Montserrat-Regular.woff') format('woff');
- src: url('/fonts/Montserrat/Montserrat-Regular.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
- font-size: 'small';
-
-}
-
-@font-face {
- font-family: 'Montserrat Bold';
- src: url('/fonts/Montserrat/Montserrat-Bold.woff') format('woff');
- src: url('/fonts/Montserrat/Montserrat-Bold.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
-}
-
-@font-face {
- font-family: 'Montserrat Light';
- src: url('/fonts/Montserrat/Montserrat-Light.woff') format('woff');
- src: url('/fonts/Montserrat/Montserrat-Light.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
-}
-
-@font-face {
- font-family: 'Montserrat UltraLight';
- src: url('/fonts/Montserrat/Montserrat-UltraLight.woff') format('woff');
- src: url('/fonts/Montserrat/Montserrat-UltraLight.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
-}
diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss
new file mode 100644
index 000000000..01899ccad
--- /dev/null
+++ b/ui/app/css/index.scss
@@ -0,0 +1,13 @@
+/*
+ ITCSS
+
+ http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528
+ https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/
+ */
+@import './itcss/settings/index.scss';
+@import './itcss/tools/index.scss';
+@import './itcss/generic/index.scss';
+@import './itcss/base/index.scss';
+@import './itcss/objects/index.scss';
+@import './itcss/components/index.scss';
+@import './itcss/trumps/index.scss';
diff --git a/ui/app/css/itcss/base/index.scss b/ui/app/css/itcss/base/index.scss
new file mode 100644
index 000000000..baa6ea037
--- /dev/null
+++ b/ui/app/css/itcss/base/index.scss
@@ -0,0 +1 @@
+// Base
diff --git a/ui/app/css/itcss/components/account-dropdown.scss b/ui/app/css/itcss/components/account-dropdown.scss
new file mode 100644
index 000000000..4fc7c705a
--- /dev/null
+++ b/ui/app/css/itcss/components/account-dropdown.scss
@@ -0,0 +1,65 @@
+.account-dropdown-name {
+ font-family: Roboto;
+}
+
+.account-dropdown-balance {
+ color: $dusty-gray;
+ line-height: 19px;
+}
+
+.account-dropdown-edit-button {
+ color: $dusty-gray;
+ font-family: Roboto;
+
+ &:hover {
+ color: $white;
+ }
+}
+
+.account-list-item {
+ &__top-row {
+ display: flex;
+ margin-top: 10px;
+ margin-left: 8px;
+ position: relative;
+ }
+
+ &__account-balances {
+ height: auto;
+ border: none;
+ background-color: transparent;
+ color: #9b9b9b;
+ margin-left: 34px;
+ margin-top: 4px;
+ position: relative;
+ }
+
+ &__account-name {
+ font-size: 16px;
+ margin-left: 8px;
+ }
+
+ &__icon {
+ position: absolute;
+ right: 12px;
+ top: 1px;
+ }
+
+ &__account-primary-balance,
+ &__account-secondary-balance {
+ font-family: Roboto;
+ line-height: 16px;
+ font-size: 12px;
+ font-weight: 300;
+ }
+
+ &__account-primary-balance {
+ color: $scorpion;
+ border: none;
+ outline: 0 !important;
+ }
+
+ &__account-secondary-balance {
+ color: $dusty-gray;
+ }
+}
diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss
new file mode 100644
index 000000000..857903ce1
--- /dev/null
+++ b/ui/app/css/itcss/components/account-menu.scss
@@ -0,0 +1,118 @@
+.account-menu {
+ position: fixed;
+ z-index: 100;
+ top: 58px;
+ width: 310px;
+
+ @media screen and (max-width: 575px) {
+ right: calc((100vw - 100%) / 2);
+ }
+
+ @media screen and (min-width: 576px) {
+ right: calc((100vw - 85vw) / 2);
+ }
+
+ @media screen and (min-width: 769px) {
+ right: calc((100vw - 80vw) / 2);
+ }
+
+ @media screen and (min-width: 1281px) {
+ right: calc((100vw - 65vw) / 2);
+ }
+
+ &__icon {
+ cursor: pointer;
+ }
+
+ &__header {
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ &__logout-button {
+ border: 1px solid $dusty-gray;
+ background-color: transparent;
+ color: $white;
+ border-radius: 4px;
+ font-size: 12px;
+ line-height: 23px;
+ padding: 0 24px;
+ font-weight: 200;
+ }
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+
+ &__accounts {
+ display: flex;
+ flex-flow: column nowrap;
+ overflow-y: auto;
+ max-height: 240px;
+ position: relative;
+ z-index: 200;
+
+ &::-webkit-scrollbar {
+ display: none;
+ }
+
+ @media screen and (max-width: 575px) {
+ max-height: 215px;
+ }
+
+ .keyring-label {
+ margin-top: 5px;
+ }
+ }
+
+ &__account {
+ display: flex;
+ flex-flow: row nowrap;
+ padding: 16px 14px;
+ flex: 0 0 auto;
+
+ @media screen and (max-width: 575px) {
+ padding: 12px 14px;
+ }
+ }
+
+ &__account-info {
+ flex: 1 0 auto;
+ display: flex;
+ flex-flow: column nowrap;
+ padding-top: 4px;
+ }
+
+ &__check-mark {
+ width: 14px;
+ flex: 0 0 auto;
+ }
+
+ .identicon {
+ margin: 0 12px 0 0;
+ flex: 0 0 auto;
+ }
+
+ &__name {
+ color: $white;
+ font-size: 18px;
+ font-weight: 200;
+ line-height: 16px;
+ }
+
+ &__balance {
+ color: $dusty-gray;
+ font-size: 14px;
+ line-height: 19px;
+ }
+
+ &__action {
+ font-size: 16px;
+ line-height: 18px;
+ font-weight: 200;
+ cursor: pointer;
+ }
+}
diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss
new file mode 100644
index 000000000..aa8221c9a
--- /dev/null
+++ b/ui/app/css/itcss/components/add-token.scss
@@ -0,0 +1,286 @@
+.add-token {
+ width: 498px;
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: center;
+ position: relative;
+ z-index: 12;
+ font-family: 'DIN Next Light';
+
+ @media screen and (max-width: $break-small) {
+ top: 0;
+ width: 100%;
+
+ &__wrapper {
+ box-shadow: none !important;
+ }
+
+ &__footers {
+ border-bottom: 1px solid $gallery;
+ }
+ }
+
+ &__wrapper {
+ background-color: $white;
+ box-shadow: 0 2px 4px 0 rgba($black, .08);
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: center;
+ flex: 0 0 auto;
+ }
+
+ &__title-container {
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: center;
+ padding: 30px 60px 12px;
+ border-bottom: 1px solid $gallery;
+ flex: 0 0 auto;
+ }
+
+ &__title {
+ color: $scorpion;
+ font-size: 20px;
+ line-height: 26px;
+ text-align: center;
+ font-weight: 600;
+ margin-bottom: 12px;
+ }
+
+ &__description {
+ text-align: center;
+ }
+
+ &__description + &__description {
+ margin-top: 24px;
+ }
+
+ &__confirmation-description {
+ margin: 12px 0;
+ }
+
+ &__content-container {
+ width: 100%;
+ border-bottom: 1px solid $gallery;
+ }
+
+ &__input-container {
+ padding: 11px 0;
+ width: 263px;
+ margin: 0 auto;
+ position: relative;
+ }
+
+ &__search-input-error-message {
+ position: absolute;
+ bottom: -10px;
+ font-size: 12px;
+ width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ color: $red;
+ }
+
+ &__input {
+ width: 100%;
+ border: 2px solid $gallery;
+ border-radius: 4px;
+ padding: 5px 15px;
+ font-size: 14px;
+ line-height: 19px;
+
+ &::placeholder {
+ color: $silver;
+ }
+ }
+
+ &__footers {
+ width: 100%;
+ }
+
+ &__add-custom {
+ color: $scorpion;
+ font-size: 18px;
+ line-height: 24px;
+ text-align: center;
+ padding: 12px 0;
+ font-weight: 600;
+ cursor: pointer;
+
+ &:hover {
+ background-color: $gallery;
+ }
+ }
+
+ &__add-custom-form {
+ display: flex;
+ flex-flow: column nowrap;
+ margin: 8px 0 51px;
+ }
+
+ &__add-custom-field {
+ width: 290px;
+ margin: 0 auto;
+ position: relative;
+
+ &--error {
+ .add-token__add-custom-input {
+ border-color: $red;
+ }
+ }
+ }
+
+ &__add-custom-error-message {
+ position: absolute;
+ bottom: -21px;
+ font-size: 12px;
+ width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ color: $red;
+ }
+
+ &__add-custom-label {
+ font-size: 16px;
+ line-height: 21px;
+ margin-bottom: 8px;
+ }
+
+ &__add-custom-input {
+ width: 100%;
+ border: 1px solid $silver;
+ padding: 5px 15px;
+ font-size: 14px;
+ line-height: 19px;
+
+ &::placeholder {
+ color: $silver;
+ }
+ }
+
+ &__add-custom-field + &__add-custom-field {
+ margin-top: 21px;
+ }
+
+ &__buttons {
+ display: flex;
+ flex-flow: column nowrap;
+ margin: 30px 0 51px;
+ flex: 0 0 auto;
+ }
+
+ &__token-icons-container {
+ display: flex;
+ flex-flow: row wrap;
+ }
+
+ &__token-wrapper {
+ transition: 200ms ease-in-out;
+ display: flex;
+ flex-flow: row nowrap;
+ flex: 0 0 45%;
+ align-items: center;
+ padding: 12px;
+ margin: 2.5%;
+ box-sizing: border-box;
+ border-radius: 10px;
+ cursor: pointer;
+ border: 2px solid transparent;
+ position: relative;
+
+ &:hover {
+ border: 2px solid rgba($malibu-blue, .5);
+ }
+
+ &--selected {
+ border: 2px solid $malibu-blue !important;
+ }
+
+ &--disabled {
+ opacity: .4;
+ pointer-events: none;
+ }
+ }
+
+ &__token-name {
+ font-size: 14px;
+ line-height: 19px;
+ }
+
+ &__token-symbol {
+ font-size: 22px;
+ line-height: 29px;
+ font-weight: 600;
+ }
+
+ &__token-icon {
+ width: 60px;
+ height: 60px;
+ background-repeat: no-repeat;
+ background-size: contain;
+ background-position: center;
+ border-radius: 50%;
+ background-color: $white;
+ box-shadow: 0 2px 4px 0 rgba($black, .24);
+ margin-right: 12px;
+ flex: 0 0 auto;
+ }
+
+ &__token-message {
+ position: absolute;
+ color: $caribbean-green;
+ font-size: 11px;
+ bottom: 0;
+ left: 85px;
+ }
+
+ &__confirmation-token-list {
+ display: flex;
+ flex-flow: column nowrap;
+
+ .token-balance {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: flex-start;
+
+ &__amount {
+ color: $scorpion;
+ font-size: 43px;
+ font-weight: 300;
+ line-height: 43px;
+ margin-right: 8px;
+ }
+
+ &__symbol {
+ color: $scorpion;
+ font-size: 16px;
+ line-height: 24px;
+ }
+ }
+ }
+
+ &__confirmation-title {
+ padding: 30px 120px 12px;
+ }
+
+ &__confirmation-content {
+ padding-bottom: 60px;
+ }
+
+ &__confirmation-token-list-item {
+ display: flex;
+ flex-flow: row nowrap;
+ padding: 0 120px;
+ align-items: center;
+ }
+
+ &__confirmation-token-list-item + &__confirmation-token-list-item {
+ margin-top: 30px;
+ }
+
+ &__confirmation-token-icon {
+ margin-right: 18px;
+ }
+}
diff --git a/ui/app/css/itcss/components/buttons.scss b/ui/app/css/itcss/components/buttons.scss
new file mode 100644
index 000000000..8ba084b4a
--- /dev/null
+++ b/ui/app/css/itcss/components/buttons.scss
@@ -0,0 +1,108 @@
+/*
+ Buttons
+ */
+
+.btn-green {
+ background-color: #02c9b1; // TODO: reusable color in colors.css
+}
+
+button.btn-clear {
+ background: $white;
+ border: 1px solid;
+}
+
+// No longer used in flat design, remove when modal buttons done
+// div.wallet-btn {
+// border: 1px solid rgb(91, 93, 103);
+// border-radius: 2px;
+// height: 30px;
+// width: 75px;
+// font-size: 0.8em;
+// text-align: center;
+// line-height: 25px;
+// }
+
+// .btn-red {
+// background: rgba(254, 35, 17, 1);
+// box-shadow: 0px 3px 6px rgba(254, 35, 17, 0.36);
+// }
+
+button[disabled],
+input[type="submit"][disabled] {
+ cursor: not-allowed;
+ opacity: .5;
+ // background: rgba(197, 197, 197, 1);
+ // box-shadow: 0 3px 6px rgba(197, 197, 197, .36);
+}
+
+// button.spaced {
+// margin: 2px;
+// }
+
+// button:not([disabled]):hover, input[type="submit"]:not([disabled]):hover {
+// transform: scale(1.1);
+// }
+// button:not([disabled]):active, input[type="submit"]:not([disabled]):active {
+// transform: scale(0.95);
+// }
+
+button.primary {
+ padding: 8px 12px;
+ background: #f7861c;
+ box-shadow: 0 3px 6px rgba(247, 134, 28, .36);
+ color: $white;
+ font-size: 1.1em;
+ font-family: Roboto;
+ text-transform: uppercase;
+}
+
+.btn-light {
+ padding: 8px 12px;
+ // background: #FFFFFF; // $bg-white
+ box-shadow: 0 3px 6px rgba(247, 134, 28, .36);
+ color: #585d67; // TODO: make reusable light button color
+ font-size: 1.1em;
+ font-family: Roboto;
+ text-transform: uppercase;
+ text-align: center;
+ line-height: 20px;
+ border-radius: 2px;
+ border: 1px solid #979797; // #TODO: make reusable light border color
+ opacity: .5;
+}
+
+// TODO: cleanup: not used anywhere
+button.btn-thin {
+ border: 1px solid;
+ border-color: #4d4d4d;
+ color: #4d4d4d;
+ background: rgb(255, 174, 41);
+ border-radius: 4px;
+ min-width: 200px;
+ margin: 12px 0;
+ padding: 6px;
+ font-size: 13px;
+}
+
+.btn-secondary {
+ border: 1px solid #979797;
+ border-radius: 2px;
+ background-color: $white;
+ font-size: 16px;
+ line-height: 24px;
+ padding: 16px 42px;
+
+ &[disabled] {
+ background-color: $white !important;
+ opacity: .5;
+ }
+}
+
+.btn-tertiary {
+ border: 1px solid transparent;
+ border-radius: 2px;
+ background-color: transparent;
+ font-size: 16px;
+ line-height: 24px;
+ padding: 16px 42px;
+}
diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss
new file mode 100644
index 000000000..d4f0fe5ac
--- /dev/null
+++ b/ui/app/css/itcss/components/confirm.scss
@@ -0,0 +1,309 @@
+.confirm-screen-container {
+ position: relative;
+ align-items: center;
+ font-family: Roboto;
+ flex: 0 0 auto;
+ flex-flow: column nowrap;
+ box-shadow: 0 2px 4px 0 rgba($black, .08);
+ border-radius: 8px;
+
+ @media screen and (max-width: 575px) {
+ width: 100%;
+ }
+
+ @media screen and (min-width: 576px) {
+ // top: -26px;
+ }
+}
+
+.confirm-screen-wrapper {
+ height: 100%;
+ width: 380px;
+ background-color: $white;
+ display: flex;
+ flex-flow: column nowrap;
+ z-index: 25;
+ align-items: center;
+ font-family: Roboto;
+ position: relative;
+ overflow-y: auto;
+ overflow-x: hidden;
+ border-top-left-radius: 8px;
+ border-top-right-radius: 8px;
+
+ @media screen and (max-width: $break-small) {
+ width: 100%;
+ overflow-x: hidden;
+ overflow-y: auto;
+ top: 0;
+ box-shadow: none;
+ height: calc(100vh - 58px - 100px);
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ }
+}
+
+.confirm-screen-wrapper > .confirm-screen-total-box {
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+.confirm-screen-wrapper > .confirm-memo-wrapper {
+ margin: 0;
+}
+
+.confirm-screen-header {
+ height: 88px;
+ background-color: $athens-grey;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 22px;
+ line-height: 29px;
+ width: 100%;
+ padding: 25px 0;
+ flex: 0 0 auto;
+
+ @media screen and (max-width: $break-small) {
+ font-size: 22px;
+ }
+}
+
+.confirm-screen-header-tip {
+ height: 25px;
+ width: 25px;
+ background: $athens-grey;
+ position: absolute;
+ transform: rotate(45deg);
+ left: 178px;
+ top: 71px;
+}
+
+.confirm-screen-title {
+ line-height: 27px;
+
+ @media screen and (max-width: $break-small) {
+ margin-left: 22px;
+ margin-right: 8px;
+ }
+}
+
+.confirm-screen-back-button {
+ background: transparent;
+ border: 1px solid $curious-blue;
+ left: 24px;
+ position: absolute;
+ text-align: center;
+ color: $curious-blue;
+ padding: 6px 13px 7px 12px;
+ border-radius: 2px;
+ height: 30px;
+ width: 54px;
+
+ @media screen and (max-width: $break-small) {
+ margin-right: 12px;
+ }
+}
+
+.confirm-screen-account-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.confirm-screen-account-name {
+ margin-top: 12px;
+ font-size: 14px;
+ line-height: 19px;
+ color: $scorpion;
+ text-align: center;
+}
+
+.confirm-screen-row-info {
+ font-size: 16px;
+ line-height: 21px;
+}
+
+.confirm-screen-account-number {
+ font-size: 10px;
+ line-height: 16px;
+ color: $dusty-gray;
+ text-align: center;
+ height: 16px;
+}
+
+.confirm-screen-identicons {
+ margin-top: 24px;
+ flex: 0 0 auto;
+
+ i.fa-arrow-right {
+ align-self: start;
+ margin: 42px 14px 0;
+ }
+
+ i.fa-file-text-o {
+ font-size: 60px;
+ margin: 16px 8px 0 8px;
+ text-align: center;
+ }
+}
+
+.confirm-screen-sending-to-message {
+ text-align: center;
+ font-size: 16px;
+ margin-top: 30px;
+ font-family: 'DIN NEXT Light';
+}
+
+.confirm-screen-send-amount {
+ color: $scorpion;
+ margin-top: 12px;
+ text-align: center;
+ font-size: 40px;
+ font-weight: 300;
+ line-height: 53px;
+ flex: 0 0 auto;
+}
+
+.confirm-screen-send-amount-currency {
+ font-size: 20px;
+ line-height: 20px;
+ text-align: center;
+ flex: 0 0 auto;
+}
+
+.confirm-memo-wrapper {
+ min-height: 24px;
+ width: 100%;
+ border-bottom: 1px solid $alto;
+ flex: 0 0 auto;
+}
+
+.confirm-screen-send-memo {
+ color: $scorpion;
+ font-size: 16px;
+ line-height: 19px;
+ font-weight: 400;
+}
+
+.confirm-screen-label {
+ font-size: 18px;
+ line-height: 40px;
+ color: $scorpion;
+ text-align: left;
+}
+
+section .confirm-screen-account-name,
+section .confirm-screen-account-number,
+.confirm-screen-row-info,
+.confirm-screen-row-detail {
+ text-align: left;
+}
+
+.confirm-screen-rows {
+ display: flex;
+ flex-flow: column nowrap;
+ width: 100%;
+ flex: 0 0 auto;
+}
+
+.confirm-screen-section-column {
+ flex: .5;
+}
+
+.confirm-screen-row {
+ display: flex;
+ flex-flow: row nowrap;
+ border-bottom: 1px solid $alto;
+ width: 100%;
+ align-items: center;
+ padding: 12px;
+ padding-left: 35px;
+ font-size: 16px;
+ line-height: 22px;
+ font-weight: 300;
+}
+
+.confirm-screen-row-detail {
+ font-size: 12px;
+ line-height: 16px;
+ color: $dusty-gray;
+}
+
+.confirm-screen-total-box {
+ background-color: $wild-sand;
+ padding: 20px;
+ padding-left: 35px;
+ border-bottom: 1px solid $alto;
+
+ .confirm-screen-label {
+ line-height: 18px;
+ }
+
+ .confirm-screen-row-detail {
+ color: $scorpion;
+ }
+
+ &__subtitle {
+ font-size: 12px;
+ line-height: 22px;
+ }
+
+ .confirm-screen-row-info {
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 21px;
+ }
+}
+
+.confirm-screen-confirm-button {
+ height: 62px;
+ border-radius: 2px;
+ background-color: #02c9b1;
+ font-size: 16px;
+ color: $white;
+ text-align: center;
+ font-family: Roboto;
+ padding-top: 15px;
+ padding-bottom: 15px;
+ border-width: 0;
+ box-shadow: none;
+ flex: 1 0 auto;
+ font-weight: 300;
+}
+
+.btn-light.confirm-screen-cancel-button {
+ height: 62px;
+ background: none;
+ border: none;
+ opacity: 1;
+ font-family: Roboto;
+ border-width: 0;
+ padding-top: 15px;
+ padding-bottom: 15px;
+ font-size: 16px;
+ line-height: 32px;
+ box-shadow: none;
+ cursor: pointer;
+ flex: 1 0 auto;
+ font-weight: 300;
+}
+
+#pending-tx-form {
+ flex: 1 0 auto;
+ position: relative;
+ display: flex;
+ flex-flow: row nowrap;
+ background-color: $white;
+ padding: 19px 18px;
+ border-bottom-left-radius: 8px;
+ border-bottom-right-radius: 8px;
+ width: 100%;
+
+ @media screen and (max-width: $break-small) {
+ border-top: 1px solid $alto;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+}
diff --git a/ui/app/css/itcss/components/currency-display.scss b/ui/app/css/itcss/components/currency-display.scss
new file mode 100644
index 000000000..f2cc6e700
--- /dev/null
+++ b/ui/app/css/itcss/components/currency-display.scss
@@ -0,0 +1,46 @@
+.currency-display {
+ height: 54px;
+ width: 240px;
+ border: 1px solid $alto;
+ border-radius: 4px;
+ background-color: $white;
+ color: $dusty-gray;
+ font-family: Roboto;
+ font-size: 16px;
+ font-weight: 300;
+ padding: 8px 10px;
+ position: relative;
+
+ &__primary-row {
+ display: flex;
+ }
+
+ &__input {
+ color: $scorpion;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 22px;
+ border: none;
+ outline: 0 !important;
+ }
+
+ &__primary-currency {
+ color: $scorpion;
+ font-weight: 400;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 22px;
+ }
+
+ &__converted-row {
+ display: flex;
+ }
+
+ &__converted-value,
+ &__converted-currency {
+ color: $dusty-gray;
+ font-family: Roboto;
+ font-size: 12px;
+ line-height: 12px;
+ }
+}
\ No newline at end of file
diff --git a/ui/app/css/itcss/components/footer.scss b/ui/app/css/itcss/components/footer.scss
new file mode 100644
index 000000000..000a53eed
--- /dev/null
+++ b/ui/app/css/itcss/components/footer.scss
@@ -0,0 +1,4 @@
+.app-footer {
+ padding-bottom: 10px;
+ align-items: center;
+}
diff --git a/ui/app/css/itcss/components/gas-slider.scss b/ui/app/css/itcss/components/gas-slider.scss
new file mode 100644
index 000000000..c27a560bd
--- /dev/null
+++ b/ui/app/css/itcss/components/gas-slider.scss
@@ -0,0 +1,51 @@
+.gas-slider {
+ position: relative;
+ width: 313px;
+
+ &__input {
+ width: 317px;
+ margin-left: -2px;
+ z-index: 2;
+ }
+
+ input[type=range] {
+ -webkit-appearance: none !important;
+ }
+
+ input[type=range]::-webkit-slider-thumb {
+ -webkit-appearance: none !important;
+ height: 26px;
+ width: 26px;
+ border: 2px solid #B8B8B8;
+ background-color: #FFFFFF;
+ box-shadow: 0 2px 4px 0 rgba(0,0,0,0.08);
+ border-radius: 50%;
+ position: relative;
+ z-index: 10;
+ }
+
+ &__bar {
+ height: 6px;
+ width: 313px;
+ background: $alto;
+ display: flex;
+ justify-content: space-between;
+ position: absolute;
+ top: 11px;
+ z-index: 0;
+ }
+
+ &__low, &__high {
+ height: 6px;
+ width: 49px;
+ z-index: 1;
+ }
+
+ &__low {
+ background-color: $crimson;
+ }
+
+ &__high {
+ background-color: $caribbean-green;
+ }
+}
\ No newline at end of file
diff --git a/ui/app/css/itcss/components/header.scss b/ui/app/css/itcss/components/header.scss
new file mode 100644
index 000000000..ef84dc3f4
--- /dev/null
+++ b/ui/app/css/itcss/components/header.scss
@@ -0,0 +1,95 @@
+.app-header {
+ align-items: center;
+ visibility: visible;
+ background: $gallery;
+ position: relative;
+ z-index: $header-z-index;
+ display: flex;
+ flex-flow: column nowrap;
+
+ @media screen and (max-width: 575px) {
+ padding: 12px;
+ width: 100%;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, .08);
+ z-index: $mobile-header-z-index;
+ }
+
+ @media screen and (min-width: 576px) {
+ height: 75px;
+ justify-content: center;
+
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 32px;
+ background: $gallery;
+ bottom: -32px;
+ }
+ }
+}
+
+.app-header-contents {
+ display: flex;
+ justify-content: space-between;
+ flex-flow: row nowrap;
+ width: 100%;
+ height: 6.9vh;
+
+ @media screen and (max-width: 575px) {
+ height: 100%;
+ }
+
+ @media screen and (min-width: 576px) {
+ width: 85vw;
+ }
+
+ @media screen and (min-width: 769px) {
+ width: 80vw;
+ }
+
+ @media screen and (min-width: 1281px) {
+ width: 65vw;
+ }
+}
+
+.app-header h1 {
+ font-family: Roboto;
+ text-transform: uppercase;
+ font-weight: 400;
+ color: #22232c; // $shark
+
+ @media screen and (max-width: 575px) {
+ display: none;
+ }
+}
+
+h2.page-subtitle {
+ text-transform: uppercase;
+ color: #aeaeae;
+ font-size: 1em;
+ margin: 12px;
+}
+
+.network-component-wrapper {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ margin-right: 20px;
+}
+
+.left-menu-wrapper {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+
+.header__right-actions {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+
+ .identicon {
+ cursor: pointer;
+ }
+}
diff --git a/ui/app/css/itcss/components/hero-balance.scss b/ui/app/css/itcss/components/hero-balance.scss
new file mode 100644
index 000000000..8f6731358
--- /dev/null
+++ b/ui/app/css/itcss/components/hero-balance.scss
@@ -0,0 +1,110 @@
+.hero-balance {
+
+ @media screen and (max-width: $break-small) {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ margin: .3em .9em 0;
+ height: 80vh;
+ max-height: 225px;
+ }
+
+ @media screen and (min-width: $break-large) {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ margin: 2.8em 2.37em .8em;
+ }
+
+ .balance-container {
+ display: flex;
+ margin: 0;
+ justify-content: flex-start;
+ align-items: center;
+
+ @media screen and (max-width: $break-small) {
+ flex-direction: column;
+ }
+
+ @media screen and (min-width: $break-large) {
+ flex-direction: row;
+ flex-grow: 3;
+ }
+ }
+
+ .balance-display {
+
+ @media screen and (max-width: $break-small) {
+ text-align: center;
+
+ .token-amount {
+ font-size: 175%;
+ margin-top: 12.5%;
+ }
+
+ .fiat-amount {
+ font-size: 115%;
+ margin-top: 8.5%;
+ color: #a0a0a0;
+ }
+ }
+
+ @media screen and (min-width: $break-large) {
+ margin-left: 3%;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .token-amount {
+ font-size: 135%;
+ }
+
+ .fiat-amount {
+ margin-top: .25%;
+ font-size: 105%;
+ }
+ }
+ }
+
+ .balance-icon {
+ border-radius: 25px;
+ width: 45px;
+ height: 45px;
+ border: 1px solid $alto;
+ }
+
+ .hero-balance-buttons {
+
+ @media screen and (max-width: $break-small) {
+ width: 100%;
+ height: 100px; // needed a round number to set the heights of the buttons inside
+ }
+
+ @media screen and (min-width: $break-large) {
+ flex-grow: 2;
+ justify-content: flex-end;
+ }
+
+ button.btn-clear {
+ background: $white;
+ border: 1px solid;
+ border-radius: 2px;
+ font-size: 12px;
+
+ @media screen and (max-width: $break-small) {
+ width: 23%;
+ height: 55%;
+ border-color: $black;
+ }
+
+ @media screen and (min-width: $break-large) {
+ border-color: $curious-blue;
+ color: $curious-blue;
+ padding: 0;
+ width: 85px;
+ height: 34px;
+ }
+ }
+ }
+}
diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss
new file mode 100644
index 000000000..fda002785
--- /dev/null
+++ b/ui/app/css/itcss/components/index.scss
@@ -0,0 +1,40 @@
+@import './buttons.scss';
+
+@import './header.scss';
+
+@import './footer.scss';
+
+@import './network.scss';
+
+@import './modal.scss';
+
+@import './newui-sections.scss';
+
+@import './account-dropdown.scss';
+
+@import './send.scss';
+
+@import './confirm.scss';
+
+// Balances
+@import './hero-balance.scss';
+
+@import './wallet-balance.scss';
+
+// Tx List and Sections
+@import './transaction-list.scss';
+
+@import './sections.scss';
+
+@import './token-list.scss';
+
+@import './add-token.scss';
+
+@import './currency-display.scss';
+
+@import './account-menu.scss';
+
+@import './menu.scss';
+
+@import './gas-slider.scss';
+
diff --git a/ui/app/css/itcss/components/menu.scss b/ui/app/css/itcss/components/menu.scss
new file mode 100644
index 000000000..c98ee70d9
--- /dev/null
+++ b/ui/app/css/itcss/components/menu.scss
@@ -0,0 +1,58 @@
+.menu {
+ border-radius: 4px;
+ background: rgba($black, .8);
+ box-shadow: rgba($black, .15) 0 2px 2px 2px;
+ min-width: 150px;
+ color: $white;
+
+ &__item {
+ padding: 18px;
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+ position: relative;
+ z-index: 200;
+
+ @media screen and (max-width: 575px) {
+ padding: 14px;
+ }
+
+ &--clickable {
+ cursor: pointer;
+
+ &:hover {
+ background-color: rgba($white, .05);
+ }
+
+ &:active {
+ background-color: rgba($white, .1);
+ }
+ }
+
+ &__icon {
+ height: 16px;
+ width: 16px;
+ margin-right: 14px;
+ }
+
+ &__text {
+ font-size: 16px;
+ line-height: 21px;
+ }
+ }
+
+ &__divider {
+ background-color: $scorpion;
+ width: 100%;
+ height: 1px;
+ }
+
+ &__close-area {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ z-index: 100;
+ }
+}
diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss
new file mode 100644
index 000000000..1ffea58a9
--- /dev/null
+++ b/ui/app/css/itcss/components/modal.scss
@@ -0,0 +1,558 @@
+.modal > div:focus {
+ outline: none !important;
+}
+
+// Buy Modal
+.buy-modal-content {
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ font-family: Roboto;
+ padding: 0 16px;
+}
+
+.buy-modal-content-option {
+ cursor: pointer;
+ color: #5B5D67;
+}
+
+.qr-ellip-address, .ellip-address {
+ width: 247px;
+ border: none;
+ font-family: Roboto;
+ font-size: 14px;
+}
+
+@media screen and (max-width: 575px) {
+ .buy-modal-content-title-wrapper {
+ justify-content: space-around;
+ width: 100%;
+ height: 100px;
+ }
+
+ .buy-modal-content-title {
+ font-size: 26px;
+ margin-top: 15px;
+ }
+
+ .buy-modal-content-options {
+ flex-direction: column;
+ padding: 5% 33%;
+ }
+
+ .buy-modal-content-footer {
+ text-transform: uppercase;
+ width: 100%;
+ height: 50px;
+ }
+
+ div.buy-modal-content-option {
+ display: flex;
+ flex-direction: column;
+ width: 80vw;
+ height: 15vh;
+ margin: 10px;
+ text-align: center;
+ border-radius: 6px;
+ border: 1px solid $black;
+ padding: 0% 7%;
+
+ div.buy-modal-content-option-title {
+ font-size: 20px;
+ }
+
+ div.buy-modal-content-option-subtitle {
+ font-size: 16px;
+ }
+ }
+}
+
+@media screen and (min-width: 576px) {
+ .buy-modal-content-title-wrapper {
+ justify-content: space-around;
+ width: 100%;
+ height: 110px;
+ }
+
+ .buy-modal-content-title {
+ font-size: 26px;
+ margin-top: 15px;
+ }
+
+ .buy-modal-content-footer {
+ text-transform: uppercase;
+ width: 100%;
+ height: 50px;
+ }
+
+ .buy-modal-content-options {
+ flex-direction: row;
+ margin: 20px 0 60px;
+ }
+
+ div.buy-modal-content-option {
+ display: flex;
+ flex-direction: column;
+ width: 20vw;
+ height: 120px;
+ text-align: center;
+ border-radius: 6px;
+ border: 1px solid $black;
+ margin: 0 8px;
+ padding: 18px 0;
+
+ div.buy-modal-content-option-title {
+ font-size: 20px;
+ margin-bottom: 12px;
+
+ @media screen and (max-width: 679px) {
+ font-size: 14px;
+ }
+
+ @media screen and (min-width: 1281px) {
+ font-size: 20px;
+ }
+ }
+
+ div.buy-modal-content-option-subtitle {
+ font-size: 16px;
+ padding: 0 10px;
+ height: 25%;
+
+ @media screen and (max-width: 679px) {
+ font-size: 10px;
+ padding: 0 10px;
+ margin-bottom: 5px;
+ line-height: 15px;
+ }
+
+ @media screen and (min-width: 680px) {
+ font-size: 14px;
+ padding: 0 4px;
+ margin-bottom: 2px;
+ }
+
+ @media screen and (min-width: 1281px) {
+ font-size: 16px;
+ padding: 0;
+ }
+ }
+
+ div.buy-modal-content-footer {
+ margin-top: 8vh;
+ }
+ }
+}
+
+// Edit Account Name Modal
+.edit-account-name-modal-content {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ position: relative;
+}
+
+.edit-account-name-modal-cancel {
+ position: absolute;
+ top: 12px;
+ right: 20px;
+ font-size: 25px;
+}
+
+.edit-account-name-modal-title {
+ margin: 15px;
+}
+
+.edit-account-name-modal-save-button {
+ width: 33%;
+ height: 45px;
+ margin: 15px;
+ font-weight: 700;
+ margin-top: 25px;
+}
+
+.edit-account-name-modal-input {
+ width: 90%;
+ height: 50px;
+ text-align: left;
+ margin: 10px;
+ padding: 10px;
+ font-size: 18px;
+}
+
+// Account Modal Container
+.account-modal-container {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ position: relative;
+ padding: 5px 0 31px 0;
+ border: 1px solid $silver;
+ border-radius: 4px;
+ font-family: Roboto;
+
+ button {
+ cursor: pointer;
+ }
+}
+
+.account-modal-back {
+ color: $dusty-gray;
+ position: absolute;
+ top: 13px;
+ left: 17px;
+ cursor: pointer;
+
+ &__text {
+ margin-top: 2px;
+ font-family: Roboto;
+ font-size: 14px;
+ line-height: 18px;
+ }
+}
+
+.account-modal-close::after {
+ content: '\00D7';
+ font-size: 40px;
+ color: $dusty-gray;
+ position: absolute;
+ top: 10px;
+ right: 12px;
+ cursor: pointer;
+}
+
+.account-modal-container .identicon {
+ position: relative;
+ left: 0;
+ right: 0;
+ margin: 0 auto;
+ top: -32px;
+ margin-bottom: -32px;
+}
+
+
+// Account Details Modal
+
+.account-modal-container {
+
+ .qr-header {
+ margin-top: 9px;
+ font-size: 20px;
+ }
+
+ .qr-wrapper {
+ margin-top: 5px;
+ }
+
+ .ellip-address-wrapper {
+ display: flex;
+ justify-content: center;
+ border: 1px solid $alto;
+ padding: 5px 10px;
+ font-family: Roboto;
+ margin-top: 7px;
+ width: 286px;
+ }
+
+ .btn-clear {
+ min-height: 28px;
+ font-size: 14px;
+ border-color: $curious-blue;
+ color: $curious-blue;
+ border-radius: 2px;
+ flex-basis: 100%;
+ width: 75%;
+ margin-top: 17px;
+ padding: 10px 22px;
+ height: 44px;
+ width: 235px;
+ font-family: Roboto;
+ }
+}
+
+.account-modal-divider {
+ width: 100%;
+ height: 1px;
+ margin: 19px 0 8px 0;
+ background-color: $alto;
+}
+
+// Export Private Key Modal
+
+.account-modal-container .account-name {
+ margin-top: 9px;
+ font-size: 20px;
+}
+
+.account-modal-container .modal-body-title {
+ margin-top: 16px;
+ margin-bottom: 16px;
+ font-size: 18px;
+}
+
+.private-key-password {
+ display: flex;
+ flex-direction: column;
+}
+
+.private-key-password-label, .private-key-password-error {
+ color: $scorpion;
+ font-size: 14px;
+ line-height: 18px;
+ margin-bottom: 10px;
+}
+
+.private-key-password-error {
+ color: $crimson;
+ margin-bottom: 0;
+}
+
+.private-key-password-input {
+ padding: 10px 0 13px 17px;
+ font-size: 16px;
+ line-height: 21px;
+ width: 291px;
+ height: 44px;
+}
+
+.private-key-password::-webkit-input-placeholder {
+ color: $dusty-gray;
+ font-family: Roboto;
+}
+
+.private-key-password-warning {
+ border-radius: 8px;
+ background-color: #FFF6F6;
+ font-size: 12px;
+ font-weight: 500;
+ line-height: 15px;
+ color: $crimson;
+ width: 292px;
+ padding: 9px 15px;
+ margin-top: 18px;
+ font-family: Roboto;
+}
+
+.export-private-key-buttons {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+
+ .btn-clear {
+ width: 141px;
+ height: 54px;
+ }
+
+ .btn-cancel {
+ margin-right: 15px;
+ border-color: $dusty-gray;
+ color: $scorpion;
+ }
+}
+
+.private-key-password-display-wrapper {
+ height: 80px;
+ width: 291px;
+ border: 1px solid $silver;
+ border-radius: 2px;
+}
+
+.private-key-password-display-textarea {
+ color: $crimson;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 21px;
+ border: none;
+ height: 75px;
+ width: 100%;
+ overflow: hidden;
+ resize: none;
+ padding: 9px 13px 8px;
+ text-transform: uppercase;
+}
+
+
+// New Account Modal
+.new-account-modal-wrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ position: relative;
+ border: 1px solid $alto;
+ box-shadow: 0 0 2px 2px $alto;
+ font-family: Roboto;
+}
+
+.new-account-modal-header {
+ background: $wild-sand;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ padding: 30px;
+ font-size: 22px;
+ color: $nile-blue;
+ height: 79px;
+}
+
+.modal-close-x::after {
+ content: '\00D7';
+ font-size: 2em;
+ color: $dusty-gray;
+ position: absolute;
+ top: 25px;
+ right: 17.5px;
+ font-family: sans-serif;
+ cursor: pointer;
+}
+
+.new-account-modal-content {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ margin-top: 15px;
+ font-size: 17px;
+ color: $nile-blue;
+}
+
+.new-account-modal-content.after-input {
+ margin-top: 15px;
+ line-height: 25px;
+}
+
+.new-account-input-wrapper {
+ display: flex;
+ width: 100%;
+ justify-content: center;
+ padding-bottom: 2px;
+ margin-top: 13px;
+}
+
+.new-account-input {
+ padding: 15px;
+ padding-bottom: 20px;
+ border-radius: 8px;
+ border: 1px solid $alto;
+ width: 100%;
+ font-size: 1em;
+ color: $dusty-gray;
+ font-family: Roboto;
+ font-size: 17px;
+ margin: 0 60px;
+}
+
+// For reference on below placeholder selectors: https://stackoverflow.com/questions/2610497/change-an-html5-inputs-placeholder-color-with-css
+.new-account-input::-webkit-input-placeholder {
+ color: $dusty-gray;
+}
+
+.new-account-input:-moz-placeholder {
+ color: $dusty-gray;
+ opacity: 1;
+}
+
+.new-account-input::-moz-placeholder {
+ color: $dusty-gray;
+ opacity: 1;
+}
+
+.new-account-input:-ms-input-placeholder {
+ color: $dusty-gray;
+}
+
+.new-account-input::-ms-input-placeholder {
+ color: $dusty-gray;
+}
+
+.new-account-modal-content.button {
+ margin-top: 22px;
+ margin-bottom: 30px;
+ width: 113px;
+ height: 44px;
+}
+
+.new-account-modal-wrapper .btn-clear {
+ font-size: 14px;
+ font-weight: 700;
+ background: $white;
+ border: 1px solid;
+ border-radius: 2px;
+ color: $tundora;
+ flex: 1;
+}
+
+// Hide token confirmation
+
+.hide-token-confirmation {
+ min-height: 250.72px;
+ width: 374.49px;
+ border-radius: 4px;
+ background-color: #FFFFFF;
+ box-shadow: 0 1px 7px 0 rgba(0,0,0,0.5);
+
+ &__container {
+ padding: 24px 27px 21px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ &__identicon {
+ margin-bottom: 10px
+ }
+
+ &__symbol {
+ color: $tundora;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 24px;
+ text-align: center;
+ margin-bottom: 7.5px;
+ }
+
+ &__title {
+ height: 30px;
+ width: 271.28px;
+ color: $tundora;
+ font-family: Roboto;
+ font-size: 22px;
+ line-height: 30px;
+ text-align: center;
+ margin-bottom: 10.5px;
+ }
+
+ &__copy {
+ height: 41px;
+ width: 318px;
+ color: $scorpion;
+ font-family: Roboto;
+ font-size: 14px;
+ line-height: 18px;
+ text-align: center;
+ }
+
+ &__buttons {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ margin-top: 15px;
+ width: 100%;
+
+ button {
+ height: 44px;
+ width: 113px;
+ border: 1px solid $scorpion;
+ border-radius: 2px;
+ color: $tundora;
+ font-family: Roboto;
+ font-size: 14px;
+ line-height: 20px;
+ text-align: center;
+ margin-left: 4px;
+ margin-right: 4px;
+ }
+ }
+}
diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss
new file mode 100644
index 000000000..bb8c4eea8
--- /dev/null
+++ b/ui/app/css/itcss/components/network.scss
@@ -0,0 +1,160 @@
+.network-component.pointer {
+ border: 1px solid $shark;
+ border-radius: 82px;
+ padding: 6px;
+ flex: 0 0 auto;
+
+ &.ethereum-network {
+ border-color: rgb(3, 135, 137);
+
+ .menu-icon-circle div {
+ background-color: rgba(3, 135, 137, .7) !important;
+ }
+ }
+
+ &.ropsten-test-network {
+ border-color: rgb(233, 21, 80);
+
+ .menu-icon-circle div {
+ background-color: rgba(233, 21, 80, .7) !important;
+ }
+ }
+
+ &.kovan-test-network {
+ border-color: rgb(105, 4, 150);
+
+ .menu-icon-circle div {
+ background-color: rgba(105, 4, 150, .7) !important;
+ }
+ }
+
+ &.rinkeby-test-network {
+ border-color: rgb(235, 179, 63);
+
+ .menu-icon-circle div {
+ background-color: rgba(235, 179, 63, .7) !important;
+ }
+ }
+}
+
+.dropdown-menu-item {
+ .menu-icon-circle,
+ .menu-icon-circle--active {
+ margin: 0 16px;
+ }
+}
+
+.network-indicator {
+ display: flex;
+ align-items: center;
+ font-size: .6em;
+
+ .fa-caret-down {
+ line-height: 15px;
+ font-size: 12px;
+ padding: 0 4px;
+ }
+}
+
+.network-name {
+ line-height: 15px;
+ padding: 0 4px;
+ font-family: Roboto;
+ font-size: 12px;
+ flex: 1 0 auto;
+}
+
+.network-droppo {
+ right: 2px;
+
+ @media screen and (min-width: 576px) {
+ right: calc(((100% - 85vw) / 2) + 2px);
+ }
+
+ @media screen and (min-width: 769px) {
+ right: calc(((100% - 80vw) / 2) + 2px);
+ }
+
+ @media screen and (min-width: 1281px) {
+ right: calc(((100% - 65vw) / 2) + 2px);
+ }
+}
+
+.network-name-item {
+ font-weight: 100;
+ flex: 1 0 auto;
+ color: $dusty-gray;
+}
+
+.network-check,
+.network-check__transparent {
+ color: $white;
+ margin-left: 7px;
+}
+
+.network-check__transparent {
+ opacity: 0;
+ width: 16px;
+ margin: 0;
+}
+
+.menu-icon-circle,
+.menu-icon-circle--active {
+ background: none;
+ border-radius: 22px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border: 1px solid transparent;
+ margin: 0 4px;
+}
+
+.menu-icon-circle--active {
+ border: 1px solid $white;
+ background: rgba(100, 100, 100, .4);
+}
+
+.menu-icon-circle div,
+.menu-icon-circle--active div {
+ height: 17px;
+ width: 17px;
+ border-radius: 17px;
+}
+
+.menu-icon-circle--active div {
+ opacity: 1;
+}
+
+.network-dropdown-header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+}
+
+.network-dropdown-divider {
+ width: 100%;
+ height: 1px;
+ margin: 10px 0;
+ background-color: $scorpion;
+}
+
+.network-dropdown-title {
+ height: 25px;
+ width: 75px;
+ color: $white;
+ font-family: Roboto;
+ font-size: 18px;
+ line-height: 25px;
+ text-align: center;
+}
+
+.network-dropdown-content {
+ height: 36px;
+ width: 265px;
+ color: $dusty-gray;
+ font-family: Roboto;
+ font-size: 14px;
+ line-height: 18px;
+}
+
diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss
new file mode 100644
index 000000000..fc1dba87c
--- /dev/null
+++ b/ui/app/css/itcss/components/newui-sections.scss
@@ -0,0 +1,189 @@
+/*
+ NewUI Container Elements
+ */
+
+// Component Colors
+$tx-view-bg: $white;
+$wallet-view-bg: $wild-sand;
+
+// Main container
+.main-container {
+ // position: absolute;
+ z-index: $main-container-z-index;
+ font-family: Roboto;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: stretch;
+}
+
+.main-container::-webkit-scrollbar {
+ display: none;
+}
+
+// tx view
+
+.tx-view {
+ flex: 63.5 0 66.5%;
+ background: $tx-view-bg;
+}
+
+// wallet view and sidebar
+
+.wallet-view {
+ display: flex;
+ flex-direction: column;
+ flex: 33.5 0 33.5%;
+ background: $wallet-view-bg;
+
+ @media screen and (min-width: 576px) {
+ overflow-y: scroll;
+ overflow-x: hidden;
+ }
+
+ .wallet-view-account-details {
+ flex: 0 0 150px;
+ }
+}
+
+@media screen and (min-width: 576px) {
+ .wallet-view::-webkit-scrollbar {
+ display: none;
+ }
+}
+
+.wallet-view-title-wrapper {
+ flex: 0 0 25px;
+}
+
+.wallet-view-title {
+ margin-left: 15px;
+ font-size: 16px;
+
+ // No title on mobile
+ @media screen and (max-width: 575px) {
+ display: none;
+ }
+}
+
+.wallet-view.sidebar {
+ flex: 1 0 230px;
+ background: rgb(250, 250, 250);
+ z-index: $sidebar-z-index;
+ position: fixed;
+ // top: 41px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ opacity: 1;
+ visibility: visible;
+ will-change: transform;
+ overflow-y: auto;
+ box-shadow: rgba(0, 0, 0, .15) 2px 2px 4px;
+ width: 85%;
+ height: 100%;
+}
+
+.sidebar-overlay {
+ z-index: $sidebar-overlay-z-index;
+ position: fixed;
+ // top: 41px;
+ height: 100%;
+ width: 100%;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ opacity: 1;
+ visibility: visible;
+ background-color: rgba(0, 0, 0, .3);
+}
+
+// main-container media queries
+
+@media screen and (min-width: 576px) {
+ .lap-visible {
+ display: flex;
+ }
+
+ .phone-visible {
+ display: none;
+ }
+
+ .main-container {
+ // margin-top: 6.9vh;
+ width: 85%;
+ height: 90vh;
+ box-shadow: 0 0 7px 0 rgba(0, 0, 0, .08);
+ }
+}
+
+@media screen and (min-width: 769px) {
+ .main-container {
+ // margin-top: 6.9vh;
+ width: 80%;
+ height: 82vh;
+ box-shadow: 0 0 7px 0 rgba(0, 0, 0, .08);
+ }
+}
+
+@media screen and (min-width: 1281px) {
+ .main-container {
+ // margin-top: 6.9vh;
+ width: 65%;
+ height: 82vh;
+ box-shadow: 0 0 7px 0 rgba(0, 0, 0, .08);
+ }
+}
+
+@media screen and (max-width: 575px) {
+ .lap-visible {
+ display: none;
+ }
+
+ .phone-visible {
+ display: flex;
+ }
+
+ .main-container {
+ // margin-top: 41px;
+ height: 100%;
+ width: 100%;
+ overflow-y: auto;
+ background-color: $white;
+ }
+
+ button.btn-clear {
+ width: 93px;
+ height: 50px;
+ font-size: .7em;
+ background: $white;
+ border: 1px solid;
+ }
+}
+
+// wallet view
+.account-name {
+
+ @media screen and (max-width: 575px) {
+ font-size: 102%;
+ margin-left: 3%;
+ }
+
+ @media screen and (max-width: 575px) {
+ text-align: center;
+ }
+}
+
+// account options dropdown
+.account-options-menu {
+ align-items: center;
+ justify-content: flex-start;
+ margin: 5% 7% 0%;
+}
+
+.fiat-amount {
+ text-transform: uppercase;
+}
+
+.token-balance__amount {
+ padding-right: 6px;
+}
diff --git a/ui/app/css/index.css b/ui/app/css/itcss/components/sections.scss
similarity index 52%
rename from ui/app/css/index.css
rename to ui/app/css/itcss/components/sections.scss
index 49b432a1f..bc89fdccc 100644
--- a/ui/app/css/index.css
+++ b/ui/app/css/itcss/components/sections.scss
@@ -1,222 +1,26 @@
-/*
-faint orange (textfield shades) #FAF6F0
-light orange (button shades): #F5C26D
-dark orange (text): #F5A623
-borders/font/any gray: #4A4A4A
-*/
+// Old scss, do not lint - clean up later
+/* stylelint-disable */
+
/*
-application specific styles
+App Sections
+ TODO: Move into separate files.
*/
-* {
- box-sizing: border-box;
-}
-
-html, body {
- font-family: 'Montserrat Regular', Arial;
- color: #4D4D4D;
- font-weight: 300;
- line-height: 1.4em;
- background: #F7F7F7;
- margin: 0;
- padding: 0;
-}
-
-html {
- min-height: 500px;
-}
-
-.app-root {
- overflow: hidden;
- position: relative
-}
-
-.app-primary {
- display: flex;
-}
-
-input:focus, textarea:focus {
- outline: none;
-}
-
-.full-size {
- height: 100%;
- width: 100%;
-}
-
-.full-width {
- width: 100%;
-}
-
-.full-height {
- height: 100%;
-}
-
-.full-flex-height {
- display: flex;
- flex: 1 1 auto;
- flex-direction: column;
-}
-
-#app-content {
- overflow-x: hidden;
- min-width: 357px;
- height: 100%;
- display: flex;
- flex-direction: column;
-}
-
-button, input[type="submit"] {
- font-family: 'Montserrat Bold';
- outline: none;
- cursor: pointer;
- padding: 8px 12px;
- border: none;
- color: white;
- transform-origin: center center;
- transition: transform 50ms ease-in;
- /* default orange */
- background: rgba(247, 134, 28, 1);
- box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
-}
-
-.btn-green, input[type="submit"].btn-green {
- background: rgba(106, 195, 96, 1);
- box-shadow: 0px 3px 6px rgba(106, 195, 96, 0.36);
-}
-
-.btn-red {
- background: rgba(254, 35, 17, 1);
- box-shadow: 0px 3px 6px rgba(254, 35, 17, 0.36);
-}
-
-button[disabled], input[type="submit"][disabled] {
- cursor: not-allowed;
- background: rgba(197, 197, 197, 1);
- box-shadow: 0px 3px 6px rgba(197, 197, 197, 0.36);
-}
-
-button.spaced {
- margin: 2px;
-}
-
-button:not([disabled]):hover, input[type="submit"]:not([disabled]):hover {
- transform: scale(1.1);
-}
-button:not([disabled]):active, input[type="submit"]:not([disabled]):active {
- transform: scale(0.95);
-}
-
-a {
- text-decoration: none;
- color: inherit;
-}
-
-a:hover{
- color: #df6b0e;
-}
-
-/*
-app
-*/
-
-.active {
- color: #909090;
-}
-
-button.primary {
- padding: 8px 12px;
- background: #F7861C;
- box-shadow: 0px 3px 6px rgba(247, 134, 28, 0.36);
- color: white;
- font-size: 1.1em;
- font-family: 'Montserrat Regular';
- text-transform: uppercase;
-}
-
-button.btn-thin {
- border: 1px solid;
- border-color: #4D4D4D;
- color: #4D4D4D;
- background: rgb(255, 174, 41);
- border-radius: 4px;
- min-width: 200px;
- margin: 12px 0;
- padding: 6px;
- font-size: 13px;
-}
-
-.app-header {
- padding: 6px 8px;
-}
-
-.app-header h1 {
- font-family: 'Montserrat Regular';
- text-transform: uppercase;
- color: #AEAEAE;
-}
-
-h2.page-subtitle {
- font-family: 'Montserrat Regular';
- text-transform: uppercase;
- color: #AEAEAE;
- font-size: 1em;
- margin: 12px;
-}
-
-.app-footer {
- padding-bottom: 10px;
- align-items: center;
-}
-
-.identicon {
- height: 46px;
- width: 46px;
- background-size: cover;
- border-radius: 100%;
- border: 3px solid gray;
-}
-
+/* initialize */
textarea.twelve-word-phrase {
padding: 12px;
width: 300px;
height: 140px;
font-size: 16px;
- background: white;
+ background: $white;
resize: none;
}
-.network-indicator {
- display: flex;
- align-items: center;
- font-size: 0.6em;
-
-}
-
-.network-name {
- width: 5.2em;
- line-height: 9px;
- text-rendering: geometricPrecision;
-}
-
-.check {
- margin-left: 12px;
- color: #F7861C;
- flex: 1 0 auto;
- display: flex;
- justify-content: flex-end;
-}
-/*
-app sections
-*/
-
-/* initialize */
-
.initialize-screen hr {
width: 60px;
margin: 12px;
- border-color: #F7861C;
+ border-color: #f7861c;
border-style: solid;
}
@@ -235,11 +39,11 @@ app sections
/* unlock */
.error {
- color: #E20202;
+ color: #e20202;
}
.warning {
- color: #FFAE00;
+ color: #ffae00;
}
.lock {
@@ -249,9 +53,10 @@ app sections
.lock.locked {
transform: scale(1.5);
- opacity: 0.0;
+ opacity: 0;
transition: opacity 400ms ease-in, transform 400ms ease-in;
}
+
.lock.unlocked {
transform: scale(1);
opacity: 1;
@@ -262,15 +67,18 @@ app sections
transform: scaleX(1) translateX(0);
transition: transform 250ms ease-in;
}
+
.lock.unlocked .lock-top {
transform: scaleX(-1) translateX(-12px);
transition: transform 250ms ease-in;
}
+
.lock.unlocked:hover {
border-radius: 4px;
background: #e5e5e5;
border: 1px solid #b1b1b1;
}
+
.lock.unlocked:active {
background: #c3c3c3;
}
@@ -290,55 +98,46 @@ app sections
.unlock-screen input[type=password] {
width: 260px;
- /*height: 36px;
- margin-bottom: 24px;
- padding: 8px;*/
}
-.sizing-input{
+.sizing-input {
font-size: 14px;
height: 30px;
padding-left: 5px;
}
-.editable-label{
+
+.editable-label {
display: flex;
}
+
/* Webkit */
+
.unlock-screen input::-webkit-input-placeholder {
text-align: center;
font-size: 1.2em;
}
+
/* Firefox 18- */
+
.unlock-screen input:-moz-placeholder {
text-align: center;
font-size: 1.2em;
}
+
/* Firefox 19+ */
+
.unlock-screen input::-moz-placeholder {
text-align: center;
font-size: 1.2em;
}
+
/* IE */
+
.unlock-screen input:-ms-input-placeholder {
text-align: center;
font-size: 1.2em;
}
-input.large-input, textarea.large-input {
- /*margin-bottom: 24px;*/
- padding: 8px;
-}
-
-input.large-input {
- height: 36px;
-}
-
-.letter-spacey {
- letter-spacing: 0.1em;
-}
-
-
-
/* accounts */
.accounts-section {
@@ -346,7 +145,7 @@ input.large-input {
}
.accounts-section .horizontal-line {
- margin: 0px 18px;
+ margin: 0 18px;
}
.accounts-list-option {
@@ -363,7 +162,7 @@ input.large-input {
}
.unconftx-link .fa-arrow-right {
- margin: 0px -8px 0px 8px;
+ margin: 0 -8px 0px 8px;
}
/* identity panel */
@@ -390,7 +189,7 @@ input.large-input {
.identity-panel i {
margin-top: 32px;
margin-right: 6px;
- color: #B9B9B9;
+ color: #b9b9b9;
}
.identity-panel .arrow-right {
@@ -401,34 +200,33 @@ input.large-input {
}
.identity-copy.flex-column {
- flex: 0.25 0 auto;
+ flex: .25 0 auto;
justify-content: center;
}
/* accounts screen */
.identity-section {
-
}
.identity-section .identity-panel {
- background: #E9E9E9;
- border-bottom: 1px solid #B1B1B1;
+ background: #e9e9e9;
+ border-bottom: 1px solid #b1b1b1;
cursor: pointer;
}
.identity-section .identity-panel.selected {
- background: white;
- color: #F3C83E;
+ background: $white;
+ color: #f3c83e;
}
.identity-section .identity-panel.selected .identicon {
- border-color: orange;
+ border-color: $orange;
}
.identity-section .accounts-list-option:hover,
.identity-section .accounts-list-option.selected {
- background:white;
+ background: $white;
}
/* account detail screen */
@@ -444,15 +242,14 @@ input.large-input {
flex-grow: 10;
}
-.name-label{
-
+.name-label {
}
.unapproved-tx-icon {
height: 16px;
width: 16px;
background: rgb(47, 174, 244);
- border-color: #AEAEAE;
+ border-color: $silver-chalice;
border-radius: 13px;
}
@@ -460,6 +257,7 @@ input.large-input {
height: 100%;
visibility: hidden;
}
+
.editing-label {
display: flex;
justify-content: flex-start;
@@ -467,8 +265,9 @@ input.large-input {
margin-bottom: 2px;
font-size: 11px;
text-rendering: geometricPrecision;
- color: #F7861C;
+ color: #f7861c;
}
+
.name-label:hover .edit-text {
visibility: visible;
}
@@ -480,48 +279,33 @@ input.large-input {
margin: 12px;
margin-bottom: 24px;
border-radius: 4px;
- border: 2px solid #F3C83E;
- background: #FAF6F0;
-}
-
-/* Send Screen */
-
-.send-screen {
-
-}
-
-.send-screen section {
- margin: 8px 16px;
-}
-
-.send-screen input {
- width: 100%;
- font-size: 12px;
+ border: 2px solid #f3c83e;
+ background: #faf6f0;
}
/* Ether Balance Widget */
.ether-balance-amount {
- color: #F7861C;
+ color: #f7861c;
}
.ether-balance-label {
- color: #ABA9AA;
+ color: #aba9aa;
}
/* Info screen */
-.info-gray{
- font-family: 'Montserrat Regular';
+.info-gray {
+ font-family: Roboto;
text-transform: uppercase;
- color: #AEAEAE;
+ color: $silver-chalice;
}
-.icon-size{
+.icon-size {
width: 20px;
}
-.info{
- font-family: 'Montserrat Regular', Arial;
+.info {
+ font-family: Roboto, Arial;
padding-bottom: 10px;
display: inline-block;
padding-left: 5px;
@@ -533,7 +317,6 @@ input.large-input {
align-items: center;
}
-
.custom-radio-selected {
width: 17px;
height: 17px;
@@ -542,7 +325,7 @@ input.large-input {
border-radius: 15px;
border-width: 5px;
background: rgba(247, 134, 28, 1);
- border-color: #F7F7F7;
+ border-color: #f7f7f7;
}
.custom-radio-inactive {
@@ -551,72 +334,59 @@ input.large-input {
border: solid;
border-width: 1px;
border-radius: 24px;
- border-color: #AEAEAE;
+ border-color: $silver-chalice;
}
.radio-titles {
color: rgba(247, 134, 28, 1);
}
-.radio-titles-subtext {
-
-}
-
-.selected-exchange {
-
-}
-
-.buy-radio {
-
-}
-
-.eth-warning{
+.eth-warning {
transition: opacity 400ms ease-in, transform 400ms ease-in;
}
-.buy-subview{
+.buy-subview {
transition: opacity 400ms ease-in, transform 400ms ease-in;
}
-.input-container:hover .edit-text{
+.input-container:hover .edit-text {
visibility: visible;
}
-.buy-inputs{
- font-family: 'Montserrat Light';
+.buy-inputs {
+ font-family: Roboto;
font-size: 13px;
height: 20px;
background: transparent;
box-sizing: border-box;
border: solid;
border-color: transparent;
- border-width: 0.5px;
+ border-width: .5px;
border-radius: 2px;
-
}
-.input-container:hover .buy-inputs{
+
+.input-container:hover .buy-inputs {
box-sizing: inherit;
border: solid;
- border-color: #F7861C;
- border-width: 0.5px;
+ border-color: #f7861c;
+ border-width: .5px;
border-radius: 2px;
}
-.buy-inputs:focus{
+.buy-inputs:focus {
border: solid;
- border-color: #F7861C;
- border-width: 0.5px;
+ border-color: #f7861c;
+ border-width: .5px;
border-radius: 2px;
}
.activeForm {
- background: #F7F7F7;
+ background: #f7f7f7;
border: none;
border-radius: 8px 8px 0px 0px;
width: 50%;
text-align: center;
padding-bottom: 4px;
-
}
.inactiveForm {
@@ -628,19 +398,19 @@ input.large-input {
}
.ex-coins {
- font-family: 'Montserrat Regular';
+ font-family: Roboto;
text-transform: uppercase;
text-align: center;
font-size: 33px;
width: 118px;
height: 42px;
padding: 1px;
- color: #4D4D4D;
+ color: #4d4d4d;
}
-.marketinfo{
- font-family: 'Montserrat light';
- color: #AEAEAE;
+.marketinfo {
+ font-family: Roboto;
+ color: $silver-chalice;
font-size: 15px;
line-height: 17px;
}
@@ -655,52 +425,50 @@ input.large-input {
overflow: scroll;
}
-.icon-control .fa-refresh{
+.icon-control .fa-refresh {
visibility: hidden;
}
-.icon-control:hover .fa-refresh{
+.icon-control:hover .fa-refresh {
visibility: visible;
}
-.icon-control:hover .fa-chevron-right{
+.icon-control:hover .fa-chevron-right {
visibility: hidden;
}
.inactive {
- color: #AEAEAE;
+ color: $silver-chalice;
}
-.inactive button{
- background: #AEAEAE;
- color: white;
+.inactive button {
+ background: $silver-chalice;
+ color: $white;
}
-.ellip-address {
+.qr-ellip-address, .ellip-address {
overflow: hidden;
text-overflow: ellipsis;
- width: 5em;
- font-size: 14px;
- font-family: "Montserrat Light";
- margin-left: 5px;
}
.qr-header {
- font-size: 25px;
- margin-top: 40px;
+ font-size: 25px;
+ margin-top: 40px;
}
.qr-message {
font-size: 12px;
- color: #F7861C;
+ color: #f7861c;
}
div.message-container > div:first-child {
margin-top: 18px;
font-size: 15px;
- color: #4D4D4D;
+ color: #4d4d4d;
}
.pop-hover:hover {
- transform: scale(1.1);
+ transform: scale(1.1);
}
+
+/* stylelint-enable */
diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss
new file mode 100644
index 000000000..7e72e8399
--- /dev/null
+++ b/ui/app/css/itcss/components/send.scss
@@ -0,0 +1,803 @@
+.send-screen-wrapper {
+ display: flex;
+ flex-flow: column nowrap;
+ z-index: 25;
+ font-family: Roboto;
+
+ @media screen and (max-width: $break-small) {
+ width: 100%;
+ overflow-y: auto;
+ }
+
+ section {
+ flex: 0 0 auto;
+ }
+}
+
+.send-screen-card {
+ background-color: #fff;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .08);
+ padding: 46px 40.5px 26px;
+ position: relative;
+ // top: -26px;
+ align-items: center;
+ display: flex;
+ flex-flow: column nowrap;
+ width: 498px;
+ flex: 1 0 auto;
+
+ @media screen and (max-width: $break-small) {
+ top: 0;
+ width: 100%;
+ box-shadow: none;
+ padding: 12px;
+ }
+}
+
+/* Send Screen */
+
+.send-screen section {
+ margin: 4px 16px;
+}
+
+.send-screen input {
+ width: 100%;
+ font-size: 12px;
+}
+
+.send-eth-icon {
+ border-radius: 50%;
+ width: 70px;
+ height: 70px;
+ border: 1px solid $alto;
+ box-shadow: 0 0 4px 0 rgba(0, 0, 0, .2);
+ position: absolute;
+ top: -35px;
+ z-index: 25;
+ padding: 4px;
+ background-color: $white;
+
+ @media screen and (max-width: $break-small) {
+ position: relative;
+ top: 0;
+ }
+}
+
+.send-screen-input-wrapper {
+ width: 95%;
+ position: relative;
+
+ .fa-bolt {
+ padding-right: 4px;
+ }
+
+ .large-input {
+ border: 1px solid $dusty-gray;
+ border-radius: 4px;
+ margin: 4px 0 20px;
+ font-size: 16px;
+ line-height: 22.4px;
+ font-family: Roboto;
+ }
+
+ .send-screen-gas-input {
+ border: 1px solid transparent;
+ }
+
+ &__error-message {
+ display: none;
+ }
+
+ &--error {
+ input,
+ .send-screen-gas-input {
+ border-color: $red !important;
+ }
+
+ .send-screen-input-wrapper__error-message {
+ display: block;
+ position: absolute;
+ bottom: 4px;
+ font-size: 12px;
+ line-height: 12px;
+ left: 8px;
+ color: $red;
+ }
+ }
+
+ .send-screen-input-wrapper__error-message {
+ display: block;
+ position: absolute;
+ bottom: 4px;
+ font-size: 12px;
+ line-height: 12px;
+ left: 8px;
+ color: $red;
+ }
+}
+
+.send-screen-input {
+ width: 100%;
+}
+
+.send-screen-gas-input {
+ width: 100%;
+ height: 41px;
+ border-radius: 3px;
+ background-color: #f3f3f3;
+ border-width: 0;
+ border-style: none;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding-left: 10px;
+ padding-right: 12px;
+ font-size: 16px;
+ color: $scorpion;
+}
+
+.send-screen-amount-labels {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+.send-screen-gas-labels {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+.currency-toggle {
+ &__item {
+ color: $curious-blue;
+ cursor: pointer;
+
+ &--selected {
+ color: $black;
+ cursor: default;
+ }
+ }
+}
+
+.send-screen-gas-input-customize {
+ color: $curious-blue;
+ font-size: 12px;
+ cursor: pointer;
+}
+
+.gas-tooltip-close-area {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1000;
+ width: 100%;
+ height: 100%;
+}
+
+.customize-gas-tooltip-container {
+ position: absolute;
+ bottom: 50px;
+ width: 237px;
+ height: 307px;
+ background-color: $white;
+ opacity: 1;
+ box-shadow: $alto 0 0 5px;
+ z-index: 1050;
+ padding: 13px 19px;
+ font-size: 16px;
+ border-radius: 4px;
+ font-family: "Lato";
+ font-weight: 500;
+}
+
+.gas-tooltip-arrow {
+ height: 25px;
+ width: 25px;
+ z-index: 1200;
+ background: $white;
+ position: absolute;
+ transform: rotate(45deg);
+ left: 107px;
+ top: 294px;
+ box-shadow: 2px 2px 2px $alto;
+}
+
+.customize-gas-tooltip-container input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ display: none;
+}
+
+.customize-gas-tooltip-container input[type="number"]:hover::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ display: none;
+}
+
+.customize-gas-tooltip {
+ position: relative;
+}
+
+.gas-tooltip {
+ display: flex;
+ justify-content: center;
+}
+
+.gas-tooltip-label {
+ font-size: 16px;
+ color: $tundora;
+}
+
+.gas-tooltip-header {
+ padding-bottom: 12px;
+}
+
+.gas-tooltip-input-label {
+ margin-bottom: 5px;
+}
+
+.gas-tooltip-input-label i {
+ color: $silver-chalice;
+ margin-left: 6px;
+}
+
+.customize-gas-input {
+ width: 178px;
+ height: 28px;
+ border: 1px solid $alto;
+ font-size: 16px;
+ color: $nile-blue;
+ padding-left: 8px;
+}
+
+.customize-gas-input-wrapper {
+ position: relative;
+}
+
+.gas-tooltip-input-detail {
+ position: absolute;
+ top: 4px;
+ right: 26px;
+ font-size: 12px;
+ color: $silver-chalice;
+}
+
+.gas-tooltip-input-arrows {
+ position: absolute;
+ top: 0;
+ right: 4px;
+ width: 17px;
+ height: 28px;
+ border: 1px solid #dadada;
+ border-left: 0;
+ display: flex;
+ flex-direction: column;
+ color: #9b9b9b;
+ font-size: .8em;
+ padding: 1px 4px;
+}
+
+.token-gas {
+ &__amount {
+ display: inline-block;
+ margin-right: 4px;
+ }
+
+ &__symbol {
+ display: inline-block;
+ }
+}
+
+.send-screen {
+ &__title {
+ color: $scorpion;
+ font-size: 18px;
+ line-height: 29px;
+ }
+
+ &__subtitle {
+ margin: 10px 0 20px;
+ font-size: 14px;
+ line-height: 24px;
+ }
+
+ &__send-button,
+ &__cancel-button {
+ width: 163px;
+ text-align: center;
+ }
+
+ &__send-button__disabled {
+ opacity: .5;
+ cursor: auto;
+ }
+}
+
+.send-token {
+ display: flex;
+ flex-flow: column nowrap;
+ z-index: 25;
+ font-family: Roboto;
+
+ &__content {
+ width: 498px;
+ height: 605px;
+ background-color: #fff;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .08);
+ padding: 46px 40.5px 26px;
+ position: relative;
+ // top: -26px;
+ align-items: center;
+ display: flex;
+ flex-flow: column nowrap;
+ flex: 1 0 auto;
+
+ @media screen and (max-width: $break-small) {
+ top: 0;
+ width: 100%;
+ box-shadow: none;
+ padding: 12px;
+ }
+ }
+
+ .identicon {
+ position: absolute;
+ top: -35px;
+ z-index: 25;
+
+ @media screen and (max-width: $break-small) {
+ position: relative;
+ top: 0;
+ flex: 0 0 auto;
+ }
+ }
+
+ &__title {
+ color: $scorpion;
+ font-size: 18px;
+ line-height: 29px;
+ }
+
+ &__description,
+ &__balance-text,
+ &__token-symbol {
+ margin-top: 10px;
+ font-size: 14px;
+ line-height: 24px;
+ text-align: center;
+ }
+
+ &__token-balance {
+ font-size: 40px;
+ line-height: 40px;
+ margin-top: 13px;
+
+ .token-balance__amount {
+ padding-right: 12px;
+ }
+ }
+
+ &__button-group {
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: center;
+ flex: 0 0 auto;
+
+ @media screen and (max-width: $break-small) {
+ margin-top: 24px;
+ }
+
+ button {
+ width: 163px;
+ }
+ }
+}
+
+.confirm-send-token {
+ &__hero-amount-wrapper {
+ width: 100%;
+ }
+}
+
+.send-v2 {
+ &__container {
+ height: 701px;
+ width: 380px;
+ border-radius: 8px;
+ background-color: $white;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .08);
+ display: flex;
+ flex-flow: column nowrap;
+ z-index: 25;
+ align-items: center;
+ font-family: Roboto;
+ position: relative;
+
+ @media screen and (max-width: $break-small) {
+ width: 100%;
+ overflow-y: auto;
+ top: 0;
+ box-shadow: none;
+ }
+ }
+
+ &__send-header-icon-container {
+ z-index: 25;
+
+ @media screen and (max-width: $break-small) {
+ position: relative;
+ top: 0;
+ }
+ }
+
+ &__send-header-icon {
+ border-radius: 50%;
+ width: 48px;
+ height: 48px;
+ border: 1px solid $alto;
+ z-index: 25;
+ padding: 4px;
+ background-color: $white;
+ }
+
+ &__send-arrow-icon {
+ color: #f28930;
+ transform: rotate(-45deg);
+ position: absolute;
+ top: -2px;
+ left: 0;
+ font-size: 1.12em;
+ }
+
+ &__arrow-background {
+ background-color: $white;
+ height: 14px;
+ width: 14px;
+ position: absolute;
+ top: 52px;
+ left: 199px;
+ border-radius: 50%;
+ z-index: 100;
+ }
+
+ &__header {
+ height: 88px;
+ width: 380px;
+ background-color: $athens-grey;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ &__header-tip {
+ height: 25px;
+ width: 25px;
+ background: $athens-grey;
+ position: absolute;
+ transform: rotate(45deg);
+ left: 178px;
+ top: 65px;
+ }
+
+ &__title {
+ color: $scorpion;
+ font-size: 22px;
+ line-height: 29px;
+ text-align: center;
+ margin-top: 25px;
+ }
+
+ &__copy {
+ color: $gray;
+ font-size: 14px;
+ font-weight: 300;
+ line-height: 19px;
+ text-align: center;
+ margin-top: 10px;
+ width: 287px;
+ }
+
+ &__error {
+ font-size: 12px;
+ line-height: 12px;
+ left: 8px;
+ color: $red;
+ }
+
+ &__error-border {
+ color: $red;
+ }
+
+ &__form {
+ display: flex;
+ flex-direction: column;
+ margin-top: 13px;
+ width: 100%;
+ }
+
+ &__form-row {
+ margin: 14.5px 18px 0px;
+ display: flex;
+ position: relative;
+ justify-content: space-between;
+ }
+
+ &__form-label {
+ color: $scorpion;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 22px;
+ display: flex;
+ flex-flow: column;
+ justify-content: center;
+ }
+
+ &__from-dropdown {
+ height: 73px;
+ width: 240px;
+ border: 1px solid $alto;
+ border-radius: 4px;
+ background-color: $white;
+ font-family: Roboto;
+ line-height: 16px;
+ font-size: 12px;
+ color: $tundora;
+
+ &__close-area {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1000;
+ width: 100%;
+ height: 100%;
+ }
+
+ &__list {
+ z-index: 1050;
+ position: absolute;
+ height: 220px;
+ width: 240px;
+ border: 1px solid $geyser;
+ border-radius: 4px;
+ background-color: $white;
+ box-shadow: 0 3px 6px 0 rgba(0 ,0 ,0 ,.11);
+ margin-top: 11px;
+ margin-left: -1px;
+ overflow-y: scroll;
+ }
+ }
+
+ &__to-autocomplete, &__memo-text-area {
+ &__input {
+ height: 54px;
+ width: 240px;
+ border: 1px solid $alto;
+ border-radius: 4px;
+ background-color: $white;
+ color: $dusty-gray;
+ padding: 10px;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 21px;
+ font-weight: 300;
+ }
+ }
+
+ &__sliders-icon-container {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 24px;
+ width: 24px;
+ border: 1px solid $curious-blue;
+ border-radius: 4px;
+ background-color: $white;
+ padding: 5px;
+ position: absolute;
+ right: 15px;
+ top: 14px;
+ cursor: pointer;
+ }
+
+ &__sliders-icon {
+ color: $curious-blue;
+ }
+
+ &__memo-text-area {
+ &__input {
+ padding: 6px 10px;
+ }
+ }
+
+ &__footer {
+ height: 92px;
+ width: 100%;
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+ border-top: 1px solid $alto;
+ margin-top: 29px;
+ }
+
+ &__next-btn,
+ &__cancel-btn {
+ width: 163px;
+ text-align: center;
+ height: 55px;
+ width: 163px;
+ border-radius: 2px;
+ background-color: $white;
+ font-family: Roboto;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 21px;
+ text-align: center;
+ border: 1px solid;
+ }
+
+ &__next-btn__disabled {
+ opacity: .5;
+ cursor: auto;
+ }
+
+ &__next-btn {
+ color: $curious-blue;
+ border-color: $curious-blue;
+ }
+
+ &__cancel-btn {
+ color: $dusty-gray;
+ border-color: $dusty-gray;
+ }
+
+ &__customize-gas {
+ border: 1px solid #D8D8D8;
+ border-radius: 4px;
+ background-color: #FFFFFF;
+ box-shadow: 0 2px 4px 0 rgba(0,0,0,0.14);
+ font-family: Roboto;
+ display: flex;
+ flex-flow: column;
+
+ @media screen and (max-width: $break-small) {
+ width: 355px;
+ height: 598px;
+ }
+
+ &__header {
+ height: 52px;
+ border-bottom: 1px solid $alto;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 22px;
+ }
+
+ &__title {
+ margin-left: 19.25px;
+ }
+
+ &__close::after {
+ content: '\00D7';
+ font-size: 1.8em;
+ color: $dusty-gray;
+ font-family: sans-serif;
+ cursor: pointer;
+ margin-right: 19.25px;
+ }
+
+ &__body {
+ height: 248px;
+ display: flex;
+
+ @media screen and (max-width: $break-small) {
+ width: 355px;
+ height: 470px;
+ flex-flow: column;
+ }
+ }
+
+ &__footer {
+ height: 75px;
+ border-top: 1px solid $alto;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 22px;
+ }
+
+ &__buttons {
+ display: flex;
+ justify-content: space-between;
+ width: 181.75px;
+ margin-right: 21.25px;
+ }
+
+ &__revert, &__cancel, &__save {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ }
+
+ &__revert {
+ color: $silver-chalice;
+ font-size: 16px;
+ margin-left: 21.25px;
+ }
+
+ &__cancel, &__save {
+ height: 34.64px;
+ width: 85.74px;
+ border: 1px solid $dusty-gray;
+ border-radius: 2px;
+ font-family: 'DIN OT';
+ font-size: 12px;
+ color: $dusty-gray;
+ }
+ }
+
+ &__gas-modal-card {
+ width: 360px;
+ display: flex;
+ flex-flow: column;
+ align-items: flex-start;
+ padding-left: 20px;
+
+ &__title {
+ height: 26px;
+ width: 84px;
+ color: $tundora;
+ font-family: Roboto;
+ font-size: 20px;
+ font-weight: 300;
+ line-height: 26px;
+ margin-top: 17px;
+ }
+
+ &__copy {
+ height: 38px;
+ width: 314px;
+ color: $tundora;
+ font-family: Roboto;
+ font-size: 14px;
+ line-height: 19px;
+ margin-top: 17px;
+ }
+
+ .customize-gas-input-wrapper {
+ margin-top: 17px;
+ }
+
+ .customize-gas-input {
+ height: 54px;
+ width: 315px;
+ border: 1px solid $geyser;
+ background-color: $white;
+ padding-left: 15px;
+ }
+
+ .gas-tooltip-input-arrows {
+ width: 32px;
+ height: 54px;
+ border-left: 1px solid #dadada;
+ font-size: 18px;
+ color: $tundora;
+ right: 0px;
+ padding: 1px 4px;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ }
+
+ input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ display: none;
+ }
+
+ input[type="number"]:hover::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ display: none;
+ }
+ }
+}
diff --git a/ui/app/css/itcss/components/token-list.scss b/ui/app/css/itcss/components/token-list.scss
new file mode 100644
index 000000000..bbc64c324
--- /dev/null
+++ b/ui/app/css/itcss/components/token-list.scss
@@ -0,0 +1,99 @@
+$wallet-balance-breakpoint: 890px;
+$wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (max-width: #{$wallet-balance-breakpoint})";
+
+.token-list-item {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+ padding: 20px 24px;
+ cursor: pointer;
+ transition: linear 200ms;
+ background-color: rgba($wallet-balance-bg, 0);
+ position: relative;
+
+ &__token-balance {
+ font-size: 130%;
+
+ @media #{$wallet-balance-breakpoint-range} {
+ font-size: 105%;
+ }
+ }
+
+ &__fiat-amount {
+ margin-top: .25%;
+ font-size: 105%;
+ text-transform: uppercase;
+
+ @media #{$wallet-balance-breakpoint-range} {
+ font-size: 95%;
+ }
+ }
+
+ @media #{$wallet-balance-breakpoint-range} {
+ padding: 10% 4%;
+ }
+
+ &--active {
+ background-color: rgba($wallet-balance-bg, 1);
+ }
+
+ &__identicon {
+ margin-right: 15px;
+ border: '1px solid #dedede';
+
+ @media #{$wallet-balance-breakpoint-range} {
+ margin-right: 4%;
+ }
+ }
+
+ &__ellipsis {
+ // position: absolute;
+ // top: 20px;
+ // right: 24px;
+ line-height: 45px;
+ }
+
+ &__balance-wrapper {
+ flex: 1 1 auto;
+ }
+}
+
+.token-menu-dropdown {
+ height: 55px;
+ width: 191px;
+ border-radius: 4px;
+ background-color: rgba(0,0,0,0.82);
+ box-shadow: 0 2px 4px 0 rgba(0,0,0,0.5);
+ position: fixed;
+ margin-top: 20px;
+ margin-left: 105px;
+
+ &__close-area {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1000;
+ width: 100%;
+ height: 100%;
+ }
+
+ &__container {
+ padding: 16px 34px 32px;
+ z-index: 1050;
+ position: relative;
+ }
+
+ &__options {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ &__option {
+ color: $white;
+ font-family: Roboto;
+ font-size: 16px;
+ line-height: 21px;
+ text-align: center;
+ }
+}
\ No newline at end of file
diff --git a/ui/app/css/itcss/components/transaction-list.scss b/ui/app/css/itcss/components/transaction-list.scss
new file mode 100644
index 000000000..76fac09e2
--- /dev/null
+++ b/ui/app/css/itcss/components/transaction-list.scss
@@ -0,0 +1,257 @@
+.tx-list-container {
+ height: 87.5%;
+
+ @media screen and (min-width: $break-large) {
+ overflow-y: scroll;
+ }
+}
+
+.tx-list-header {
+ text-transform: capitalize;
+}
+
+@media screen and (max-width: $break-small) {
+ .tx-list-header-wrapper {
+ margin-top: .2em;
+ margin-bottom: .6em;
+ // TODO: Resolve Layout Conflicst in Wallet View
+ // - This fixes txlist "transactions" title dispay
+ // margin-top: 0.2em;
+ // margin-bottom: 0.6em;
+ justify-content: center;
+ }
+
+ .tx-list-header {
+ align-self: center;
+ font-size: 12px;
+ color: $dusty-gray;
+ }
+}
+
+@media screen and (min-width: $break-large) {
+ .tx-list-header-wrapper {
+ flex: 0 0 55px;
+ }
+
+ .tx-list-header {
+ font-size: 16px;
+ margin: 1.5em 2.37em;
+ }
+
+ .tx-list-container::-webkit-scrollbar {
+ display: none;
+ }
+}
+
+.tx-list-content-divider {
+ height: 1px;
+ background: rgb(231, 231, 231);
+ flex: 0 0 1px;
+
+ @media screen and (max-width: $break-small) {
+ margin: .1em 0;
+ }
+
+ @media screen and (min-width: $break-large) {
+ margin: .1em 2.37em;
+ }
+}
+
+.tx-list-item-wrapper {
+ flex: 1 1 auto;
+ width: 0;
+ align-items: stretch;
+ justify-content: flex-start;
+ display: flex;
+ flex-flow: column nowrap;
+
+ @media screen and (max-width: $break-small) {
+ padding: 0 1.3em;
+ }
+
+ @media screen and (min-width: $break-large) {
+ padding-bottom: 12px;
+ }
+}
+
+.tx-list-clickable {
+ cursor: pointer;
+
+ &:hover {
+ background: rgba($alto, .2);
+ }
+}
+
+.tx-list-pending-item-container {
+ cursor: pointer;
+ opacity: .5;
+}
+
+.tx-list-date-wrapper {
+ flex: 1 1 auto;
+
+ @media screen and (max-width: $break-small) {
+ margin-top: 6px;
+ }
+
+ @media screen and (min-width: $break-large) {
+ margin-top: 12px;
+ }
+}
+
+.tx-list-content-wrapper {
+ align-items: stretch;
+ margin-bottom: 4px;
+ margin-top: 2px;
+ flex: 1 0 auto;
+ width: 100%;
+ display: flex;
+ flex-flow: row nowrap;
+
+ @media screen and (max-width: $break-small) {
+ font-size: 12px;
+
+ .tx-list-status {
+ font-size: 12px !important;
+ }
+
+ .tx-list-account {
+ font-size: 14px !important;
+ }
+
+ .tx-list-value {
+ font-size: 14px;
+ }
+
+ .tx-list-fiat-value {
+ font-size: 12px;
+ }
+ }
+}
+
+.tx-list-date {
+ color: $dusty-gray;
+ font-size: 12px;
+ font-family: Roboto;
+}
+
+.tx-list-identicon-wrapper {
+ align-self: center;
+ flex: 0 0 auto;
+ margin-right: 16px;
+}
+
+.tx-list-account-and-status-wrapper {
+ display: flex;
+ flex: 1 1 auto;
+ flex-flow: row wrap;
+ width: 0;
+
+ @media screen and (max-width: $break-small) {
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+ align-self: center;
+ }
+
+ @media screen and (min-width: $break-large) {
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+
+ .tx-list-account-wrapper {
+ flex: 1.3 2 auto;
+ min-width: 153px;
+ }
+
+ .tx-list-status-wrapper {
+ flex: 6 6 auto;
+ }
+ }
+
+ .tx-list-account {
+ font-size: 16px;
+ color: $scorpion;
+ }
+
+ .tx-list-status {
+ color: $dusty-gray;
+ font-size: 16px;
+ text-transform: capitalize;
+ }
+
+ .tx-list-status--rejected,
+ .tx-list-status--failed {
+ color: $monzo;
+ }
+}
+
+.tx-list-item {
+ border-top: 1px solid rgb(231, 231, 231);
+ flex: 0 0 auto;
+ display: flex;
+ flex-flow: row nowrap;
+
+ @media screen and (max-width: $break-small) {
+ // margin: 0 1.3em .95em; !important
+ }
+
+ @media screen and (min-width: $break-large) {
+ margin: 0 2.37em;
+ }
+
+ &:last-of-type {
+ border-bottom: 1px solid rgb(231, 231, 231);
+ margin-bottom: 32px;
+ }
+
+ &__wrapper {
+ align-self: center;
+ flex: 2 2 auto;
+ color: $dusty-gray;
+
+ .tx-list-value {
+ font-size: 16px;
+ text-align: right;
+ }
+
+ .tx-list-value--confirmed {
+ color: $caribbean-green;
+ }
+
+ .tx-list-fiat-value {
+ font-size: 12px;
+ text-align: right;
+ }
+ }
+
+ &--empty {
+ text-align: center;
+ border-bottom: none !important;
+ padding: 16px;
+ }
+}
+
+.tx-list-details-wrapper {
+ overflow: hidden;
+ flex: 0 0 35%;
+}
+
+.tx-list-value {
+ font-size: 16px;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.tx-list-fiat-value {
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.tx-list-value--confirmed {
+ color: $caribbean-green;
+}
diff --git a/ui/app/css/itcss/components/wallet-balance.scss b/ui/app/css/itcss/components/wallet-balance.scss
new file mode 100644
index 000000000..cd44f89bb
--- /dev/null
+++ b/ui/app/css/itcss/components/wallet-balance.scss
@@ -0,0 +1,70 @@
+$wallet-balance-bg: $gallery;
+$wallet-balance-breakpoint: 890px;
+$wallet-balance-breakpoint-range: "screen and (min-width: #{$break-large}) and (max-width: #{$wallet-balance-breakpoint})";
+
+.wallet-balance-wrapper {
+ flex: 0 0 auto;
+ transition: linear 200ms;
+ background: rgba($wallet-balance-bg, 0);
+
+ &--active {
+ background: rgba($wallet-balance-bg, 1);
+ }
+}
+
+.wallet-balance {
+ background: inherit;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ flex: 0 0 auto;
+ cursor: pointer;
+
+ .balance-container {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ margin: 20px 24px;
+ flex-direction: row;
+ flex-grow: 3;
+
+ @media #{$wallet-balance-breakpoint-range} {
+ margin: 10% 4%;
+ }
+ }
+
+ .balance-display {
+ margin-left: 15px;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .token-amount {
+ font-size: 135%;
+ }
+
+ .fiat-amount {
+ margin-top: .25%;
+ font-size: 105%;
+ }
+
+ @media #{$wallet-balance-breakpoint-range} {
+ margin-left: 4%;
+
+ .token-amount {
+ font-size: 105%;
+ }
+
+ .fiat-amount {
+ font-size: 95%;
+ }
+ }
+ }
+
+ .balance-icon {
+ border-radius: 25px;
+ width: 45px;
+ height: 45px;
+ border: 1px solid $alto;
+ }
+}
diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss
new file mode 100644
index 000000000..9d55324e3
--- /dev/null
+++ b/ui/app/css/itcss/generic/index.scss
@@ -0,0 +1,71 @@
+/*
+ Generic
+ */
+
+@import './reset.scss';
+
+* {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ font-family: Roboto, Arial;
+ color: #4d4d4d;
+ font-weight: 300;
+ line-height: 1.4em;
+ background: #f7f7f7;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+}
+
+html {
+ min-height: 500px;
+}
+
+.app-root {
+ overflow: hidden;
+ position: relative;
+}
+
+.app-primary {
+ display: flex;
+}
+
+input:focus,
+textarea:focus {
+ outline: none;
+}
+
+/* stylelint-disable */
+#app-content {
+ overflow-x: hidden;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+
+ @media screen and (max-width: $break-small) {
+ background-color: $white;
+ }
+}
+/* stylelint-enable */
+
+a {
+ text-decoration: none;
+ color: inherit;
+}
+
+a:hover {
+ color: #df6b0e;
+}
+
+input.large-input,
+textarea.large-input {
+ padding: 8px;
+}
+
+input.large-input {
+ height: 36px;
+}
diff --git a/ui/app/css/itcss/generic/reset.scss b/ui/app/css/itcss/generic/reset.scss
new file mode 100644
index 000000000..e054d533e
--- /dev/null
+++ b/ui/app/css/itcss/generic/reset.scss
@@ -0,0 +1,147 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ /* stylelint-disable */
+ font: inherit;
+ /* stylelint-enable */
+ vertical-align: baseline;
+}
+
+/* HTML5 display-role reset for older browsers */
+
+/* stylelint-disable */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+ display: block;
+}
+
+body {
+ line-height: 1;
+}
+
+ol,
+ul {
+ list-style: none;
+}
+
+blockquote,
+q {
+ quotes: none;
+}
+
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+ content: '';
+ content: none;
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+button {
+ border-style: none;
+ cursor: pointer;
+}
+
+/* stylelint-enable */
diff --git a/ui/app/css/itcss/objects/index.scss b/ui/app/css/itcss/objects/index.scss
new file mode 100644
index 000000000..220775682
--- /dev/null
+++ b/ui/app/css/itcss/objects/index.scss
@@ -0,0 +1 @@
+// Objects
diff --git a/ui/app/css/itcss/settings/index.scss b/ui/app/css/itcss/settings/index.scss
new file mode 100644
index 000000000..58a7ca7b7
--- /dev/null
+++ b/ui/app/css/itcss/settings/index.scss
@@ -0,0 +1,3 @@
+@import './variables.scss';
+
+@import './typography.scss';
diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss
new file mode 100644
index 000000000..58e2d444e
--- /dev/null
+++ b/ui/app/css/itcss/settings/typography.scss
@@ -0,0 +1,71 @@
+@import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900');
+
+@import url('https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css');
+
+@font-face {
+ font-family: 'Montserrat Regular';
+ src: url('/fonts/Montserrat/Montserrat-Regular.woff') format('woff');
+ src: url('/fonts/Montserrat/Montserrat-Regular.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+ font-size: 'small';
+}
+
+@font-face {
+ font-family: 'Montserrat Bold';
+ src: url('/fonts/Montserrat/Montserrat-Bold.woff') format('woff');
+ src: url('/fonts/Montserrat/Montserrat-Bold.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Montserrat Light';
+ src: url('/fonts/Montserrat/Montserrat-Light.woff') format('woff');
+ src: url('/fonts/Montserrat/Montserrat-Light.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Montserrat UltraLight';
+ src: url('/fonts/Montserrat/Montserrat-UltraLight.woff') format('woff');
+ src: url('/fonts/Montserrat/Montserrat-UltraLight.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'DIN OT';
+ src: url('/fonts/DIN_OT/DINOT-2.otf') format('opentype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'DIN OT Light';
+ src: url('/fonts/DIN_OT/DINOT-2.otf') format('opentype');
+ font-weight: 200;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'DIN NEXT';
+ src: url('/fonts/DIN NEXT/DIN NEXT W01 Regular.otf') format('opentype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'DIN NEXT Light';
+ src: url('/fonts/DIN NEXT/DIN NEXT W10 Light.otf') format('opentype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Lato';
+ src: url('/fonts/Lato/Lato-Regular.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+}
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
new file mode 100644
index 000000000..387d14b5f
--- /dev/null
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -0,0 +1,77 @@
+/*
+ Variables
+ */
+
+// Base Colors
+$white: #fff;
+$black: #000;
+$orange: #ffa500;
+$red: #f00;
+$gray: #808080;
+
+/*
+ Colors
+ http://chir.ag/projects/name-that-color
+ */
+$white-linen: #faf6f0; // formerly 'faint orange (textfield shades)'
+$rajah: #f5c26d; // formerly 'light orange (button shades)'
+$buttercup: #f5a623; // formerly 'dark orange (text)'
+$tundora: #4a4a4a; // formerly 'borders/font/any gray'
+$gallery: #efefef;
+$alabaster: #f7f7f7;
+$shark: #22232c;
+$wild-sand: #f6f6f6;
+$white: #fff;
+$dusty-gray: #9b9b9b;
+$alto: #dedede;
+$alabaster: #fafafa;
+$silver-chalice: #aeaeae;
+$curious-blue: #2f9ae0;
+$concrete: #f3f3f3;
+$tundora: #4d4d4d;
+$nile-blue: #1b344d;
+$scorpion: #5d5d5d;
+$silver: #cdcdcd;
+$caribbean-green: #02c9b1;
+$monzo: #d0021b;
+$crimson: #e91550;
+$blue-lagoon: #038789;
+$purple: #690496;
+$tulip-tree: #ebb33f;
+$malibu-blue: #7ac9fd;
+$athens-grey: #e9edf0;
+$jaffa: #f28930;
+$geyser: #d2d8dd;
+
+/*
+ Z-Indicies
+ */
+$dropdown-z-index: 30;
+$token-icon-z-index: 15;
+$container-z-index: 15;
+$header-z-index: 12;
+$mobile-header-z-index: 26;
+$main-container-z-index: 18;
+$send-card-z-index: 20;
+$sidebar-z-index: 26;
+$sidebar-overlay-z-index: 25;
+
+/*
+ Z Indicies - Current
+ app - 11
+ hex/bn as decimal input - 1 - remove?
+ dropdown - 11
+ loading - 10 - higher?
+ mascot - 0 - remove?
+ */
+
+/*
+ Responsive Breakpoints
+ */
+$break-small: 575px;
+$break-midpoint: 780px;
+$break-large: 576px;
+
+
+$primary-font-type: Roboto;
+
diff --git a/ui/app/css/itcss/tools/index.scss b/ui/app/css/itcss/tools/index.scss
new file mode 100644
index 000000000..2236729e8
--- /dev/null
+++ b/ui/app/css/itcss/tools/index.scss
@@ -0,0 +1 @@
+@import './utilities.scss';
diff --git a/ui/app/css/lib.css b/ui/app/css/itcss/tools/utilities.scss
similarity index 72%
rename from ui/app/css/lib.css
rename to ui/app/css/itcss/tools/utilities.scss
index f3acbee76..ca9fd0d9c 100644
--- a/ui/app/css/lib.css
+++ b/ui/app/css/itcss/tools/utilities.scss
@@ -1,19 +1,34 @@
+/*
+ Utility Classes
+ */
+
/* color */
.color-orange {
- color: #F7861C;
+ color: #f7861c; // TODO: move to settings/variables
}
.color-forest {
- color: #0A5448;
+ color: #0a5448; // TODO: move to settings/variables
}
/* lib */
+.full-size {
+ height: 100%;
+ width: 100%;
+}
+
.full-width {
width: 100%;
}
+.full-flex-height {
+ display: flex;
+ flex: 1 1 auto;
+ flex-direction: column;
+}
+
.full-height {
height: 100%;
}
@@ -118,16 +133,19 @@
.pointer {
cursor: pointer;
}
+
.cursor-pointer {
cursor: pointer;
transform-origin: center center;
transition: transform 50ms ease-in-out;
}
+
.cursor-pointer:hover {
transform: scale(1.1);
}
+
.cursor-pointer:active {
- transform: scale(0.95);
+ transform: scale(.95);
}
.cursor-disabled {
@@ -147,7 +165,7 @@
}
.bold {
- font-weight: bold;
+ font-weight: 700;
}
.text-transform-uppercase {
@@ -172,12 +190,12 @@ hr.horizontal-line {
}
.hover-white:hover {
- background: white;
+ background: $white;
}
.red-dot {
- background: #E91550;
- color: white;
+ background: #e91550;
+ color: $white;
border-radius: 10px;
}
@@ -192,14 +210,14 @@ hr.horizontal-line {
}
.golden-square {
- background: #EBB33F;
+ background: #ebb33f;
}
.pending-dot {
- background: red;
+ background: $red;
left: 14px;
top: 14px;
- color: white;
+ color: $white;
border-radius: 10px;
height: 20px;
min-width: 20px;
@@ -213,19 +231,15 @@ hr.horizontal-line {
.keyring-label {
z-index: 1;
- font-size: 11px;
- background: rgba(255,0,0,0.8);
- color: white;
- bottom: 0px;
- left: -8px;
+ font-size: 8px;
+ line-height: 8px;
+ background: rgba(255, 255, 255, 0.4);
+ color: #fff;
border-radius: 10px;
- height: 20px;
- min-width: 20px;
- position: absolute;
- display: flex;
- align-items: center;
- justify-content: center;
padding: 4px;
+ width: 41px;
+ text-align: center;
+ height: 15px;
}
.ether-balance {
@@ -244,16 +258,13 @@ hr.horizontal-line {
margin: 13px;
}
-i.fa.fa-question-circle.fa-lg.menu-icon {
- font-size: 18px;
-}
-
.ether-icon {
background: rgb(0, 163, 68);
border-radius: 20px;
}
+
.testnet-icon {
- background: #2465E1;
+ background: #2465e1;
}
.drop-menu-item {
@@ -274,33 +285,26 @@ i.fa.fa-question-circle.fa-lg.menu-icon {
.critical-error {
text-align: center;
margin-top: 20px;
- color: red;
+ color: $red;
}
/*
- Hacky breakpoint fix for account + tab sections
- Resolves issue from @frankiebee in
- https://github.com/MetaMask/metamask-extension/pull/1835
- Please remove this when integrating new designs
+ Misc
*/
-@media screen and (min-width: 575px) and (max-width: 800px) {
- .account-data-subsection {
- flex: 0 0 auto !important; // reset flex
- margin-left: 10px !important; // create additional horizontal space
- margin-right: 10px !important;
- width: 40%;
- }
-
- .tabSection {
- flex: 0 0 auto !important;
- margin-left: 10px !important;
- margin-right: 10px !important;
- min-width: 285px;
- width: 49%;
- }
-
- .name-label {
- width: 80%;
- }
+// TODO: move into component-level contextual 'active' state
+.letter-spacey {
+ letter-spacing: .1em;
+}
+
+.active {
+ color: #909090;
+}
+
+.check {
+ margin-left: 7px;
+ color: #f7861c;
+ flex: 1 0 auto;
+ display: flex;
+ justify-content: flex-end;
}
diff --git a/ui/app/css/transitions.css b/ui/app/css/itcss/trumps/index.scss
similarity index 59%
rename from ui/app/css/transitions.css
rename to ui/app/css/itcss/trumps/index.scss
index 393a944f9..d9a4202a4 100644
--- a/ui/app/css/transitions.css
+++ b/ui/app/css/itcss/trumps/index.scss
@@ -1,3 +1,9 @@
+/*
+ Trumps
+ */
+
+// Transitions
+
/* universal */
.app-primary .main-enter {
position: absolute;
@@ -8,7 +14,7 @@
.app-primary.from-right .main-enter-active,
.app-primary.from-left .main-enter-active {
overflow-x: hidden;
- transform: translateX(0px);
+ transform: translateX(0);
transition: transform 300ms ease-in;
}
@@ -17,18 +23,27 @@
transform: translateX(360px);
transition: transform 300ms ease-in;
}
+
.app-primary.from-right .main-leave-active {
transform: translateX(-360px);
transition: transform 300ms ease-in;
}
+.sidebar.from-left {
+ transform: translateX(-320px);
+ transition: transform 300ms ease-in;
+}
+
/* loader transitions */
-.loader-enter, .loader-leave-active {
- opacity: 0.0;
+.loader-enter,
+.loader-leave-active {
+ opacity: 0;
transition: opacity 150 ease-in;
}
-.loader-enter-active, .loader-leave {
- opacity: 1.0;
+
+.loader-enter-active,
+.loader-leave {
+ opacity: 1;
transition: opacity 150 ease-in;
}
@@ -36,7 +51,22 @@
.app-primary.from-right .main-enter:not(.main-enter-active) {
transform: translateX(360px);
}
+
.app-primary.from-left .main-enter:not(.main-enter-active) {
transform: translateX(-360px);
}
+i.fa.fa-question-circle.fa-lg.menu-icon {
+ font-size: 18px;
+}
+
+// This text is contained inside a div.
+// ID needed to override user agent stylesheet.
+// See components/modal.scss
+
+/* stylelint-disable */
+#buy-modal-content-footer-text {
+ font-family: 'DIN OT';
+ font-size: 16px;
+}
+/* stylelint-enable */
diff --git a/ui/app/css/reset.css b/ui/app/css/reset.css
deleted file mode 100644
index 9ce89e8bc..000000000
--- a/ui/app/css/reset.css
+++ /dev/null
@@ -1,48 +0,0 @@
-/* http://meyerweb.com/eric/tools/css/reset/
- v2.0 | 20110126
- License: none (public domain)
-*/
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
-body {
- line-height: 1;
-}
-ol, ul {
- list-style: none;
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
\ No newline at end of file
diff --git a/ui/app/main-container.js b/ui/app/main-container.js
new file mode 100644
index 000000000..eaaff8517
--- /dev/null
+++ b/ui/app/main-container.js
@@ -0,0 +1,71 @@
+const Component = require('react').Component
+const h = require('react-hyperscript')
+const inherits = require('util').inherits
+const AccountAndTransactionDetails = require('./account-and-transaction-details')
+const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
+const ConfigScreen = require('./config')
+const UnlockScreen = require('./unlock')
+
+module.exports = MainContainer
+
+inherits(MainContainer, Component)
+function MainContainer () {
+ Component.call(this)
+}
+
+MainContainer.prototype.render = function () {
+ // 3. summarize:
+ // switch statement goes inside MainContainer,
+ // or a method in renderPrimary
+ // - pass resulting h() to MainContainer
+ // - error checking in separate func
+ // - router in separate func
+ let contents = {
+ component: AccountAndTransactionDetails,
+ key: 'account-detail',
+ style: {},
+ }
+
+ if (this.props.isUnlocked === false) {
+ switch (this.props.currentViewName) {
+ case 'restoreVault':
+ log.debug('rendering restore vault screen')
+ contents = {
+ component: HDRestoreVaultScreen,
+ key: 'HDRestoreVaultScreen',
+ }
+ break
+ case 'config':
+ log.debug('rendering config screen from unlock screen.')
+ contents = {
+ component: ConfigScreen,
+ key: 'config',
+ }
+ break
+ default:
+ log.debug('rendering locked screen')
+ contents = {
+ component: UnlockScreen,
+ style: {
+ boxShadow: 'none',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ background: '#F7F7F7',
+ // must force 100%, because lock screen is full-width
+ width: '100%',
+ },
+ key: 'locked',
+ }
+ }
+ }
+
+ return h('div.main-container', {
+ style: contents.style,
+ }, [
+ h(contents.component, {
+ key: contents.key,
+ }, []),
+ ])
+}
+
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 349c25b96..f10bf9fb7 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -14,6 +14,7 @@ function reduceApp (state, action) {
if (selectedAddress) {
name = 'accountDetail'
}
+
if (hasUnconfActions) {
log.debug('pending txs detected, defaulting to conf-tx view.')
name = 'confTx'
@@ -36,6 +37,17 @@ function reduceApp (state, action) {
var appState = extend({
shouldClose: false,
menuOpen: false,
+ modal: {
+ open: false,
+ modalState: {
+ name: null,
+ },
+ previousModalState: {
+ name: null,
+ }
+ },
+ sidebarOpen: false,
+ networkDropdownOpen: false,
currentView: seedWords ? seedConfView : defaultView,
accountDetail: {
subview: 'transactions',
@@ -49,9 +61,50 @@ function reduceApp (state, action) {
}, state.appState)
switch (action.type) {
+ // dropdown methods
+ case actions.NETWORK_DROPDOWN_OPEN:
+ return extend(appState, {
+ networkDropdownOpen: true,
+ })
+
+ case actions.NETWORK_DROPDOWN_CLOSE:
+ return extend(appState, {
+ networkDropdownOpen: false,
+ })
+
+ // sidebar methods
+ case actions.SIDEBAR_OPEN:
+ return extend(appState, {
+ sidebarOpen: true,
+ })
+
+ case actions.SIDEBAR_CLOSE:
+ return extend(appState, {
+ sidebarOpen: false,
+ })
+
+ // modal methods:
+ case actions.MODAL_OPEN:
+ return extend(appState, {
+ modal: Object.assign(
+ state.appState.modal,
+ { open: true },
+ { modalState: action.payload },
+ { previousModalState: appState.modal.modalState},
+ ),
+ })
+
+ case actions.MODAL_CLOSE:
+ return extend(appState, {
+ modal: Object.assign(
+ state.appState.modal,
+ { open: false },
+ { modalState: { name: null } },
+ { previousModalState: appState.modal.modalState},
+ ),
+ })
// transition methods
-
case actions.TRANSITION_FORWARD:
return extend(appState, {
transForward: true,
@@ -133,7 +186,7 @@ function reduceApp (state, action) {
transForward: true,
})
- case actions.CREATE_NEW_VAULT_IN_PROGRESS:
+ case actions.CREATE_NEW_VAULT_IN_PROGRESS:
return extend(appState, {
currentView: {
name: 'createVault',
@@ -172,6 +225,16 @@ function reduceApp (state, action) {
warning: null,
})
+ case actions.SHOW_SEND_TOKEN_PAGE:
+ return extend(appState, {
+ currentView: {
+ name: 'sendToken',
+ context: appState.currentView.context,
+ },
+ transForward: true,
+ warning: null,
+ })
+
case actions.SHOW_NEW_KEYCHAIN:
return extend(appState, {
currentView: {
@@ -307,7 +370,7 @@ function reduceApp (state, action) {
return extend(appState, {
currentView: {
name: 'confTx',
- context: 0,
+ context: action.id ? indexForPending(state, action.id) : indexForLastPending(state),
},
transForward: action.transForward,
warning: null,
@@ -327,36 +390,36 @@ function reduceApp (state, action) {
case actions.COMPLETED_TX:
log.debug('reducing COMPLETED_TX for tx ' + action.value)
- const otherUnconfActions = getUnconfActionList(state)
- .filter(tx => tx.id !== action.value)
- const hasOtherUnconfActions = otherUnconfActions.length > 0
+ // const otherUnconfActions = getUnconfActionList(state)
+ // .filter(tx => tx.id !== action.value)
+ // const hasOtherUnconfActions = otherUnconfActions.length > 0
- if (hasOtherUnconfActions) {
- log.debug('reducer detected txs - rendering confTx view')
- return extend(appState, {
- transForward: false,
- currentView: {
- name: 'confTx',
- context: 0,
- },
- warning: null,
- })
- } else {
- log.debug('attempting to close popup')
- return extend(appState, {
- // indicate notification should close
- shouldClose: true,
- transForward: false,
- warning: null,
- currentView: {
- name: 'accountDetail',
- context: state.metamask.selectedAddress,
- },
- accountDetail: {
- subview: 'transactions',
- },
- })
- }
+ // if (hasOtherUnconfActions) {
+ // log.debug('reducer detected txs - rendering confTx view')
+ // return extend(appState, {
+ // transForward: false,
+ // currentView: {
+ // name: 'confTx',
+ // context: 0,
+ // },
+ // warning: null,
+ // })
+ // } else {
+ log.debug('attempting to close popup')
+ return extend(appState, {
+ // indicate notification should close
+ shouldClose: true,
+ transForward: false,
+ warning: null,
+ currentView: {
+ name: 'accountDetail',
+ context: state.metamask.selectedAddress,
+ },
+ accountDetail: {
+ subview: 'transactions',
+ },
+ })
+ // }
case actions.NEXT_TX:
return extend(appState, {
@@ -586,3 +649,7 @@ function indexForPending (state, txId) {
const index = unconfTxList.indexOf(match)
return index
}
+
+function indexForLastPending (state) {
+ return getUnconfActionList(state).length
+}
diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js
index e0c416c2d..fb2b2e674 100644
--- a/ui/app/reducers/metamask.js
+++ b/ui/app/reducers/metamask.js
@@ -10,6 +10,7 @@ function reduceMetamask (state, action) {
var metamaskState = extend({
isInitialized: false,
isUnlocked: false,
+ isAccountMenuOpen: false,
rpcTarget: 'https://rawtestrpc.metamask.io/',
identities: {},
unapprovedTxs: {},
@@ -17,6 +18,19 @@ function reduceMetamask (state, action) {
lastUnreadNotice: undefined,
frequentRpcList: [],
addressBook: [],
+ selectedTokenAddress: null,
+ tokenExchangeRates: {},
+ tokens: [],
+ send: {
+ gasLimit: null,
+ gasPrice: null,
+ gasTotal: null,
+ from: '',
+ to: '',
+ amount: '0x0',
+ memo: '',
+ errors: {},
+ },
}, state.metamask)
switch (action.type) {
@@ -115,6 +129,11 @@ function reduceMetamask (state, action) {
delete newState.seedWords
return newState
+ case actions.SET_SELECTED_TOKEN:
+ return extend(metamaskState, {
+ selectedTokenAddress: action.value,
+ })
+
case actions.SAVE_ACCOUNT_LABEL:
const account = action.value.account
const name = action.value.label
@@ -130,6 +149,97 @@ function reduceMetamask (state, action) {
conversionDate: action.value.conversionDate,
})
+ case actions.UPDATE_TOKEN_EXCHANGE_RATE:
+ const { payload: { pair, marketinfo } } = action
+ return extend(metamaskState, {
+ tokenExchangeRates: {
+ ...metamaskState.tokenExchangeRates,
+ [pair]: marketinfo,
+ },
+ })
+
+ case actions.UPDATE_TOKENS:
+ return extend(metamaskState, {
+ tokens: action.newTokens,
+ })
+
+ // metamask.send
+ case actions.UPDATE_GAS_LIMIT:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ gasLimit: action.value,
+ },
+ })
+
+ case actions.UPDATE_GAS_PRICE:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ gasPrice: action.value,
+ },
+ })
+
+ case actions.TOGGLE_ACCOUNT_MENU:
+ return extend(metamaskState, {
+ isAccountMenuOpen: !metamaskState.isAccountMenuOpen,
+ })
+
+ case actions.UPDATE_GAS_TOTAL:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ gasTotal: action.value,
+ },
+ })
+
+ case actions.UPDATE_SEND_FROM:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ from: action.value,
+ },
+ })
+
+ case actions.UPDATE_SEND_TO:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ to: action.value,
+ },
+ })
+
+ case actions.UPDATE_SEND_AMOUNT:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ amount: action.value,
+ },
+ })
+
+ case actions.UPDATE_SEND_MEMO:
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ memo: action.value,
+ },
+ })
+
+ case actions.UPDATE_SEND_ERRORS:
+ console.log(123, {
+ ...metamaskState.send.errors,
+ ...action.value,
+ })
+ return extend(metamaskState, {
+ send: {
+ ...metamaskState.send,
+ errors: {
+ ...metamaskState.send.errors,
+ ...action.value,
+ }
+ },
+ })
+
default:
return metamaskState
diff --git a/ui/app/selectors.js b/ui/app/selectors.js
new file mode 100644
index 000000000..9d4e6eb67
--- /dev/null
+++ b/ui/app/selectors.js
@@ -0,0 +1,114 @@
+const valuesFor = require('./util').valuesFor
+
+const selectors = {
+ getSelectedAddress,
+ getSelectedIdentity,
+ getSelectedAccount,
+ getSelectedToken,
+ getSelectedTokenExchangeRate,
+ conversionRateSelector,
+ transactionsSelector,
+ accountsWithSendEtherInfoSelector,
+ getCurrentAccountWithSendEtherInfo,
+ getGasPrice,
+ getGasLimit,
+ getAddressBook,
+ getSendFrom,
+}
+
+module.exports = selectors
+
+function getSelectedAddress (state) {
+ const selectedAddress = state.metamask.selectedAddress || Object.keys(state.metamask.accounts)[0]
+
+ return selectedAddress
+}
+
+function getSelectedIdentity (state) {
+ const selectedAddress = getSelectedAddress(state)
+ const identities = state.metamask.identities
+
+ return identities[selectedAddress]
+}
+
+function getSelectedAccount (state) {
+ const accounts = state.metamask.accounts
+ const selectedAddress = getSelectedAddress(state)
+
+ return accounts[selectedAddress]
+}
+
+function getSelectedToken (state) {
+ const tokens = state.metamask.tokens || []
+ const selectedTokenAddress = state.metamask.selectedTokenAddress
+ const selectedToken = tokens.filter(({ address }) => address === selectedTokenAddress)[0]
+
+ return selectedToken || null
+}
+
+function getSelectedTokenExchangeRate (state) {
+ const tokenExchangeRates = state.metamask.tokenExchangeRates
+ const selectedToken = getSelectedToken(state) || {}
+ const { symbol = '' } = selectedToken
+
+ const pair = `${symbol.toLowerCase()}_eth`
+ const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {}
+
+ return tokenExchangeRate
+}
+
+function conversionRateSelector (state) {
+ return state.metamask.conversionRate
+}
+
+function getAddressBook (state) {
+ return state.metamask.addressBook
+}
+
+function accountsWithSendEtherInfoSelector (state) {
+ const {
+ accounts,
+ identities,
+ } = state.metamask
+
+ const accountsWithSendEtherInfo = Object.entries(accounts).map(([key, account]) => {
+ return Object.assign({}, account, identities[key])
+ })
+
+ return accountsWithSendEtherInfo
+}
+
+function getCurrentAccountWithSendEtherInfo (state) {
+ const currentAddress = getSelectedAddress(state)
+ const accounts = accountsWithSendEtherInfoSelector(state)
+
+ return accounts.find(({ address }) => address === currentAddress)
+}
+
+function transactionsSelector (state) {
+ const { network, selectedTokenAddress } = state.metamask
+ const unapprovedMsgs = valuesFor(state.metamask.unapprovedMsgs)
+ const shapeShiftTxList = (network === '1') ? state.metamask.shapeShiftTxList : undefined
+ const transactions = state.metamask.selectedAddressTxList || []
+ const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList)
+
+ console.log({txsToRender, selectedTokenAddress})
+ return selectedTokenAddress
+ ? txsToRender
+ .filter(({ txParams: { to } }) => to === selectedTokenAddress)
+ .sort((a, b) => b.time - a.time)
+ : txsToRender
+ .sort((a, b) => b.time - a.time)
+}
+
+function getGasPrice (state) {
+ return state.metamask.send.gasPrice
+}
+
+function getGasLimit (state) {
+ return state.metamask.send.gasLimit
+}
+
+function getSendFrom (state) {
+ return state.metamask.send.from
+}
diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js
new file mode 100644
index 000000000..8d368044a
--- /dev/null
+++ b/ui/app/send-v2.js
@@ -0,0 +1,419 @@
+const { inherits } = require('util')
+const PersistentForm = require('../lib/persistent-form')
+const h = require('react-hyperscript')
+const connect = require('react-redux').connect
+
+const Identicon = require('./components/identicon')
+const FromDropdown = require('./components/send/from-dropdown')
+const ToAutoComplete = require('./components/send/to-autocomplete')
+const CurrencyDisplay = require('./components/send/currency-display')
+const MemoTextArea = require('./components/send/memo-textarea')
+const GasFeeDisplay = require('./components/send/gas-fee-display-v2')
+
+const { showModal } = require('./actions')
+
+const { multiplyCurrencies, conversionGreaterThan } = require('./conversion-util')
+const { isValidAddress } = require('./util')
+
+module.exports = SendTransactionScreen
+
+inherits(SendTransactionScreen, PersistentForm)
+function SendTransactionScreen () {
+ PersistentForm.call(this)
+
+ this.state = {
+ dropdownOpen: false,
+ errors: {
+ to: null,
+ amount: null,
+ },
+ }
+
+ this.handleToChange = this.handleToChange.bind(this)
+ this.handleAmountChange = this.handleAmountChange.bind(this)
+ this.validateAmount = this.validateAmount.bind(this)
+}
+
+SendTransactionScreen.prototype.componentWillMount = function () {
+ const {
+ updateTokenExchangeRate,
+ selectedToken = {},
+ getGasPrice,
+ estimateGas,
+ selectedAddress,
+ data,
+ updateGasTotal,
+ } = this.props
+ const { symbol } = selectedToken || {}
+
+ const estimateGasParams = {
+ from: selectedAddress,
+ gas: '746a528800',
+ }
+
+ if (symbol) {
+ updateTokenExchangeRate(symbol)
+ Object.assign(estimateGasParams, { value: '0x0' })
+ }
+
+ if (data) {
+ Object.assign(estimateGasParams, { data })
+ }
+
+ Promise
+ .all([
+ getGasPrice(),
+ estimateGas({
+ from: selectedAddress,
+ gas: '746a528800',
+ }),
+ ])
+ .then(([gasPrice, gas]) => {
+
+ const newGasTotal = multiplyCurrencies(gas, gasPrice, {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ })
+ updateGasTotal(newGasTotal)
+ })
+}
+
+SendTransactionScreen.prototype.renderHeaderIcon = function () {
+ const { selectedToken } = this.props
+
+ return h('div.send-v2__send-header-icon-container', [
+ selectedToken
+ ? h(Identicon, {
+ diameter: 40,
+ address: selectedToken.address,
+ })
+ : h('img.send-v2__send-header-icon', { src: '../images/eth_logo.svg' })
+ ])
+}
+
+SendTransactionScreen.prototype.renderTitle = function () {
+ const { selectedToken } = this.props
+
+ return h('div.send-v2__title', [selectedToken ? 'Send Tokens' : 'Send Funds'])
+}
+
+SendTransactionScreen.prototype.renderCopy = function () {
+ const { selectedToken } = this.props
+
+ const tokenText = selectedToken ? 'tokens' : 'ETH'
+
+ return h('div', [
+
+ h('div.send-v2__copy', `Only send ${tokenText} to an Ethereum address.`),
+
+ h('div.send-v2__copy', 'Sending to a different crytpocurrency that is not Ethereum may result in permanent loss.'),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderHeader = function () {
+ return h('div', [
+ h('div.send-v2__header', {}, [
+
+ this.renderHeaderIcon(),
+
+ h('div.send-v2__arrow-background', [
+ h('i.fa.fa-lg.fa-arrow-circle-right.send-v2__send-arrow-icon'),
+ ]),
+
+ h('div.send-v2__header-tip'),
+
+ ]),
+
+ this.renderTitle(),
+
+ this.renderCopy(),
+ ])
+}
+
+SendTransactionScreen.prototype.renderErrorMessage = function(errorType) {
+ const { errors } = this.props
+ console.log(`! errors`, errors);
+ const errorMessage = errors[errorType];
+ console.log(`errorMessage`, errorMessage);
+ return errorMessage
+ ? h('div.send-v2__error', [ errorMessage ] )
+ : null
+}
+
+SendTransactionScreen.prototype.renderFromRow = function () {
+ const {
+ from,
+ fromAccounts,
+ conversionRate,
+ setSelectedAddress,
+ updateSendFrom,
+ } = this.props
+
+ const { dropdownOpen } = this.state
+
+ return h('div.send-v2__form-row', [
+
+ h('div.send-v2__form-label', 'From:'),
+
+ h(FromDropdown, {
+ dropdownOpen,
+ accounts: fromAccounts,
+ selectedAccount: from,
+ onSelect: updateSendFrom,
+ openDropdown: () => this.setState({ dropdownOpen: true }),
+ closeDropdown: () => this.setState({ dropdownOpen: false }),
+ conversionRate,
+ }),
+
+ ])
+}
+
+SendTransactionScreen.prototype.handleToChange = function (event) {
+ const { updateSendTo, updateSendErrors } = this.props
+ const to = event.target.value
+ let toError = null
+
+ if (!to) {
+ toError = 'Required'
+ } else if (!isValidAddress(to)) {
+ toError = 'Recipient address is invalid.'
+ }
+
+ updateSendTo(to)
+ updateSendErrors({ to: toError })
+}
+
+SendTransactionScreen.prototype.renderToRow = function () {
+ const { toAccounts, errors } = this.props
+ const { to } = this.state
+
+ return h('div.send-v2__form-row', [
+
+ h('div.send-v2__form-label', [
+
+ 'To:',
+
+ this.renderErrorMessage('to'),
+
+ ]),
+
+ h(ToAutoComplete, {
+ to,
+ accounts: toAccounts,
+ onChange: this.handleToChange,
+ inError: Boolean(errors.to),
+ }),
+
+ ])
+}
+
+SendTransactionScreen.prototype.handleAmountChange = function (value) {
+ const amount = value
+ const { updateSendAmount } = this.props
+
+ updateSendAmount(amount)
+}
+
+SendTransactionScreen.prototype.validateAmount = function (value) {
+ const {
+ from: { balance },
+ updateSendErrors,
+ amountConversionRate,
+ conversionRate,
+ primaryCurrency,
+ toCurrency,
+ selectedToken
+ } = this.props
+ const amount = value
+
+ let amountError = null
+
+ const sufficientBalance = conversionGreaterThan(
+ {
+ value: balance,
+ fromNumericBase: 'hex',
+ fromCurrency: primaryCurrency,
+ conversionRate,
+ },
+ {
+ value: amount,
+ fromNumericBase: 'hex',
+ conversionRate: amountConversionRate,
+ fromCurrency: selectedToken || primaryCurrency,
+ conversionRate: amountConversionRate,
+ },
+ )
+ console.log(`sufficientBalance`, sufficientBalance);
+ const amountLessThanZero = conversionGreaterThan(
+ { value: 0, fromNumericBase: 'dec' },
+ { value: amount, fromNumericBase: 'hex' },
+ )
+
+ if (!sufficientBalance) {
+ amountError = 'Insufficient funds.'
+ } else if (amountLessThanZero) {
+ amountError = 'Can not send negative amounts of ETH.'
+ }
+
+ updateSendErrors({ amount: amountError })
+}
+
+SendTransactionScreen.prototype.renderAmountRow = function () {
+ const {
+ selectedToken,
+ primaryCurrency = 'ETH',
+ amountConversionRate,
+ errors,
+ } = this.props
+
+ const { amount } = this.state
+
+ return h('div.send-v2__form-row', [
+
+ h('div.send-v2__form-label', [
+ 'Amount:',
+ this.renderErrorMessage('amount'),
+ ]),
+
+ h(CurrencyDisplay, {
+ inError: Boolean(errors.amount),
+ primaryCurrency,
+ convertedCurrency: 'USD',
+ value: amount,
+ conversionRate: amountConversionRate,
+ convertedPrefix: '$',
+ handleChange: this.handleAmountChange,
+ validate: this.validateAmount,
+ }),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderGasRow = function () {
+ const {
+ conversionRate,
+ showCustomizeGasModal,
+ gasTotal,
+ } = this.props
+
+ return h('div.send-v2__form-row', [
+
+ h('div.send-v2__form-label', 'Gas fee:'),
+
+ h(GasFeeDisplay, {
+ gasTotal,
+ conversionRate,
+ onClick: showCustomizeGasModal,
+ }),
+
+ h('div.send-v2__sliders-icon-container', {
+ onClick: showCustomizeGasModal,
+ }, [
+ h('i.fa.fa-sliders.send-v2__sliders-icon'),
+ ])
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderMemoRow = function () {
+ const { updateSendMemo } = this.props
+ const { memo } = this.state
+
+ return h('div.send-v2__form-row', [
+
+ h('div.send-v2__form-label', 'Transaction Memo:'),
+
+ h(MemoTextArea, {
+ memo,
+ onChange: (event) => updateSendMemo(event.target.value),
+ }),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderForm = function () {
+ return h('div.send-v2__form', {}, [
+
+ this.renderFromRow(),
+
+ this.renderToRow(),
+
+ this.renderAmountRow(),
+
+ this.renderGasRow(),
+
+ this.renderMemoRow(),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderFooter = function () {
+ const { goHome } = this.props
+
+ return h('div.send-v2__footer', [
+ h('button.send-v2__cancel-btn', {
+ onClick: goHome,
+ }, 'Cancel'),
+ h('button.send-v2__next-btn', {
+ onClick: event => this.onSubmit(event),
+ }, 'Next'),
+ ])
+}
+
+SendTransactionScreen.prototype.render = function () {
+ return (
+
+ h('div.send-v2__container', [
+
+ this.renderHeader(),
+
+ this.renderForm(),
+
+ this.renderFooter(),
+ ])
+
+ )
+}
+
+SendTransactionScreen.prototype.addToAddressBookIfNew = function (newAddress) {
+ const { toAccounts, addToAddressBook } = this.props
+ if (!toAccounts.find(({ address }) => newAddress === address)) {
+ // TODO: nickname, i.e. addToAddressBook(recipient, nickname)
+ addToAddressBook(newAddress)
+ }
+}
+
+SendTransactionScreen.prototype.onSubmit = function (event) {
+ event.preventDefault()
+ const {
+ from: {address: from},
+ to,
+ amount,
+ gasLimit: gas,
+ gasPrice,
+ signTokenTx,
+ signTx,
+ selectedToken,
+ toAccounts,
+ } = this.props
+
+ this.addToAddressBookIfNew(to)
+
+ const txParams = {
+ from,
+ value: '0',
+ gas,
+ gasPrice,
+ }
+
+ if (!selectedToken) {
+ txParams.value = amount
+ txParams.to = to
+ }
+
+ selectedToken
+ ? signTokenTx(selectedToken.address, to, amount, txParams)
+ : signTx(txParams)
+}
diff --git a/ui/app/send.js b/ui/app/send.js
index e59c1130e..5643d927b 100644
--- a/ui/app/send.js
+++ b/ui/app/send.js
@@ -1,42 +1,325 @@
-const inherits = require('util').inherits
+const { inherits } = require('util')
const PersistentForm = require('../lib/persistent-form')
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const Identicon = require('./components/identicon')
-const actions = require('./actions')
-const util = require('./util')
-const numericBalance = require('./util').numericBalance
-const addressSummary = require('./util').addressSummary
-const isHex = require('./util').isHex
-const EthBalance = require('./components/eth-balance')
const EnsInput = require('./components/ens-input')
-const ethUtil = require('ethereumjs-util')
+const GasTooltip = require('./components/send/gas-tooltip')
+const CurrencyToggle = require('./components/send/currency-toggle')
+const GasFeeDisplay = require('./components/send/gas-fee-display')
+const { getSelectedIdentity } = require('./selectors')
+
+const {
+ showAccountsPage,
+ backToAccountDetail,
+ displayWarning,
+ hideWarning,
+ addToAddressBook,
+ signTx,
+ estimateGas,
+ getGasPrice,
+} = require('./actions')
+const { stripHexPrefix, addHexPrefix } = require('ethereumjs-util')
+const { isHex, numericBalance, isValidAddress, allNull } = require('./util')
+const { conversionUtil, conversionGreaterThan } = require('./conversion-util')
+
module.exports = connect(mapStateToProps)(SendTransactionScreen)
function mapStateToProps (state) {
- var result = {
- address: state.metamask.selectedAddress,
- accounts: state.metamask.accounts,
- identities: state.metamask.identities,
- warning: state.appState.warning,
- network: state.metamask.network,
- addressBook: state.metamask.addressBook,
- conversionRate: state.metamask.conversionRate,
- currentCurrency: state.metamask.currentCurrency,
+ const {
+ selectedAddress: address,
+ accounts,
+ identities,
+ network,
+ addressBook,
+ conversionRate,
+ currentBlockGasLimit: blockGasLimit,
+ } = state.metamask
+ const { warning } = state.appState
+ const selectedIdentity = getSelectedIdentity(state)
+ const account = accounts[address]
+
+ return {
+ address,
+ accounts,
+ identities,
+ network,
+ addressBook,
+ conversionRate,
+ blockGasLimit,
+ warning,
+ selectedIdentity,
+ error: warning && warning.split('.')[0],
+ account,
+ identity: identities[address],
+ balance: account ? account.balance : null,
}
-
- result.error = result.warning && result.warning.split('.')[0]
-
- result.account = result.accounts[result.address]
- result.identity = result.identities[result.address]
- result.balance = result.account ? numericBalance(result.account.balance) : null
-
- return result
}
inherits(SendTransactionScreen, PersistentForm)
function SendTransactionScreen () {
PersistentForm.call(this)
+
+ // [WIP] These are the bare minimum of tx props needed to sign a transaction
+ // We will need a few more for contract-related interactions
+ this.state = {
+ newTx: {
+ from: '',
+ to: '',
+ amountToSend: '0x0',
+ gasPrice: null,
+ gas: null,
+ amount: '0x0',
+ txData: null,
+ memo: '',
+ },
+ activeCurrency: 'USD',
+ tooltipIsOpen: false,
+ errors: {},
+ isValid: false,
+ }
+
+ this.back = this.back.bind(this)
+ this.closeTooltip = this.closeTooltip.bind(this)
+ this.onSubmit = this.onSubmit.bind(this)
+ this.setActiveCurrency = this.setActiveCurrency.bind(this)
+ this.toggleTooltip = this.toggleTooltip.bind(this)
+ this.validate = this.validate.bind(this)
+ this.getAmountToSend = this.getAmountToSend.bind(this)
+ this.setErrorsFor = this.setErrorsFor.bind(this)
+ this.clearErrorsFor = this.clearErrorsFor.bind(this)
+
+ this.renderFromInput = this.renderFromInput.bind(this)
+ this.renderToInput = this.renderToInput.bind(this)
+ this.renderAmountInput = this.renderAmountInput.bind(this)
+ this.renderGasInput = this.renderGasInput.bind(this)
+ this.renderMemoInput = this.renderMemoInput.bind(this)
+ this.renderErrorMessage = this.renderErrorMessage.bind(this)
+}
+
+SendTransactionScreen.prototype.componentWillMount = function () {
+ const { newTx } = this.state
+ const { address } = this.props
+
+ Promise.all([
+ this.props.dispatch(getGasPrice()),
+ this.props.dispatch(estimateGas({
+ from: address,
+ gas: '746a528800',
+ })),
+ ])
+ .then(([blockGasPrice, estimatedGas]) => {
+ console.log({ blockGasPrice, estimatedGas})
+ this.setState({
+ newTx: {
+ ...newTx,
+ gasPrice: blockGasPrice,
+ gas: estimatedGas,
+ },
+ })
+ })
+}
+
+SendTransactionScreen.prototype.renderErrorMessage = function(errorType, warning) {
+ const { errors } = this.state
+ const errorMessage = errors[errorType];
+
+ return errorMessage || warning
+ ? h('div.send-screen-input-wrapper__error-message', [ errorMessage || warning ])
+ : null
+}
+
+SendTransactionScreen.prototype.renderFromInput = function (from, identities) {
+ return h('div.send-screen-input-wrapper', [
+
+ h('div', 'From:'),
+
+ h('input.large-input.send-screen-input', {
+ list: 'accounts',
+ placeholder: 'Account',
+ value: from,
+ onChange: (event) => {
+ this.setState({
+ newTx: {
+ ...this.state.newTx,
+ from: event.target.value,
+ },
+ })
+ },
+ onBlur: () => this.setErrorsFor('from'),
+ onFocus: event => {
+ this.clearErrorsFor('from')
+ this.state.newTx.from && event.target.select()
+ },
+ }),
+
+ h('datalist#accounts', [
+ Object.entries(identities).map(([key, { address, name }]) => {
+ return h('option', {
+ value: address,
+ label: name,
+ key: address,
+ })
+ }),
+ ]),
+
+ this.renderErrorMessage('from'),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderToInput = function (to, identities, addressBook) {
+ return h('div.send-screen-input-wrapper', [
+
+ h('div', 'To:'),
+
+ h('input.large-input.send-screen-input', {
+ name: 'address',
+ list: 'addresses',
+ placeholder: 'Address',
+ value: to,
+ onChange: (event) => {
+ this.setState({
+ newTx: {
+ ...this.state.newTx,
+ to: event.target.value,
+ },
+ })
+ },
+ onBlur: () => {
+ this.setErrorsFor('to')
+ },
+ onFocus: event => {
+ this.clearErrorsFor('to')
+ this.state.newTx.to && event.target.select()
+ },
+ }),
+
+ h('datalist#addresses', [
+ // Corresponds to the addresses owned.
+ ...Object.entries(identities).map(([key, { address, name }]) => {
+ return h('option', {
+ value: address,
+ label: name,
+ key: address,
+ })
+ }),
+ // Corresponds to previously sent-to addresses.
+ ...addressBook.map(({ address, name }) => {
+ return h('option', {
+ value: address,
+ label: name,
+ key: address,
+ })
+ }),
+ ]),
+
+ this.renderErrorMessage('to'),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderAmountInput = function (activeCurrency) {
+ return h('div.send-screen-input-wrapper', [
+
+ h('div.send-screen-amount-labels', [
+ h('span', 'Amount'),
+ h(CurrencyToggle, {
+ activeCurrency,
+ onClick: (newCurrency) => this.setActiveCurrency(newCurrency),
+ }), // holding on icon from design
+ ]),
+
+ h('input.large-input.send-screen-input', {
+ placeholder: `0 ${activeCurrency}`,
+ type: 'number',
+ onChange: (event) => {
+ const amountToSend = event.target.value
+ ? this.getAmountToSend(event.target.value)
+ : '0x0'
+
+ this.setState({
+ newTx: Object.assign(
+ this.state.newTx,
+ {
+ amount: event.target.value,
+ amountToSend: amountToSend,
+ }
+ ),
+ })
+ },
+ onBlur: () => {
+ this.setErrorsFor('amount')
+ },
+ onFocus: () => this.clearErrorsFor('amount'),
+ }),
+
+ this.renderErrorMessage('amount'),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderGasInput = function (gasPrice, gas, activeCurrency, conversionRate, blockGasLimit) {
+ return h('div.send-screen-input-wrapper', [
+ this.state.tooltipIsOpen && h(GasTooltip, {
+ className: 'send-tooltip',
+ gasPrice,
+ gasLimit: gas,
+ onClose: this.closeTooltip,
+ onFeeChange: ({gasLimit, gasPrice}) => {
+ this.setState({
+ newTx: {
+ ...this.state.newTx,
+ gas: gasLimit,
+ gasPrice,
+ },
+ })
+ },
+ }),
+
+ h('div.send-screen-gas-labels', [
+ h('span', [
+ h('i.fa.fa-bolt'),
+ 'Gas fee:',
+ ]),
+ h('span', 'What\'s this?'),
+ ]),
+
+ // TODO: handle loading time when switching to USD
+ h('div.large-input.send-screen-gas-input', {}, [
+ h(GasFeeDisplay, {
+ activeCurrency,
+ conversionRate,
+ gas,
+ gasPrice,
+ blockGasLimit,
+ }),
+ h('div.send-screen-gas-input-customize', {
+ onClick: this.toggleTooltip,
+ }, [
+ 'Customize',
+ ]),
+ ]),
+
+ ])
+}
+
+SendTransactionScreen.prototype.renderMemoInput = function () {
+ return h('div.send-screen-input-wrapper', [
+ h('div', 'Transaction memo (optional)'),
+ h('input.large-input.send-screen-input', {
+ onChange: () => {
+ this.setState({
+ newTx: Object.assign(
+ this.state.newTx,
+ {
+ memo: event.target.value,
+ }
+ ),
+ })
+ },
+ }),
+ ])
}
SendTransactionScreen.prototype.render = function () {
@@ -44,250 +327,221 @@ SendTransactionScreen.prototype.render = function () {
const props = this.props
const {
- address,
- account,
- identity,
- network,
+ warning,
identities,
addressBook,
conversionRate,
- currentCurrency,
} = props
+ const {
+ blockGasLimit,
+ newTx,
+ activeCurrency,
+ isValid,
+ } = this.state
+ const { gas, gasPrice } = newTx
+
return (
- h('.send-screen.flex-column.flex-grow', [
+ h('div.send-screen-wrapper', [
+ // Main Send token Card
+ h('div.send-screen-card', [
- //
- // Sender Profile
- //
+ h('img.send-eth-icon', { src: '../images/eth_logo.svg' }),
- h('.account-data-subsection.flex-row.flex-grow', {
- style: {
- margin: '0 20px',
- },
- }, [
+ h('div.send-screen__title', 'Send'),
- // header - identicon + nav
- h('.flex-row.flex-space-between', {
- style: {
- marginTop: '15px',
- },
- }, [
- // back button
- h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', {
- onClick: this.back.bind(this),
- }),
+ h('div.send-screen__subtitle', 'Send Ethereum to anyone with an Ethereum account'),
- // large identicon
- h('.identicon-wrapper.flex-column.flex-center.select-none', [
- h(Identicon, {
- diameter: 62,
- address: address,
- }),
- ]),
+ this.renderFromInput(this.state.newTx.from, identities),
- // invisible place holder
- h('i.fa.fa-users.fa-lg.invisible', {
- style: {
- marginTop: '28px',
- },
- }),
+ this.renderToInput(this.state.newTx.to, identities, addressBook),
- ]),
+ this.renderAmountInput(activeCurrency),
- // account label
+ this.renderGasInput(
+ gasPrice || '0x0',
+ gas || '0x0',
+ activeCurrency,
+ conversionRate,
+ blockGasLimit
+ ),
- h('.flex-column', {
- style: {
- marginTop: '10px',
- alignItems: 'flex-start',
- },
- }, [
- h('h2.font-medium.color-forest.flex-center', {
- style: {
- paddingTop: '8px',
- marginBottom: '8px',
- },
- }, identity && identity.name),
+ this.renderMemoInput(),
- // address and getter actions
- h('.flex-row.flex-center', {
- style: {
- marginBottom: '8px',
- },
- }, [
-
- h('div', {
- style: {
- lineHeight: '16px',
- },
- }, addressSummary(address)),
-
- ]),
-
- // balance
- h('.flex-row.flex-center', [
-
- h(EthBalance, {
- value: account && account.balance,
- conversionRate,
- currentCurrency,
- }),
-
- ]),
- ]),
- ]),
-
- //
- // Required Fields
- //
-
- h('h3.flex-center.text-transform-uppercase', {
- style: {
- background: '#EBEBEB',
- color: '#AEAEAE',
- marginTop: '15px',
- marginBottom: '16px',
- },
- }, [
- 'Send Transaction',
- ]),
-
- // error message
- props.error && h('span.error.flex-center', props.error),
-
- // 'to' field
- h('section.flex-row.flex-center', [
- h(EnsInput, {
- name: 'address',
- placeholder: 'Recipient Address',
- onChange: this.recipientDidChange.bind(this),
- network,
- identities,
- addressBook,
- }),
- ]),
-
- // 'amount' and send button
- h('section.flex-row.flex-center', [
-
- h('input.large-input', {
- name: 'amount',
- placeholder: 'Amount',
- type: 'number',
- style: {
- marginRight: '6px',
- },
- dataset: {
- persistentFormId: 'tx-amount',
- },
- }),
-
- h('button.primary', {
- onClick: this.onSubmit.bind(this),
- style: {
- textTransform: 'uppercase',
- },
- }, 'Next'),
+ this.renderErrorMessage(null, warning),
]),
- //
- // Optional Fields
- //
- h('h3.flex-center.text-transform-uppercase', {
- style: {
- background: '#EBEBEB',
- color: '#AEAEAE',
- marginTop: '16px',
- marginBottom: '16px',
- },
- }, [
- 'Transaction Data (optional)',
- ]),
-
- // 'data' field
+ // Buttons underneath card
h('section.flex-column.flex-center', [
- h('input.large-input', {
- name: 'txData',
- placeholder: '0x01234',
- style: {
- width: '100%',
- resize: 'none',
- },
- dataset: {
- persistentFormId: 'tx-data',
- },
- }),
+ h('button.btn-secondary.send-screen__send-button', {
+ className: !isValid && 'send-screen__send-button__disabled',
+ onClick: (event) => isValid && this.onSubmit(event),
+ }, 'Next'),
+ h('button.btn-tertiary.send-screen__cancel-button', {
+ onClick: this.back,
+ }, 'Cancel'),
]),
])
+
)
}
-SendTransactionScreen.prototype.navigateToAccounts = function (event) {
- event.stopPropagation()
- this.props.dispatch(actions.showAccountsPage())
+SendTransactionScreen.prototype.toggleTooltip = function () {
+ this.setState({ tooltipIsOpen: !this.state.tooltipIsOpen })
+}
+
+SendTransactionScreen.prototype.closeTooltip = function () {
+ this.setState({ tooltipIsOpen: false })
+}
+
+SendTransactionScreen.prototype.setActiveCurrency = function (newCurrency) {
+ this.setState({ activeCurrency: newCurrency })
}
SendTransactionScreen.prototype.back = function () {
var address = this.props.address
- this.props.dispatch(actions.backToAccountDetail(address))
+ this.props.dispatch(backToAccountDetail(address))
}
-SendTransactionScreen.prototype.recipientDidChange = function (recipient, nickname) {
- this.setState({
- recipient: recipient,
- nickname: nickname,
+SendTransactionScreen.prototype.validate = function (balance, amountToSend, { to, from }) {
+ const sufficientBalance = conversionGreaterThan(
+ {
+ value: balance,
+ fromNumericBase: 'hex',
+ },
+ {
+ value: amountToSend,
+ fromNumericBase: 'hex',
+ },
+ )
+
+ const amountLessThanZero = conversionGreaterThan(
+ {
+ value: 0,
+ fromNumericBase: 'dec',
+ },
+ {
+ value: amountToSend,
+ fromNumericBase: 'hex',
+ },
+ )
+
+ const errors = {}
+
+ if (!sufficientBalance) {
+ errors.amount = 'Insufficient funds.'
+ }
+
+ if (amountLessThanZero) {
+ errors.amount = 'Can not send negative amounts of ETH.'
+ }
+
+ if (!from) {
+ errors.from = 'Required'
+ }
+
+ if (from && !isValidAddress(from)) {
+ errors.from = 'Sender address is invalid.'
+ }
+
+ if (!to) {
+ errors.to = 'Required'
+ }
+
+ if (to && !isValidAddress(to)) {
+ errors.to = 'Recipient address is invalid.'
+ }
+
+ // if (txData && !isHex(stripHexPrefix(txData))) {
+ // message = 'Transaction data must be hex string.'
+ // return this.props.dispatch(displayWarning(message))
+ // }
+
+ return {
+ isValid: allNull(errors),
+ errors,
+ }
+}
+
+SendTransactionScreen.prototype.getAmountToSend = function (amount) {
+ const { activeCurrency } = this.state
+ const { conversionRate } = this.props
+
+ return conversionUtil(amount, {
+ fromNumericBase: 'dec',
+ toNumericBase: 'hex',
+ fromCurrency: activeCurrency,
+ toCurrency: 'ETH',
+ toDenomination: 'WEI',
+ conversionRate,
+ invertConversionRate: activeCurrency !== 'ETH',
})
}
-SendTransactionScreen.prototype.onSubmit = function () {
+SendTransactionScreen.prototype.setErrorsFor = function (field) {
+ const { balance } = this.props
+ const { newTx, errors: previousErrors } = this.state
+ const { amountToSend } = newTx
+
+ const {
+ isValid,
+ errors: newErrors
+ } = this.validate(balance, amountToSend, newTx)
+
+ const nextErrors = Object.assign({}, previousErrors, {
+ [field]: newErrors[field] || null
+ })
+
+ if (!isValid) {
+ this.setState({
+ errors: nextErrors,
+ isValid,
+ })
+ }
+}
+
+SendTransactionScreen.prototype.clearErrorsFor = function (field) {
+ const { errors: previousErrors } = this.state
+ const nextErrors = Object.assign({}, previousErrors, {
+ [field]: null
+ })
+
+ this.setState({
+ errors: nextErrors,
+ isValid: allNull(nextErrors),
+ })
+}
+
+SendTransactionScreen.prototype.onSubmit = function (event) {
+ event.preventDefault()
+ const { warning, balance } = this.props
const state = this.state || {}
- const recipient = state.recipient || document.querySelector('input[name="address"]').value.replace(/^[.\s]+|[.\s]+$/g, '')
+
+ const recipient = state.newTx.to
+ const sender = state.newTx.from
const nickname = state.nickname || ' '
- const input = document.querySelector('input[name="amount"]').value
- const value = util.normalizeEthStringToWei(input)
- const txData = document.querySelector('input[name="txData"]').value
- const balance = this.props.balance
- let message
- if (value.gt(balance)) {
- message = 'Insufficient funds.'
- return this.props.dispatch(actions.displayWarning(message))
- }
+ // TODO: convert this to hex when created and include it in send
+ const txData = state.newTx.memo
- if (input < 0) {
- message = 'Can not send negative amounts of ETH.'
- return this.props.dispatch(actions.displayWarning(message))
- }
+ this.props.dispatch(hideWarning())
- if ((util.isInvalidChecksumAddress(recipient))) {
- message = 'Recipient address checksum is invalid.'
- return this.props.dispatch(actions.displayWarning(message))
- }
-
- if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) {
- message = 'Recipient address is invalid.'
- return this.props.dispatch(actions.displayWarning(message))
- }
-
- if (!isHex(ethUtil.stripHexPrefix(txData)) && txData) {
- message = 'Transaction data must be hex string.'
- return this.props.dispatch(actions.displayWarning(message))
- }
-
- this.props.dispatch(actions.hideWarning())
-
- this.props.dispatch(actions.addToAddressBook(recipient, nickname))
+ this.props.dispatch(addToAddressBook(recipient, nickname))
var txParams = {
- from: this.props.address,
- value: '0x' + value.toString(16),
+ from: this.state.newTx.from,
+ to: this.state.newTx.to,
+
+ value: this.state.newTx.amountToSend,
+
+ gas: this.state.newTx.gas,
+ gasPrice: this.state.newTx.gasPrice,
}
- if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)
+ if (recipient) txParams.to = addHexPrefix(recipient)
if (txData) txParams.data = txData
- this.props.dispatch(actions.signTx(txParams))
+ this.props.dispatch(signTx(txParams))
}
diff --git a/ui/app/unlock.js b/ui/app/unlock.js
index 4180791c4..ec97b03bf 100644
--- a/ui/app/unlock.js
+++ b/ui/app/unlock.js
@@ -50,7 +50,7 @@ UnlockScreen.prototype.render = function () {
id: 'password-box',
placeholder: 'enter password',
style: {
-
+ background: 'white',
},
onKeyPress: this.onKeyPress.bind(this),
onInput: this.inputChanged.bind(this),
diff --git a/ui/app/util.js b/ui/app/util.js
index 3f8b4dcc3..82a5f9f29 100644
--- a/ui/app/util.js
+++ b/ui/app/util.js
@@ -1,4 +1,16 @@
+const abi = require('human-standard-token-abi')
const ethUtil = require('ethereumjs-util')
+const hexToBn = require('../../app/scripts/lib/hex-to-bn')
+const vreme = new (require('vreme'))()
+
+const MIN_GAS_PRICE_GWEI_BN = new ethUtil.BN(1)
+const GWEI_FACTOR = new ethUtil.BN(1e9)
+const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR)
+
+// formatData :: ( date: ) -> String
+function formatDate (date) {
+ return vreme.format(new Date(date), 'March 16 2014 14:30')
+}
var valueTable = {
wei: '1000000000000000000',
@@ -36,8 +48,14 @@ module.exports = {
valueTable: valueTable,
bnTable: bnTable,
isHex: isHex,
+ formatDate,
+ bnMultiplyByFraction,
+ getTxFeeBn,
+ shortenBalance,
+ getContractAtAddress,
exportAsFile: exportAsFile,
isInvalidChecksumAddress,
+ allNull,
}
function valuesFor (obj) {
@@ -224,6 +242,24 @@ function isHex (str) {
return Boolean(str.match(/^(0x)?[0-9a-fA-F]+$/))
}
+function bnMultiplyByFraction (targetBN, numerator, denominator) {
+ const numBN = new ethUtil.BN(numerator)
+ const denomBN = new ethUtil.BN(denominator)
+ return targetBN.mul(numBN).div(denomBN)
+}
+
+function getTxFeeBn (gas, gasPrice = MIN_GAS_PRICE_BN.toString(16), blockGasLimit) {
+ const gasBn = hexToBn(gas)
+ const gasPriceBn = hexToBn(gasPrice)
+ const txFeeBn = gasBn.mul(gasPriceBn)
+
+ return txFeeBn.toString(16)
+}
+
+function getContractAtAddress (tokenAddress) {
+ return global.eth.contract(abi).at(tokenAddress)
+}
+
function exportAsFile (filename, data) {
// source: https://stackoverflow.com/a/33542499 by Ludovic Feltz
const blob = new Blob([data], {type: 'text/csv'})
@@ -238,3 +274,7 @@ function exportAsFile (filename, data) {
document.body.removeChild(elem)
}
}
+
+function allNull (obj) {
+ return Object.entries(obj).every(([key, value]) => value === null)
+}
diff --git a/ui/css.js b/ui/css.js
index 043363cd7..d8f954434 100644
--- a/ui/css.js
+++ b/ui/css.js
@@ -4,11 +4,7 @@ const path = require('path')
module.exports = bundleCss
var cssFiles = {
- 'fonts.css': fs.readFileSync(path.join(__dirname, '/app/css/fonts.css'), 'utf8'),
- 'reset.css': fs.readFileSync(path.join(__dirname, '/app/css/reset.css'), 'utf8'),
- 'lib.css': fs.readFileSync(path.join(__dirname, '/app/css/lib.css'), 'utf8'),
- 'index.css': fs.readFileSync(path.join(__dirname, '/app/css/index.css'), 'utf8'),
- 'transitions.css': fs.readFileSync(path.join(__dirname, '/app/css/transitions.css'), 'utf8'),
+ 'index.css': fs.readFileSync(path.join(__dirname, '/app/css/output/index.css'), 'utf8'),
'react-tooltip-component.css': fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'react-tooltip-component', 'dist', 'react-tooltip-component.css'), 'utf8'),
'react-css': fs.readFileSync(path.join(__dirname, '..', 'node_modules', 'react-select', 'dist', 'react-select.css'), 'utf8'),
}
diff --git a/ui/index.js b/ui/index.js
index ae05cbe67..fff677471 100644
--- a/ui/index.js
+++ b/ui/index.js
@@ -38,8 +38,11 @@ function startApp (metamaskState, accountManager, opts) {
// if unconfirmed txs, start on txConf page
const unapprovedTxsAll = txHelper(metamaskState.unapprovedTxs, metamaskState.unapprovedMsgs, metamaskState.unapprovedPersonalMsgs, metamaskState.unapprovedTypedMessages, metamaskState.network)
- if (unapprovedTxsAll.length > 0) {
- store.dispatch(actions.showConfTxPage())
+ const numberOfUnapprivedTx = unapprovedTxsAll.length
+ if (numberOfUnapprivedTx > 0) {
+ store.dispatch(actions.showConfTxPage({
+ id: unapprovedTxsAll[numberOfUnapprivedTx - 1].id,
+ }))
}
accountManager.on('update', function (metamaskState) {
diff --git a/ui/lib/feature-toggle-utils.js b/ui/lib/feature-toggle-utils.js
new file mode 100644
index 000000000..6d4e461ca
--- /dev/null
+++ b/ui/lib/feature-toggle-utils.js
@@ -0,0 +1,11 @@
+function checkFeatureToggle (name) {
+ const queryPairMap = window.location.search.substr(1).split('&')
+ .map(pair => pair.split('='))
+ .reduce((pairs, [key, value]) => ({...pairs, [key]: value }), {})
+ const featureToggles = queryPairMap['ft'] ? queryPairMap['ft'].split(',') : []
+ return Boolean(featureToggles.find(ft => ft === name))
+}
+
+module.exports = {
+ checkFeatureToggle,
+}
diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js
index 27a74de66..31498a3a9 100644
--- a/ui/lib/icon-factory.js
+++ b/ui/lib/icon-factory.js
@@ -53,7 +53,7 @@ function imageElFor (address) {
const path = `images/contract/${fileName}`
const img = document.createElement('img')
img.src = path
- img.style.width = '75%'
+ img.style.width = '100%'
return img
}
diff --git a/ui/lib/is-mobile-view.js b/ui/lib/is-mobile-view.js
new file mode 100644
index 000000000..78fd6cb54
--- /dev/null
+++ b/ui/lib/is-mobile-view.js
@@ -0,0 +1,5 @@
+// Checks if viewport at invoke time fits mobile dimensions
+// isMobileView :: () => Bool
+const isMobileView = () => window.matchMedia('screen and (max-width: 575px)').matches
+
+module.exports = isMobileView
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 000000000..837374e1d
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,10539 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@gulp-sourcemaps/identity-map@1.X":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz#cfa23bc5840f9104ce32a65e74db7e7a974bbee1"
+ dependencies:
+ acorn "^5.0.3"
+ css "^2.2.1"
+ normalize-path "^2.1.1"
+ source-map "^0.5.6"
+ through2 "^2.0.3"
+
+"@gulp-sourcemaps/map-sources@1.X":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda"
+ dependencies:
+ normalize-path "^2.0.1"
+ through2 "^2.0.3"
+
+"@types/node@^6.0.46":
+ version "6.0.88"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.88.tgz#f618f11a944f6a18d92b5c472028728a3e3d4b66"
+
+JSONStream@^0.8.4:
+ version "0.8.4"
+ resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.8.4.tgz#91657dfe6ff857483066132b4618b62e8f4887bd"
+ dependencies:
+ jsonparse "0.0.5"
+ through ">=2.2.7 <3"
+
+JSONStream@^1.0.3:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a"
+ dependencies:
+ jsonparse "^1.2.0"
+ through ">=2.2.7 <3"
+
+abab@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
+
+abbrev@1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
+
+abbrev@1.0.x:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
+
+abi-decoder@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.0.8.tgz#7794d864c4b3fd8bab600bdd445ceb01d333ea43"
+ dependencies:
+ babel-core "^6.23.1"
+ babel-loader "^6.3.2"
+ babel-plugin-add-module-exports "^0.2.1"
+ babel-plugin-transform-es2015-modules-amd "^6.22.0"
+ babel-preset-es2015 "^6.22.0"
+ chai "^3.5.0"
+ mocha "^3.2.0"
+ web3 "^0.18.4"
+ webpack "^2.2.1"
+
+abstract-leveldown@2.6.3, abstract-leveldown@~2.6.0:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8"
+ dependencies:
+ xtend "~4.0.0"
+
+accepts@1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
+ dependencies:
+ mime-types "~2.1.11"
+ negotiator "0.6.1"
+
+accepts@~1.3.3, accepts@~1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
+ dependencies:
+ mime-types "~2.1.16"
+ negotiator "0.6.1"
+
+acorn-dynamic-import@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
+ dependencies:
+ acorn "^4.0.3"
+
+acorn-globals@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf"
+ dependencies:
+ acorn "^4.0.4"
+
+acorn-jsx@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+ dependencies:
+ acorn "^3.0.4"
+
+acorn@4.X, acorn@^4.0.3, acorn@^4.0.4:
+ version "4.0.13"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+
+acorn@^3.0.4:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
+acorn@^5.0.0, acorn@^5.0.3, acorn@^5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7"
+
+aes-js@^0.2.3:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d"
+
+after@0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/after/-/after-0.8.1.tgz#ab5d4fb883f596816d3515f8f791c0af486dd627"
+
+after@0.8.2:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
+
+ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
+
+ajv@^4.7.0, ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
+ajv@^5.2.0:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39"
+ dependencies:
+ co "^4.6.0"
+ fast-deep-equal "^1.0.0"
+ json-schema-traverse "^0.3.0"
+ json-stable-stringify "^1.0.1"
+
+align-text@^0.1.1, align-text@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+ dependencies:
+ kind-of "^3.0.2"
+ longest "^1.0.1"
+ repeat-string "^1.5.2"
+
+amdefine@>=0.0.4:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+
+ansi-escapes@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b"
+
+ansi-regex@^0.2.0, ansi-regex@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9"
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+
+ansi-styles@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de"
+
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+ansi-styles@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
+ dependencies:
+ color-convert "^1.9.0"
+
+ansicolors@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
+
+any-promise@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-0.1.0.tgz#830b680aa7e56f33451d4b049f3bd8044498ee27"
+
+any-promise@^1.0.0, any-promise@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+
+anymatch@^1.3.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
+ dependencies:
+ micromatch "^2.1.5"
+ normalize-path "^2.0.0"
+
+append-transform@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+ dependencies:
+ default-require-extensions "^1.0.0"
+
+aproba@^1.0.3:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1"
+
+archy@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
+
+are-we-there-yet@~1.1.2:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
+ dependencies:
+ delegates "^1.0.0"
+ readable-stream "^2.0.6"
+
+argparse@^1.0.7:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
+ dependencies:
+ sprintf-js "~1.0.2"
+
+argsparser@^0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/argsparser/-/argsparser-0.0.7.tgz#41c85e0c3de757b350f12e6ed0e490b1e82dbe06"
+
+arr-diff@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+ dependencies:
+ arr-flatten "^1.0.1"
+
+arr-filter@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee"
+ dependencies:
+ make-iterator "^1.0.0"
+
+arr-flatten@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+
+arr-map@^2.0.0, arr-map@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4"
+ dependencies:
+ make-iterator "^1.0.0"
+
+array-differ@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031"
+
+array-each@^1.0.0, array-each@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
+
+array-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
+
+array-filter@~0.0.0:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec"
+
+array-find-index@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+
+array-initial@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.0.1.tgz#86122222a29c1ed42347f6334111afa40f8b20ec"
+ dependencies:
+ array-slice "^1.0.0"
+ is-number "^3.0.0"
+
+array-last@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.2.0.tgz#0884a67ec2ac2a08133fc00f66779cfedb010986"
+ dependencies:
+ is-number "^3.0.0"
+
+array-map@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662"
+
+array-reduce@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
+
+array-slice@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
+
+array-slice@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.0.0.tgz#e73034f00dcc1f40876008fd20feae77bd4b7c2f"
+
+array-union@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ dependencies:
+ array-uniq "^1.0.1"
+
+array-uniq@^1.0.1, array-uniq@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+array-unique@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+
+arraybuffer.slice@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca"
+
+arrify@^1.0.0, arrify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asap@~2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+
+asn1.js@^4.0.0:
+ version "4.9.1"
+ resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40"
+ dependencies:
+ bn.js "^4.0.0"
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+
+asn1@~0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert-plus@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
+
+assert@^1.1.1, assert@^1.4.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+ dependencies:
+ util "0.10.3"
+
+assertion-error@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
+
+ast-types@0.9.6:
+ version "0.9.6"
+ resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
+
+astw@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/astw/-/astw-2.2.0.tgz#7bd41784d32493987aeb239b6b4e1c57a873b917"
+ dependencies:
+ acorn "^4.0.3"
+
+async-done@^1.2.0, async-done@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.2.3.tgz#6c7abc7d61ca27fe6f1f2ba3206ea9ae60a43983"
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.2"
+ process-nextick-args "^1.0.7"
+ stream-exhaust "^1.0.1"
+
+async-each@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
+
+async-eventemitter@^0.2.2:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.3.tgz#f79f480dfda6645a97bd6142c017150d63b4e70e"
+ dependencies:
+ async "^2.4.0"
+
+async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c:
+ version "0.2.3"
+ resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c"
+ dependencies:
+ async "^2.4.0"
+
+async-foreach@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
+
+async-reduce@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/async-reduce/-/async-reduce-0.0.1.tgz#b236b5f376d6fae381cded9006aa7f2c73b17f31"
+
+async-settle@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b"
+ dependencies:
+ async-done "^1.2.2"
+
+async@1.x, async@^1.4.0, async@^1.4.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
+ dependencies:
+ lodash "^4.14.0"
+
+async@~0.2.9:
+ version "0.2.10"
+ resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
+
+async@~0.9.0:
+ version "0.9.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
+
+async@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9"
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+atob@~1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773"
+
+autoprefixer@^6.0.0:
+ version "6.7.7"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
+ dependencies:
+ browserslist "^1.7.6"
+ caniuse-db "^1.0.30000634"
+ normalize-range "^0.1.2"
+ num2fraction "^1.2.2"
+ postcss "^5.2.16"
+ postcss-value-parser "^3.2.3"
+
+autoprefixer@^7.0.0, autoprefixer@^7.1.2:
+ version "7.1.4"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.4.tgz#960847dbaa4016bc8e8e52ec891cbf8f1257a748"
+ dependencies:
+ browserslist "^2.4.0"
+ caniuse-lite "^1.0.30000726"
+ normalize-range "^0.1.2"
+ num2fraction "^1.2.2"
+ postcss "^6.0.11"
+ postcss-value-parser "^3.2.3"
+
+await-semaphore@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/await-semaphore/-/await-semaphore-0.1.2.tgz#0ceba1bdb2cfc537496032f167bd8b7dedb97493"
+
+aws-sign2@~0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
+
+aws4@^1.2.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
+
+babel-code-frame@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-7.0.0-beta.0.tgz#418a7b5f3f7dc9a4670e61b1158b4c5661bec98d"
+ dependencies:
+ chalk "^2.0.0"
+ esutils "^2.0.2"
+ js-tokens "^3.0.0"
+
+babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+ dependencies:
+ chalk "^1.1.3"
+ esutils "^2.0.2"
+ js-tokens "^3.0.2"
+
+babel-core@^6.0.14, babel-core@^6.23.1, babel-core@^6.24.1, babel-core@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8"
+ dependencies:
+ babel-code-frame "^6.26.0"
+ babel-generator "^6.26.0"
+ babel-helpers "^6.24.1"
+ babel-messages "^6.23.0"
+ babel-register "^6.26.0"
+ babel-runtime "^6.26.0"
+ babel-template "^6.26.0"
+ babel-traverse "^6.26.0"
+ babel-types "^6.26.0"
+ babylon "^6.18.0"
+ convert-source-map "^1.5.0"
+ debug "^2.6.8"
+ json5 "^0.5.1"
+ lodash "^4.17.4"
+ minimatch "^3.0.4"
+ path-is-absolute "^1.0.1"
+ private "^0.1.7"
+ slash "^1.0.0"
+ source-map "^0.5.6"
+
+babel-eslint@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.0.tgz#ce06f385bdfb5b6d7e603f06222f891abd14c240"
+ dependencies:
+ babel-code-frame "7.0.0-beta.0"
+ babel-traverse "7.0.0-beta.0"
+ babel-types "7.0.0-beta.0"
+ babylon "7.0.0-beta.22"
+
+babel-generator@^6.18.0, babel-generator@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5"
+ dependencies:
+ babel-messages "^6.23.0"
+ babel-runtime "^6.26.0"
+ babel-types "^6.26.0"
+ detect-indent "^4.0.0"
+ jsesc "^1.3.0"
+ lodash "^4.17.4"
+ source-map "^0.5.6"
+ trim-right "^1.0.1"
+
+babel-helper-bindify-decorators@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
+ dependencies:
+ babel-helper-explode-assignable-expression "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-helper-call-delegate@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
+ dependencies:
+ babel-helper-hoist-variables "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helper-define-map@^6.24.1:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f"
+ dependencies:
+ babel-helper-function-name "^6.24.1"
+ babel-runtime "^6.26.0"
+ babel-types "^6.26.0"
+ lodash "^4.17.4"
+
+babel-helper-explode-assignable-expression@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helper-explode-class@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
+ dependencies:
+ babel-helper-bindify-decorators "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helper-function-name@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-7.0.0-beta.0.tgz#d1b6779b647e5c5c31ebeb05e13b998e4d352d56"
+ dependencies:
+ babel-helper-get-function-arity "7.0.0-beta.0"
+ babel-template "7.0.0-beta.0"
+ babel-traverse "7.0.0-beta.0"
+ babel-types "7.0.0-beta.0"
+
+babel-helper-function-name@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
+ dependencies:
+ babel-helper-get-function-arity "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helper-get-function-arity@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-7.0.0-beta.0.tgz#9d1ab7213bb5efe1ef1638a8ea1489969b5a8b6e"
+ dependencies:
+ babel-types "7.0.0-beta.0"
+
+babel-helper-get-function-arity@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-helper-hoist-variables@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-helper-optimise-call-expression@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-helper-regex@^6.24.1:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72"
+ dependencies:
+ babel-runtime "^6.26.0"
+ babel-types "^6.26.0"
+ lodash "^4.17.4"
+
+babel-helper-remap-async-to-generator@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
+ dependencies:
+ babel-helper-function-name "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helper-replace-supers@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
+ dependencies:
+ babel-helper-optimise-call-expression "^6.24.1"
+ babel-messages "^6.23.0"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-helpers@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-loader@^6.3.2:
+ version "6.4.1"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca"
+ dependencies:
+ find-cache-dir "^0.1.1"
+ loader-utils "^0.2.16"
+ mkdirp "^0.5.1"
+ object-assign "^4.0.1"
+
+babel-messages@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-7.0.0-beta.0.tgz#6df01296e49fc8fbd0637394326a167f36da817b"
+
+babel-messages@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-add-module-exports@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
+
+babel-plugin-check-es2015-constants@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-syntax-async-functions@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
+
+babel-plugin-syntax-async-generators@^6.5.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
+
+babel-plugin-syntax-class-constructor-call@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416"
+
+babel-plugin-syntax-class-properties@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
+
+babel-plugin-syntax-decorators@^6.13.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
+
+babel-plugin-syntax-do-expressions@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d"
+
+babel-plugin-syntax-dynamic-import@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
+
+babel-plugin-syntax-exponentiation-operator@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
+
+babel-plugin-syntax-export-extensions@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721"
+
+babel-plugin-syntax-function-bind@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46"
+
+babel-plugin-syntax-object-rest-spread@^6.8.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
+
+babel-plugin-syntax-trailing-function-commas@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
+
+babel-plugin-transform-async-generator-functions@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
+ dependencies:
+ babel-helper-remap-async-to-generator "^6.24.1"
+ babel-plugin-syntax-async-generators "^6.5.0"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
+ dependencies:
+ babel-helper-remap-async-to-generator "^6.24.1"
+ babel-plugin-syntax-async-functions "^6.8.0"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-class-constructor-call@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9"
+ dependencies:
+ babel-plugin-syntax-class-constructor-call "^6.18.0"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-class-properties@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
+ dependencies:
+ babel-helper-function-name "^6.24.1"
+ babel-plugin-syntax-class-properties "^6.8.0"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-decorators@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
+ dependencies:
+ babel-helper-explode-class "^6.24.1"
+ babel-plugin-syntax-decorators "^6.13.0"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-do-expressions@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb"
+ dependencies:
+ babel-plugin-syntax-do-expressions "^6.8.0"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-arrow-functions@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
+ dependencies:
+ babel-runtime "^6.26.0"
+ babel-template "^6.26.0"
+ babel-traverse "^6.26.0"
+ babel-types "^6.26.0"
+ lodash "^4.17.4"
+
+babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
+ dependencies:
+ babel-helper-define-map "^6.24.1"
+ babel-helper-function-name "^6.24.1"
+ babel-helper-optimise-call-expression "^6.24.1"
+ babel-helper-replace-supers "^6.24.1"
+ babel-messages "^6.23.0"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
+ dependencies:
+ babel-helper-function-name "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-literals@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
+ dependencies:
+ babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
+ dependencies:
+ babel-plugin-transform-strict-mode "^6.24.1"
+ babel-runtime "^6.26.0"
+ babel-template "^6.26.0"
+ babel-types "^6.26.0"
+
+babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
+ dependencies:
+ babel-helper-hoist-variables "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
+ dependencies:
+ babel-plugin-transform-es2015-modules-amd "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
+ dependencies:
+ babel-helper-replace-supers "^6.24.1"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
+ dependencies:
+ babel-helper-call-delegate "^6.24.1"
+ babel-helper-get-function-arity "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+ babel-traverse "^6.24.1"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-spread@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
+ dependencies:
+ babel-helper-regex "^6.24.1"
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-template-literals@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
+ dependencies:
+ babel-helper-regex "^6.24.1"
+ babel-runtime "^6.22.0"
+ regexpu-core "^2.0.0"
+
+babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
+ dependencies:
+ babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
+ babel-plugin-syntax-exponentiation-operator "^6.8.0"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-export-extensions@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653"
+ dependencies:
+ babel-plugin-syntax-export-extensions "^6.8.0"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-function-bind@^6.22.0:
+ version "6.22.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97"
+ dependencies:
+ babel-plugin-syntax-function-bind "^6.8.0"
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-object-rest-spread@^6.22.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
+ dependencies:
+ babel-plugin-syntax-object-rest-spread "^6.8.0"
+ babel-runtime "^6.26.0"
+
+babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
+ dependencies:
+ regenerator-transform "^0.10.0"
+
+babel-plugin-transform-runtime@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-transform-strict-mode@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-types "^6.24.1"
+
+babel-polyfill@^6.23.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
+ dependencies:
+ babel-runtime "^6.26.0"
+ core-js "^2.5.0"
+ regenerator-runtime "^0.10.5"
+
+babel-preset-env@^1.3.2:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4"
+ dependencies:
+ babel-plugin-check-es2015-constants "^6.22.0"
+ babel-plugin-syntax-trailing-function-commas "^6.22.0"
+ babel-plugin-transform-async-to-generator "^6.22.0"
+ babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoping "^6.23.0"
+ babel-plugin-transform-es2015-classes "^6.23.0"
+ babel-plugin-transform-es2015-computed-properties "^6.22.0"
+ babel-plugin-transform-es2015-destructuring "^6.23.0"
+ babel-plugin-transform-es2015-duplicate-keys "^6.22.0"
+ babel-plugin-transform-es2015-for-of "^6.23.0"
+ babel-plugin-transform-es2015-function-name "^6.22.0"
+ babel-plugin-transform-es2015-literals "^6.22.0"
+ babel-plugin-transform-es2015-modules-amd "^6.22.0"
+ babel-plugin-transform-es2015-modules-commonjs "^6.23.0"
+ babel-plugin-transform-es2015-modules-systemjs "^6.23.0"
+ babel-plugin-transform-es2015-modules-umd "^6.23.0"
+ babel-plugin-transform-es2015-object-super "^6.22.0"
+ babel-plugin-transform-es2015-parameters "^6.23.0"
+ babel-plugin-transform-es2015-shorthand-properties "^6.22.0"
+ babel-plugin-transform-es2015-spread "^6.22.0"
+ babel-plugin-transform-es2015-sticky-regex "^6.22.0"
+ babel-plugin-transform-es2015-template-literals "^6.22.0"
+ babel-plugin-transform-es2015-typeof-symbol "^6.23.0"
+ babel-plugin-transform-es2015-unicode-regex "^6.22.0"
+ babel-plugin-transform-exponentiation-operator "^6.22.0"
+ babel-plugin-transform-regenerator "^6.22.0"
+ browserslist "^2.1.2"
+ invariant "^2.2.2"
+ semver "^5.3.0"
+
+babel-preset-es2015@^6.22.0, babel-preset-es2015@^6.24.0, babel-preset-es2015@^6.6.0:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
+ dependencies:
+ babel-plugin-check-es2015-constants "^6.22.0"
+ babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoping "^6.24.1"
+ babel-plugin-transform-es2015-classes "^6.24.1"
+ babel-plugin-transform-es2015-computed-properties "^6.24.1"
+ babel-plugin-transform-es2015-destructuring "^6.22.0"
+ babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
+ babel-plugin-transform-es2015-for-of "^6.22.0"
+ babel-plugin-transform-es2015-function-name "^6.24.1"
+ babel-plugin-transform-es2015-literals "^6.22.0"
+ babel-plugin-transform-es2015-modules-amd "^6.24.1"
+ babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
+ babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
+ babel-plugin-transform-es2015-modules-umd "^6.24.1"
+ babel-plugin-transform-es2015-object-super "^6.24.1"
+ babel-plugin-transform-es2015-parameters "^6.24.1"
+ babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
+ babel-plugin-transform-es2015-spread "^6.22.0"
+ babel-plugin-transform-es2015-sticky-regex "^6.24.1"
+ babel-plugin-transform-es2015-template-literals "^6.22.0"
+ babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
+ babel-plugin-transform-es2015-unicode-regex "^6.24.1"
+ babel-plugin-transform-regenerator "^6.24.1"
+
+babel-preset-stage-0@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz#5642d15042f91384d7e5af8bc88b1db95b039e6a"
+ dependencies:
+ babel-plugin-transform-do-expressions "^6.22.0"
+ babel-plugin-transform-function-bind "^6.22.0"
+ babel-preset-stage-1 "^6.24.1"
+
+babel-preset-stage-1@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0"
+ dependencies:
+ babel-plugin-transform-class-constructor-call "^6.24.1"
+ babel-plugin-transform-export-extensions "^6.22.0"
+ babel-preset-stage-2 "^6.24.1"
+
+babel-preset-stage-2@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
+ dependencies:
+ babel-plugin-syntax-dynamic-import "^6.18.0"
+ babel-plugin-transform-class-properties "^6.24.1"
+ babel-plugin-transform-decorators "^6.24.1"
+ babel-preset-stage-3 "^6.24.1"
+
+babel-preset-stage-3@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
+ dependencies:
+ babel-plugin-syntax-trailing-function-commas "^6.22.0"
+ babel-plugin-transform-async-generator-functions "^6.24.1"
+ babel-plugin-transform-async-to-generator "^6.24.1"
+ babel-plugin-transform-exponentiation-operator "^6.24.1"
+ babel-plugin-transform-object-rest-spread "^6.22.0"
+
+babel-register@^6.26.0, babel-register@^6.7.2:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
+ dependencies:
+ babel-core "^6.26.0"
+ babel-runtime "^6.26.0"
+ core-js "^2.5.0"
+ home-or-tmp "^2.0.0"
+ lodash "^4.17.4"
+ mkdirp "^0.5.1"
+ source-map-support "^0.4.15"
+
+babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
+babel-template@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-7.0.0-beta.0.tgz#85083cf9e4395d5e48bf5154d7a8d6991cafecfb"
+ dependencies:
+ babel-traverse "7.0.0-beta.0"
+ babel-types "7.0.0-beta.0"
+ babylon "7.0.0-beta.22"
+ lodash "^4.2.0"
+
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+ dependencies:
+ babel-runtime "^6.26.0"
+ babel-traverse "^6.26.0"
+ babel-types "^6.26.0"
+ babylon "^6.18.0"
+ lodash "^4.17.4"
+
+babel-traverse@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-7.0.0-beta.0.tgz#da14be9b762f62a2f060db464eaafdd8cd072a41"
+ dependencies:
+ babel-code-frame "7.0.0-beta.0"
+ babel-helper-function-name "7.0.0-beta.0"
+ babel-messages "7.0.0-beta.0"
+ babel-types "7.0.0-beta.0"
+ babylon "7.0.0-beta.22"
+ debug "^3.0.1"
+ globals "^10.0.0"
+ invariant "^2.2.0"
+ lodash "^4.2.0"
+
+babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+ dependencies:
+ babel-code-frame "^6.26.0"
+ babel-messages "^6.23.0"
+ babel-runtime "^6.26.0"
+ babel-types "^6.26.0"
+ babylon "^6.18.0"
+ debug "^2.6.8"
+ globals "^9.18.0"
+ invariant "^2.2.2"
+ lodash "^4.17.4"
+
+babel-types@7.0.0-beta.0:
+ version "7.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-7.0.0-beta.0.tgz#eb8b6e556470e6dcc4aef982d79ad229469b5169"
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.2.0"
+ to-fast-properties "^2.0.0"
+
+babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+ dependencies:
+ babel-runtime "^6.26.0"
+ esutils "^2.0.2"
+ lodash "^4.17.4"
+ to-fast-properties "^1.0.3"
+
+babelify@^7.2.0, babelify@^7.3.0:
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5"
+ dependencies:
+ babel-core "^6.0.14"
+ object-assign "^4.0.0"
+
+babylon@7.0.0-beta.22:
+ version "7.0.0-beta.22"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.22.tgz#74f0ad82ed7c7c3cfeab74cf684f815104161b65"
+
+babylon@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+
+bach@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880"
+ dependencies:
+ arr-filter "^1.1.1"
+ arr-flatten "^1.0.1"
+ arr-map "^2.0.0"
+ array-each "^1.0.0"
+ array-initial "^1.0.0"
+ array-last "^1.1.1"
+ async-done "^1.2.2"
+ async-settle "^1.0.0"
+ now-and-later "^2.0.0"
+
+backbone@^1.1.2:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.3.3.tgz#4cc80ea7cb1631ac474889ce40f2f8bc683b2999"
+ dependencies:
+ underscore ">=1.8.3"
+
+backo2@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+
+balanced-match@^0.4.0:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
+base-x@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac"
+
+base62@0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/base62/-/base62-0.1.1.tgz#7b4174c2f94449753b11c2651c083da841a7b084"
+
+base64-arraybuffer@0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
+
+base64-js@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.2.tgz#024f0f72afa25b75f9c0ee73cd4f55ec1bed9784"
+
+base64-js@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
+
+base64id@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/base64id/-/base64id-0.1.0.tgz#02ce0fdeee0cef4f40080e1e73e834f0b1bfce3f"
+
+base64id@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
+ dependencies:
+ tweetnacl "^0.14.3"
+
+beefy@^2.1.5:
+ version "2.1.8"
+ resolved "https://registry.yarnpkg.com/beefy/-/beefy-2.1.8.tgz#7bc11b9a487a9a34679d85e29d3b52f374fd0029"
+ dependencies:
+ ansicolors "~0.3.2"
+ chokidar "^1.0.0"
+ concat-stream "^1.4.3"
+ find-global-packages "0.0.1"
+ ignorepatterns "^1.0.1"
+ leftpad "0.0.0"
+ mime "~1.2.9"
+ minimist "0.0.8"
+ open "0.0.3"
+ portfinder "~0.2.1"
+ pretty-bytes "~0.1.0"
+ readable-stream "^1.0.27-1"
+ resolve "^0.6.1"
+ response-stream "0.0.0"
+ script-injector "~1.0.0"
+ through "~2.2.0"
+ which "~1.0.5"
+ xtend "~2.1.2"
+
+beeper@^1.0.0, beeper@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809"
+
+better-assert@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
+ dependencies:
+ callsite "1.0.0"
+
+big.js@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
+
+bignumber.js@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.0.4.tgz#7c40f5abcd2d6623ab7b99682ee7db81b11889a4"
+
+"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
+ version "2.0.7"
+ resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
+
+"bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git":
+ version "2.0.7"
+ resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934"
+
+binary-extensions@^1.0.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0"
+
+binaryextensions@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-1.0.1.tgz#1e637488b35b58bda5f4774bf96a5212a8c90755"
+
+bindings@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7"
+
+bip39@^2.2.0, bip39@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.4.0.tgz#a0b8adbf163f53495f00f05d9ede7c25369ccf13"
+ dependencies:
+ create-hash "^1.1.0"
+ pbkdf2 "^3.0.9"
+ randombytes "^2.0.1"
+ safe-buffer "^5.0.1"
+ unorm "^1.3.3"
+
+bip66@^1.1.3:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22"
+ dependencies:
+ safe-buffer "^5.0.1"
+
+bl@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-0.7.0.tgz#3fb0670602ac2878eb770dc2039f1836be62ae5b"
+ dependencies:
+ readable-stream "~1.0.2"
+
+bl@^0.9.1:
+ version "0.9.5"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054"
+ dependencies:
+ readable-stream "~1.0.26"
+
+bl@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
+ dependencies:
+ readable-stream "^2.0.5"
+
+blob@0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
+
+block-stream@*:
+ version "0.0.9"
+ resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+ dependencies:
+ inherits "~2.0.0"
+
+bluebird@^3.0.5, bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.4.6, bluebird@^3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
+
+bn.js@4.11.6:
+ version "4.11.6"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
+
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.3, bn.js@^4.11.7, bn.js@^4.4.0, bn.js@^4.8.0:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
+
+body-parser@1.18.2:
+ version "1.18.2"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
+ dependencies:
+ bytes "3.0.0"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "~1.1.1"
+ http-errors "~1.6.2"
+ iconv-lite "0.4.19"
+ on-finished "~2.3.0"
+ qs "6.5.1"
+ raw-body "2.3.2"
+ type-is "~1.6.15"
+
+body-parser@^1.16.1:
+ version "1.18.1"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.1.tgz#9c1629370bcfd42917f30641a2dcbe2ec50d4c26"
+ dependencies:
+ bytes "3.0.0"
+ content-type "~1.0.4"
+ debug "2.6.8"
+ depd "~1.1.1"
+ http-errors "~1.6.2"
+ iconv-lite "0.4.19"
+ on-finished "~2.3.0"
+ qs "6.5.1"
+ raw-body "2.3.2"
+ type-is "~1.6.15"
+
+body-parser@~1.14.0:
+ version "1.14.2"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.14.2.tgz#1015cb1fe2c443858259581db53332f8d0cf50f9"
+ dependencies:
+ bytes "2.2.0"
+ content-type "~1.0.1"
+ debug "~2.2.0"
+ depd "~1.1.0"
+ http-errors "~1.3.1"
+ iconv-lite "0.4.13"
+ on-finished "~2.3.0"
+ qs "5.2.0"
+ raw-body "~2.1.5"
+ type-is "~1.6.10"
+
+boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
+boom@2.x.x:
+ version "2.10.1"
+ resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
+ dependencies:
+ hoek "2.x.x"
+
+bops@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.6.tgz#082d1d55fa01e60dbdc2ebc2dba37f659554cf3a"
+ dependencies:
+ base64-js "0.0.2"
+ to-utf8 "0.0.1"
+
+boron@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/boron/-/boron-0.2.3.tgz#63a1800771c0cb2b0d8f616687c62c1248cfb8a0"
+ dependencies:
+ domkit "^0.0.1"
+
+brace-expansion@^1.1.7:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^0.1.2:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6"
+ dependencies:
+ expand-range "^0.1.0"
+
+braces@^1.8.2:
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+ dependencies:
+ expand-range "^1.8.1"
+ preserve "^0.2.0"
+ repeat-element "^1.1.2"
+
+brfs@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.4.3.tgz#db675d6f5e923e6df087fca5859c9090aaed3216"
+ dependencies:
+ quote-stream "^1.0.1"
+ resolve "^1.1.5"
+ static-module "^1.1.0"
+ through2 "^2.0.0"
+
+brorand@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+
+browser-pack@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.2.tgz#f86cd6cef4f5300c8e63e07a4d512f65fbff4531"
+ dependencies:
+ JSONStream "^1.0.3"
+ combine-source-map "~0.7.1"
+ defined "^1.0.0"
+ through2 "^2.0.0"
+ umd "^3.0.0"
+
+browser-passworder@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/browser-passworder/-/browser-passworder-2.0.3.tgz#6fdd2082e516a176edbcb3dcee0b7f9fce4f7917"
+ dependencies:
+ browserify-unibabel "^3.0.0"
+
+browser-resolve@^1.11.0, browser-resolve@^1.7.0:
+ version "1.11.2"
+ resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce"
+ dependencies:
+ resolve "1.1.7"
+
+browser-stdout@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
+
+browser-unpack@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/browser-unpack/-/browser-unpack-0.2.3.tgz#88fe04cc266257e52650095cd8e0585dc7b6e2f1"
+ dependencies:
+ concat-stream "~1.2.1"
+ esprima-fb "3001.1.0-dev-harmony-fb"
+ minimist "0.0.5"
+
+browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.0.8.tgz#c8fa3b1b7585bb7ba77c5560b60996ddec6d5309"
+ dependencies:
+ buffer-xor "^1.0.3"
+ cipher-base "^1.0.0"
+ create-hash "^1.1.0"
+ evp_bytestokey "^1.0.3"
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+browserify-cipher@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a"
+ dependencies:
+ browserify-aes "^1.0.4"
+ browserify-des "^1.0.0"
+ evp_bytestokey "^1.0.0"
+
+browserify-derequire@^0.9.4:
+ version "0.9.4"
+ resolved "https://registry.yarnpkg.com/browserify-derequire/-/browserify-derequire-0.9.4.tgz#64d61e56cfdff0b8f174fd8c57f8b4033e287895"
+ dependencies:
+ derequire "^2.0.0"
+ through2 "^1.1.1"
+
+browserify-des@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd"
+ dependencies:
+ cipher-base "^1.0.1"
+ des.js "^1.0.0"
+ inherits "^2.0.1"
+
+browserify-rsa@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
+ dependencies:
+ bn.js "^4.1.0"
+ randombytes "^2.0.1"
+
+browserify-sha3@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11"
+ dependencies:
+ js-sha3 "^0.3.1"
+
+browserify-sign@^4.0.0:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298"
+ dependencies:
+ bn.js "^4.1.1"
+ browserify-rsa "^4.0.0"
+ create-hash "^1.1.0"
+ create-hmac "^1.1.2"
+ elliptic "^6.0.0"
+ inherits "^2.0.1"
+ parse-asn1 "^5.0.0"
+
+browserify-unibabel@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/browserify-unibabel/-/browserify-unibabel-3.0.0.tgz#5a6b8f0f704ce388d3927df47337e25830f71dda"
+
+browserify-zlib@^0.1.4, browserify-zlib@~0.1.2:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
+ dependencies:
+ pako "~0.2.0"
+
+browserify@^14.0.0, browserify@^14.4.0:
+ version "14.4.0"
+ resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.4.0.tgz#089a3463af58d0e48d8cd4070b3f74654d5abca9"
+ dependencies:
+ JSONStream "^1.0.3"
+ assert "^1.4.0"
+ browser-pack "^6.0.1"
+ browser-resolve "^1.11.0"
+ browserify-zlib "~0.1.2"
+ buffer "^5.0.2"
+ cached-path-relative "^1.0.0"
+ concat-stream "~1.5.1"
+ console-browserify "^1.1.0"
+ constants-browserify "~1.0.0"
+ crypto-browserify "^3.0.0"
+ defined "^1.0.0"
+ deps-sort "^2.0.0"
+ domain-browser "~1.1.0"
+ duplexer2 "~0.1.2"
+ events "~1.1.0"
+ glob "^7.1.0"
+ has "^1.0.0"
+ htmlescape "^1.1.0"
+ https-browserify "^1.0.0"
+ inherits "~2.0.1"
+ insert-module-globals "^7.0.0"
+ labeled-stream-splicer "^2.0.0"
+ module-deps "^4.0.8"
+ os-browserify "~0.1.1"
+ parents "^1.0.1"
+ path-browserify "~0.0.0"
+ process "~0.11.0"
+ punycode "^1.3.2"
+ querystring-es3 "~0.2.0"
+ read-only-stream "^2.0.0"
+ readable-stream "^2.0.2"
+ resolve "^1.1.4"
+ shasum "^1.0.0"
+ shell-quote "^1.6.1"
+ stream-browserify "^2.0.0"
+ stream-http "^2.0.0"
+ string_decoder "~1.0.0"
+ subarg "^1.0.0"
+ syntax-error "^1.1.1"
+ through2 "^2.0.0"
+ timers-browserify "^1.0.1"
+ tty-browserify "~0.0.0"
+ url "~0.11.0"
+ util "~0.10.1"
+ vm-browserify "~0.0.1"
+ xtend "^4.0.0"
+
+browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.7.6:
+ version "1.7.7"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9"
+ dependencies:
+ caniuse-db "^1.0.30000639"
+ electron-to-chromium "^1.2.7"
+
+browserslist@^2.1.2, browserslist@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.4.0.tgz#693ee93d01e66468a6348da5498e011f578f87f8"
+ dependencies:
+ caniuse-lite "^1.0.30000718"
+ electron-to-chromium "^1.3.18"
+
+bs58@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d"
+
+bs58@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e"
+ dependencies:
+ base-x "^1.1.0"
+
+bs58check@^1.0.8:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8"
+ dependencies:
+ bs58 "^3.1.0"
+ create-hash "^1.1.0"
+
+buffer-crc32@~0.2.3:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+
+buffer-equal@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
+
+buffer-xor@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+
+buffer@^4.3.0:
+ version "4.9.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
+ dependencies:
+ base64-js "^1.0.2"
+ ieee754 "^1.1.4"
+ isarray "^1.0.0"
+
+buffer@^5.0.2:
+ version "5.0.7"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.7.tgz#570a290b625cf2603290c1149223d27ccf04db97"
+ dependencies:
+ base64-js "^1.0.2"
+ ieee754 "^1.1.4"
+
+builtin-modules@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+builtin-status-codes@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+
+builtins@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/builtins/-/builtins-0.0.3.tgz#5d006166da71610bc2bcf73019f0f0cc43309755"
+
+bytes@2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.2.0.tgz#fd35464a403f6f9117c2de3609ecff9cae000588"
+
+bytes@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"
+
+bytes@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+
+cached-path-relative@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7"
+
+caching-transform@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1"
+ dependencies:
+ md5-hex "^1.2.0"
+ mkdirp "^0.5.1"
+ write-file-atomic "^1.1.4"
+
+caller-path@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
+ dependencies:
+ callsites "^0.2.0"
+
+callsite@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
+
+callsites@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
+
+camelcase-keys@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+ dependencies:
+ camelcase "^2.0.0"
+ map-obj "^1.0.0"
+
+camelcase@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+
+camelcase@^2.0.0, camelcase@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+
+camelcase@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+
+camelcase@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+
+caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
+ version "1.0.30000727"
+ resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000727.tgz#4e22593089b0f35c1b2adcfc28234493a21a4b2e"
+
+caniuse-lite@^1.0.30000718, caniuse-lite@^1.0.30000726:
+ version "1.0.30000727"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000727.tgz#20c895768398ded5f98a4beab4a76c285def41d2"
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+
+center-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+ dependencies:
+ align-text "^0.1.3"
+ lazy-cache "^1.0.3"
+
+"chai@>=1.9.2 <4.0.0", chai@^3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
+ dependencies:
+ assertion-error "^1.0.1"
+ deep-eql "^0.1.3"
+ type-detect "^1.0.0"
+
+chai@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c"
+ dependencies:
+ assertion-error "^1.0.1"
+ check-error "^1.0.1"
+ deep-eql "^3.0.0"
+ get-func-name "^2.0.0"
+ pathval "^1.0.0"
+ type-detect "^4.0.0"
+
+chain-function@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc"
+
+chalk@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174"
+ dependencies:
+ ansi-styles "^1.1.0"
+ escape-string-regexp "^1.0.0"
+ has-ansi "^0.1.0"
+ strip-ansi "^0.3.0"
+ supports-color "^0.2.0"
+
+chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ dependencies:
+ 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"
+
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
+ dependencies:
+ ansi-styles "^3.1.0"
+ escape-string-regexp "^1.0.5"
+ supports-color "^4.0.0"
+
+charm@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/charm/-/charm-1.0.2.tgz#8add367153a6d9a581331052c4090991da995e35"
+ dependencies:
+ inherits "^2.0.1"
+
+check-error@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+
+checkpoint-store@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06"
+ dependencies:
+ functional-red-black-tree "^1.0.1"
+
+cheerio@^0.22.0:
+ version "0.22.0"
+ resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e"
+ dependencies:
+ css-select "~1.2.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "^3.9.1"
+ lodash.assignin "^4.0.9"
+ lodash.bind "^4.1.4"
+ lodash.defaults "^4.0.1"
+ lodash.filter "^4.4.0"
+ lodash.flatten "^4.2.0"
+ lodash.foreach "^4.3.0"
+ lodash.map "^4.4.0"
+ lodash.merge "^4.4.0"
+ lodash.pick "^4.2.1"
+ lodash.reduce "^4.4.0"
+ lodash.reject "^4.4.0"
+ lodash.some "^4.4.0"
+
+chokidar@^1.0.0, chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.1, chokidar@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
+ dependencies:
+ anymatch "^1.3.0"
+ async-each "^1.0.0"
+ glob-parent "^2.0.0"
+ inherits "^2.0.1"
+ is-binary-path "^1.0.0"
+ is-glob "^2.0.0"
+ path-is-absolute "^1.0.0"
+ readdirp "^2.0.0"
+ optionalDependencies:
+ fsevents "^1.0.0"
+
+chownr@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
+
+cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+circular-json@^0.3.1:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
+
+classnames@^2.2.4, classnames@^2.2.5:
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
+
+cli-cursor@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ dependencies:
+ restore-cursor "^2.0.0"
+
+cli-table@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23"
+ dependencies:
+ colors "1.0.3"
+
+cli-width@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
+
+client-sw-ready-event@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/client-sw-ready-event/-/client-sw-ready-event-3.3.0.tgz#988d1045562b0c228e33d9247a6dd3ed7b276fe3"
+
+cliui@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+ dependencies:
+ center-align "^0.1.1"
+ right-align "^0.1.1"
+ wordwrap "0.0.2"
+
+cliui@^3.0.3, cliui@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+ wrap-ansi "^2.0.0"
+
+clone-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c"
+ dependencies:
+ is-regexp "^1.0.0"
+ is-supported-regexp-flag "^1.0.0"
+
+clone-stats@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
+
+clone@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f"
+
+clone@^1.0.0, clone@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
+
+clone@^2.0.0, clone@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb"
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+code-point-at@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+coinstring@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4"
+ dependencies:
+ bs58 "^2.0.1"
+ create-hash "^1.1.1"
+
+collection-map@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c"
+ dependencies:
+ arr-map "^2.0.2"
+ for-own "^1.0.0"
+ make-iterator "^1.0.0"
+
+color-convert@^1.3.0, color-convert@^1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
+ dependencies:
+ color-name "^1.1.1"
+
+color-diff@^0.1.3:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/color-diff/-/color-diff-0.1.7.tgz#6db78cd9482a8e459d40821eaf4b503283dcb8e2"
+
+color-name@^1.0.0, color-name@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+
+color-string@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991"
+ dependencies:
+ color-name "^1.0.0"
+
+color@^0.11.1:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
+ dependencies:
+ clone "^1.0.2"
+ color-convert "^1.3.0"
+ color-string "^0.3.0"
+
+colorguard@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/colorguard/-/colorguard-1.2.0.tgz#f3facaf5caaeba4ef54653d9fb25bb73177c0d84"
+ dependencies:
+ chalk "^1.1.1"
+ color-diff "^0.1.3"
+ log-symbols "^1.0.2"
+ object-assign "^4.0.1"
+ pipetteur "^2.0.0"
+ plur "^2.0.0"
+ postcss "^5.0.4"
+ postcss-reporter "^1.2.1"
+ text-table "^0.2.0"
+ yargs "^1.2.6"
+
+colors@1.0.3, colors@1.0.x:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
+
+colors@^1.1.0, colors@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
+
+combine-lists@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6"
+ dependencies:
+ lodash "^4.5.0"
+
+combine-source-map@~0.7.1:
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e"
+ dependencies:
+ convert-source-map "~1.1.0"
+ inline-source-map "~0.6.0"
+ lodash.memoize "~3.0.3"
+ source-map "~0.5.3"
+
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@2.11.0, commander@^2.5.0, commander@^2.6.0, commander@^2.9.0, commander@~2.11.0:
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
+
+commander@2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
+ dependencies:
+ graceful-readlink ">= 1.0.0"
+
+commondir@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-0.0.1.tgz#89f00fdcd51b519c578733fec563e6a6da7f5be2"
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+
+commoner@^0.10.0:
+ version "0.10.8"
+ resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5"
+ dependencies:
+ commander "^2.5.0"
+ detective "^4.3.1"
+ glob "^5.0.15"
+ graceful-fs "^4.1.2"
+ iconv-lite "^0.4.5"
+ mkdirp "^0.5.0"
+ private "^0.1.6"
+ q "^1.1.2"
+ recast "^0.11.17"
+
+commonmark-react-renderer@^4.2.4:
+ version "4.3.3"
+ resolved "https://registry.yarnpkg.com/commonmark-react-renderer/-/commonmark-react-renderer-4.3.3.tgz#9c4bca138bc83287bae792ccf133738be9cbc6fa"
+ dependencies:
+ in-publish "^2.0.0"
+ lodash.assign "^4.2.0"
+ lodash.isplainobject "^4.0.6"
+ pascalcase "^0.1.1"
+ xss-filters "^1.2.6"
+
+commonmark@^0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/commonmark/-/commonmark-0.24.0.tgz#b80de0182c546355643aa15db12bfb282368278f"
+ dependencies:
+ entities "~ 1.1.1"
+ mdurl "~ 1.0.1"
+ string.prototype.repeat "^0.2.0"
+
+component-bind@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
+
+component-emitter@1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3"
+
+component-emitter@1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
+
+component-inherit@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+concat-stream@^1.4.3, concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@~1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+concat-stream@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.2.1.tgz#f35100b6c46378bfba8b6b80f9f0d0ccdf13dc60"
+ dependencies:
+ bops "0.0.6"
+
+concat-stream@~1.5.0, concat-stream@~1.5.1:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266"
+ dependencies:
+ inherits "~2.0.1"
+ readable-stream "~2.0.0"
+ typedarray "~0.0.5"
+
+config-chain@~1.1.5:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2"
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+connect@^3.6.0:
+ version "3.6.3"
+ resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.3.tgz#f7320d46a25b4be7b483a2236517f24b1e27e301"
+ dependencies:
+ debug "2.6.8"
+ finalhandler "1.0.4"
+ parseurl "~1.3.1"
+ utils-merge "1.0.0"
+
+console-browserify@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
+ dependencies:
+ date-now "^0.1.4"
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+
+consolidate@^0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.14.5.tgz#5a25047bc76f73072667c8cb52c989888f494c63"
+ dependencies:
+ bluebird "^3.1.1"
+
+constants-browserify@^1.0.0, constants-browserify@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+
+content-disposition@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+
+content-type-parser@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.1.tgz#c3e56988c53c65127fb46d4032a3a900246fdc94"
+
+content-type@~1.0.1, content-type@~1.0.2, content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+
+convert-source-map@1.X, convert-source-map@^1.1.1, convert-source-map@^1.3.0, convert-source-map@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
+
+convert-source-map@~1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+
+cookie@0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+
+copy-props@^1.4.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-1.6.0.tgz#f0324bbee99771101e7b3ada112f313c393db8ed"
+ dependencies:
+ each-props "^1.2.1"
+ is-plain-object "^2.0.1"
+
+copy-to-clipboard@^3.0.8:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9"
+ dependencies:
+ toggle-selection "^1.0.3"
+
+core-js@^1.0.0:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
+
+core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
+
+core-util-is@1.0.2, core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+cosmiconfig@^2.1.1, cosmiconfig@^2.1.3:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892"
+ dependencies:
+ is-directory "^0.3.1"
+ js-yaml "^3.4.3"
+ minimist "^1.2.0"
+ object-assign "^4.1.0"
+ os-homedir "^1.0.1"
+ parse-json "^2.2.0"
+ require-from-string "^1.1.0"
+
+coveralls@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.0.tgz#22ef730330538080d29b8c151dc9146afde88a99"
+ dependencies:
+ js-yaml "^3.6.1"
+ lcov-parse "^0.0.10"
+ log-driver "^1.2.5"
+ minimist "^1.2.0"
+ request "^2.79.0"
+
+create-ecdh@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
+ dependencies:
+ bn.js "^4.1.0"
+ elliptic "^6.0.0"
+
+create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
+ dependencies:
+ cipher-base "^1.0.1"
+ inherits "^2.0.1"
+ ripemd160 "^2.0.0"
+ sha.js "^2.4.0"
+
+create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06"
+ dependencies:
+ cipher-base "^1.0.3"
+ create-hash "^1.1.0"
+ inherits "^2.0.1"
+ ripemd160 "^2.0.0"
+ safe-buffer "^5.0.1"
+ sha.js "^2.4.8"
+
+create-react-class@^15.5.2, create-react-class@^15.6.0:
+ version "15.6.0"
+ resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.0.tgz#ab448497c26566e1e29413e883207d57cfe7bed4"
+ dependencies:
+ fbjs "^0.8.9"
+ loose-envify "^1.3.1"
+ object-assign "^4.1.1"
+
+cross-spawn@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cross-spawn@^4:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cross-spawn@^5.0.1, cross-spawn@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
+ dependencies:
+ lru-cache "^4.0.1"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+cryptiles@2.x.x:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
+ dependencies:
+ boom "2.x.x"
+
+crypto-browserify@^3.0.0, crypto-browserify@^3.11.0:
+ version "3.11.1"
+ resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f"
+ dependencies:
+ browserify-cipher "^1.0.0"
+ browserify-sign "^4.0.0"
+ create-ecdh "^4.0.0"
+ create-hash "^1.1.0"
+ create-hmac "^1.1.0"
+ diffie-hellman "^5.0.0"
+ inherits "^2.0.1"
+ pbkdf2 "^3.0.3"
+ public-encrypt "^4.0.0"
+ randombytes "^2.0.0"
+
+crypto-js@^3.1.4:
+ version "3.1.8"
+ resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5"
+
+css-color-list@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/css-color-list/-/css-color-list-0.0.1.tgz#8718e8695ae7a2cc8787be8715f1c008a7f28b15"
+ dependencies:
+ css-color-names "0.0.1"
+
+css-color-names@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.1.tgz#5d0548fa256456ede4a9a0c2ac7ab19d3eb1ad81"
+
+css-color-names@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.3.tgz#de0cef16f4d8aa8222a320d5b6d7e9bbada7b9f6"
+
+css-rule-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/css-rule-stream/-/css-rule-stream-1.1.0.tgz#3786e7198983d965a26e31957e09078cbb7705a2"
+ dependencies:
+ css-tokenize "^1.0.1"
+ duplexer2 "0.0.2"
+ ldjson-stream "^1.2.1"
+ through2 "^0.6.3"
+
+css-select@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+css-tokenize@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/css-tokenize/-/css-tokenize-1.0.1.tgz#4625cb1eda21c143858b7f81d6803c1d26fc14be"
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^1.0.33"
+
+css-what@2.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
+
+css@2.X, css@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc"
+ dependencies:
+ inherits "^2.0.1"
+ source-map "^0.1.38"
+ source-map-resolve "^0.3.0"
+ urix "^0.1.0"
+
+cssauron@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/cssauron/-/cssauron-1.4.0.tgz#a6602dff7e04a8306dc0db9a551e92e8b5662ad8"
+ dependencies:
+ through X.X.X
+
+cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b"
+
+"cssstyle@>= 0.2.37 < 0.3.0":
+ version "0.2.37"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54"
+ dependencies:
+ cssom "0.3.x"
+
+currently-unhandled@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+ dependencies:
+ array-find-index "^1.0.1"
+
+custom-event@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
+
+cycle@1.0.x:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
+
+cyclist@~0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
+
+d3@^3.4.3:
+ version "3.5.17"
+ resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8"
+
+d@1:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
+ dependencies:
+ es5-ext "^0.10.9"
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ dependencies:
+ assert-plus "^1.0.0"
+
+date-now@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
+
+dateformat@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.0.0.tgz#2743e3abb5c3fc2462e527dca445e04e9f4dee17"
+
+debounce@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.0.2.tgz#503cc674d8d7f737099664fb75ddbd36b9626dc6"
+
+debug-fabulous@>=0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.1.1.tgz#1b970878c9fa4fbd1c88306eab323c830c58f1d6"
+ dependencies:
+ debug "2.3.0"
+ memoizee "^0.4.5"
+ object-assign "4.1.0"
+
+debug-log@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f"
+
+debug@2.2.0, debug@~2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
+ dependencies:
+ ms "0.7.1"
+
+debug@2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.0.tgz#3912dc55d7167fc3af17d2b85c13f93deaedaa43"
+ dependencies:
+ ms "0.7.2"
+
+debug@2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c"
+ dependencies:
+ ms "0.7.2"
+
+debug@2.6.8, debug@^2.1.0, debug@^2.2.0, debug@^2.6.0, debug@^2.6.3, debug@^2.6.8:
+ version "2.6.8"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
+ dependencies:
+ ms "2.0.0"
+
+debug@2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ dependencies:
+ ms "2.0.0"
+
+debug@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ dependencies:
+ ms "2.0.0"
+
+debug@^3.0.0, debug@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64"
+ dependencies:
+ ms "2.0.0"
+
+decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+deep-diff@^0.3.5:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
+
+deep-eql@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
+ dependencies:
+ type-detect "0.1.1"
+
+deep-eql@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
+ dependencies:
+ type-detect "^4.0.0"
+
+deep-equal@^1.0.0, deep-equal@^1.0.1, deep-equal@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
+
+deep-equal@~0.2.1:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d"
+
+deep-extend@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.0.tgz#6ef4a09b05f98b0e358d6d93d4ca3caec6672803"
+
+deep-extend@~0.4.0:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
+
+deep-freeze-strict@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/deep-freeze-strict/-/deep-freeze-strict-1.1.1.tgz#77d0583ca24a69be4bbd9ac2fae415d55523e5b0"
+
+deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+deepmerge@~0.2.7:
+ version "0.2.10"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-0.2.10.tgz#8906bf9e525a4fbf1b203b2afcb4640249821219"
+
+default-require-extensions@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+ dependencies:
+ strip-bom "^2.0.0"
+
+default-resolution@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684"
+
+deferred-leveldown@~1.2.1:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb"
+ dependencies:
+ abstract-leveldown "~2.6.0"
+
+define-properties@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
+ dependencies:
+ foreach "^2.0.5"
+ object-keys "^1.0.8"
+
+defined@^1.0.0, defined@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
+
+del@^2.0.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+ dependencies:
+ globby "^5.0.0"
+ is-path-cwd "^1.0.0"
+ is-path-in-cwd "^1.0.0"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ rimraf "^2.2.8"
+
+del@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
+ dependencies:
+ globby "^6.1.0"
+ is-path-cwd "^1.0.0"
+ is-path-in-cwd "^1.0.0"
+ p-map "^1.1.1"
+ pify "^3.0.0"
+ rimraf "^2.2.8"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+delegates@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+
+depd@1.1.1, depd@~1.1.0, depd@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
+deps-sort@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5"
+ dependencies:
+ JSONStream "^1.0.3"
+ shasum "^1.0.0"
+ subarg "^1.0.0"
+ through2 "^2.0.0"
+
+derequire@^2.0.0:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/derequire/-/derequire-2.0.6.tgz#31a414bb7ca176239fa78b116636ef77d517e768"
+ dependencies:
+ acorn "^4.0.3"
+ concat-stream "^1.4.6"
+ escope "^3.6.0"
+ through2 "^2.0.0"
+ yargs "^6.5.0"
+
+des.js@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
+ dependencies:
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+
+destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+
+detect-file@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63"
+ dependencies:
+ fs-exists-sync "^0.1.0"
+
+detect-indent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-2.0.0.tgz#720ff51e4d97b76884f6bf57292348b13dfde939"
+ dependencies:
+ get-stdin "^3.0.0"
+ minimist "^1.1.0"
+ repeating "^1.1.0"
+
+detect-indent@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+ dependencies:
+ repeating "^2.0.0"
+
+detect-newline@2.X:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+
+detect-node@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
+
+detective@^4.0.0, detective@^4.3.1:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/detective/-/detective-4.5.0.tgz#6e5a8c6b26e6c7a254b1c6b6d7490d98ec91edd1"
+ dependencies:
+ acorn "^4.0.3"
+ defined "^1.0.0"
+
+di@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
+
+diff@3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
+
+diff@3.3.1, diff@^3.1.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
+
+diffie-hellman@^5.0.0:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
+ dependencies:
+ bn.js "^4.1.0"
+ miller-rabin "^4.0.0"
+ randombytes "^2.0.0"
+
+disc@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/disc/-/disc-1.3.2.tgz#32a6f02e486edf77860a5363d22718425d296e40"
+ dependencies:
+ bl "^0.7.0"
+ browser-unpack "^0.2.3"
+ builtins "0.0.3"
+ commondir "0.0.1"
+ d3 "^3.4.3"
+ duplexer "^0.1.1"
+ file-tree "^1.0.0"
+ flatten "0.0.1"
+ map-async "^0.1.1"
+ opener "^1.3.0"
+ optimist "^0.6.1"
+ plucker "0.0.0"
+ through "^2.3.4"
+ uniq "^1.0.0"
+
+dnode-protocol@~0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/dnode-protocol/-/dnode-protocol-0.2.2.tgz#51151d16fc3b5f84815ee0b9497a1061d0d1949d"
+ dependencies:
+ jsonify "~0.0.0"
+ traverse "~0.6.3"
+
+dnode@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/dnode/-/dnode-1.2.2.tgz#4ac3cfe26e292b3b39b8258ae7d94edc58132efa"
+ dependencies:
+ dnode-protocol "~0.2.2"
+ jsonify "~0.0.0"
+ optionalDependencies:
+ weak "^1.0.0"
+
+doctrine@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
+ dependencies:
+ esutils "^2.0.2"
+ isarray "^1.0.0"
+
+doiuse@^2.4.1:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/doiuse/-/doiuse-2.6.0.tgz#1892d10b61a9a356addbf2b614933e81f8bb3834"
+ dependencies:
+ browserslist "^1.1.1"
+ caniuse-db "^1.0.30000187"
+ css-rule-stream "^1.1.0"
+ duplexer2 "0.0.2"
+ jsonfilter "^1.1.2"
+ ldjson-stream "^1.2.1"
+ lodash "^4.0.0"
+ multimatch "^2.0.0"
+ postcss "^5.0.8"
+ source-map "^0.4.2"
+ through2 "^0.6.3"
+ yargs "^3.5.4"
+
+dom-helpers@^3.2.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.1.tgz#3203e07fed217bd1f424b019735582fc37b2825a"
+
+dom-serialize@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
+ dependencies:
+ custom-event "~1.0.0"
+ ent "~2.2.0"
+ extend "^3.0.0"
+ void-elements "^2.0.0"
+
+dom-serializer@0, dom-serializer@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+ dependencies:
+ domelementtype "~1.1.1"
+ entities "~1.1.1"
+
+dom-walk@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
+
+domain-browser@^1.1.1, domain-browser@~1.1.0:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
+
+domelementtype@1, domelementtype@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+
+domelementtype@~1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@^2.3.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259"
+ dependencies:
+ domelementtype "1"
+
+domkit@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/domkit/-/domkit-0.0.1.tgz#88399d586794efc1154fec6c22cfe50f19bd4dbb"
+
+domutils@1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+domutils@^1.5.1:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+drbg.js@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b"
+ dependencies:
+ browserify-aes "^1.0.6"
+ create-hash "^1.1.2"
+ create-hmac "^1.1.4"
+
+duplexer2@0.0.2, duplexer2@~0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db"
+ dependencies:
+ readable-stream "~1.1.9"
+
+duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
+ dependencies:
+ readable-stream "^2.0.2"
+
+duplexer@^0.1.1, duplexer@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
+
+duplexify@^3.1.2, duplexify@^3.2.0, duplexify@^3.4.2, duplexify@^3.5.0:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
+ dependencies:
+ end-of-stream "^1.0.0"
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+ stream-shift "^1.0.0"
+
+each-props@^1.2.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.1.tgz#fc138f51e3a2774286d4858e02d6e7de462de158"
+ dependencies:
+ is-plain-object "^2.0.1"
+ object.defaults "^1.1.0"
+
+ecc-jsbn@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
+ dependencies:
+ jsbn "~0.1.0"
+
+editorconfig@^0.13.2:
+ version "0.13.3"
+ resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34"
+ dependencies:
+ bluebird "^3.0.5"
+ commander "^2.9.0"
+ lru-cache "^3.2.0"
+ semver "^5.1.0"
+ sigmund "^1.0.1"
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+
+electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.18:
+ version "1.3.21"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.21.tgz#a967ebdcfe8ed0083fc244d1894022a8e8113ea2"
+
+elliptic@^6.0.0, elliptic@^6.2.3:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
+ dependencies:
+ bn.js "^4.4.0"
+ brorand "^1.0.1"
+ hash.js "^1.0.0"
+ hmac-drbg "^1.0.0"
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+ minimalistic-crypto-utils "^1.0.0"
+
+emojis-list@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+
+encodeurl@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
+
+encoding@^0.1.11:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+ dependencies:
+ iconv-lite "~0.4.13"
+
+end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
+ dependencies:
+ once "^1.4.0"
+
+engine.io-client@1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.0.tgz#7b730e4127414087596d9be3c88d2bc5fdb6cf5c"
+ dependencies:
+ component-emitter "1.2.1"
+ component-inherit "0.0.3"
+ debug "2.3.3"
+ engine.io-parser "1.3.1"
+ has-cors "1.1.0"
+ indexof "0.0.1"
+ parsejson "0.0.3"
+ parseqs "0.0.5"
+ parseuri "0.0.5"
+ ws "1.1.1"
+ xmlhttprequest-ssl "1.5.3"
+ yeast "0.1.2"
+
+engine.io-client@1.8.3:
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab"
+ dependencies:
+ component-emitter "1.2.1"
+ component-inherit "0.0.3"
+ debug "2.3.3"
+ engine.io-parser "1.3.2"
+ has-cors "1.1.0"
+ indexof "0.0.1"
+ parsejson "0.0.3"
+ parseqs "0.0.5"
+ parseuri "0.0.5"
+ ws "1.1.2"
+ xmlhttprequest-ssl "1.5.3"
+ yeast "0.1.2"
+
+engine.io-parser@1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.1.tgz#9554f1ae33107d6fbd170ca5466d2f833f6a07cf"
+ dependencies:
+ after "0.8.1"
+ arraybuffer.slice "0.0.6"
+ base64-arraybuffer "0.1.5"
+ blob "0.0.4"
+ has-binary "0.1.6"
+ wtf-8 "1.0.0"
+
+engine.io-parser@1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a"
+ dependencies:
+ after "0.8.2"
+ arraybuffer.slice "0.0.6"
+ base64-arraybuffer "0.1.5"
+ blob "0.0.4"
+ has-binary "0.1.7"
+ wtf-8 "1.0.0"
+
+engine.io@1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.0.tgz#3eeb5f264cb75dbbec1baaea26d61f5a4eace2aa"
+ dependencies:
+ accepts "1.3.3"
+ base64id "0.1.0"
+ cookie "0.3.1"
+ debug "2.3.3"
+ engine.io-parser "1.3.1"
+ ws "1.1.1"
+
+engine.io@1.8.3:
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.3.tgz#8de7f97895d20d39b85f88eeee777b2bd42b13d4"
+ dependencies:
+ accepts "1.3.3"
+ base64id "1.0.0"
+ cookie "0.3.1"
+ debug "2.3.3"
+ engine.io-parser "1.3.2"
+ ws "1.1.2"
+
+enhanced-resolve@^3.3.0:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e"
+ dependencies:
+ graceful-fs "^4.1.2"
+ memory-fs "^0.4.0"
+ object-assign "^4.0.1"
+ tapable "^0.2.7"
+
+ensnare@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ensnare/-/ensnare-1.0.0.tgz#72d2bf7ef48aba21f66adf29d00a0904eddb61c7"
+ dependencies:
+ tape "^4.6.0"
+
+ent@~2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
+
+entities@^1.1.1, "entities@~ 1.1.1", entities@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+
+envify@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e"
+ dependencies:
+ esprima "^4.0.0"
+ through "~2.3.4"
+
+enzyme@^2.8.2:
+ version "2.9.1"
+ resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-2.9.1.tgz#07d5ce691241240fb817bf2c4b18d6e530240df6"
+ dependencies:
+ cheerio "^0.22.0"
+ function.prototype.name "^1.0.0"
+ is-subset "^0.1.1"
+ lodash "^4.17.4"
+ object-is "^1.0.1"
+ object.assign "^4.0.4"
+ object.entries "^1.0.4"
+ object.values "^1.0.4"
+ prop-types "^15.5.10"
+ uuid "^3.0.1"
+
+errno@^0.1.3, errno@~0.1.1:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
+ dependencies:
+ prr "~0.0.0"
+
+error-ex@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
+ dependencies:
+ is-arrayish "^0.2.1"
+
+es-abstract@^1.5.0, es-abstract@^1.6.1:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.8.2.tgz#25103263dc4decbda60e0c737ca32313518027ee"
+ dependencies:
+ es-to-primitive "^1.1.1"
+ function-bind "^1.1.1"
+ has "^1.0.1"
+ is-callable "^1.1.3"
+ is-regex "^1.0.4"
+
+es-to-primitive@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
+ dependencies:
+ is-callable "^1.1.1"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.1"
+
+es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2:
+ version "0.10.30"
+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.30.tgz#7141a16836697dbabfaaaeee41495ce29f52c939"
+ dependencies:
+ es6-iterator "2"
+ es6-symbol "~3.1"
+
+es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512"
+ dependencies:
+ d "1"
+ es5-ext "^0.10.14"
+ es6-symbol "^3.1"
+
+es6-map@^0.1.3:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
+ dependencies:
+ d "1"
+ es5-ext "~0.10.14"
+ es6-iterator "~2.0.1"
+ es6-set "~0.1.5"
+ es6-symbol "~3.1.1"
+ event-emitter "~0.3.5"
+
+es6-set@~0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
+ dependencies:
+ d "1"
+ es5-ext "~0.10.14"
+ es6-iterator "~2.0.1"
+ es6-symbol "3.1.1"
+ event-emitter "~0.3.5"
+
+es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
+ dependencies:
+ d "1"
+ es5-ext "~0.10.14"
+
+es6-weak-map@^2.0.1, es6-weak-map@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
+ dependencies:
+ d "1"
+ es5-ext "^0.10.14"
+ es6-iterator "^2.0.1"
+ es6-symbol "^3.1.1"
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escodegen@1.8.x:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018"
+ dependencies:
+ esprima "^2.7.1"
+ estraverse "^1.9.1"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.2.0"
+
+escodegen@^1.6.1:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852"
+ dependencies:
+ esprima "^3.1.3"
+ estraverse "^4.2.0"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.5.6"
+
+escodegen@~0.0.24:
+ version "0.0.28"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-0.0.28.tgz#0e4ff1715f328775d6cab51ac44a406cd7abffd3"
+ dependencies:
+ esprima "~1.0.2"
+ estraverse "~1.3.0"
+ optionalDependencies:
+ source-map ">= 0.1.2"
+
+escodegen@~1.3.2:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.3.3.tgz#f024016f5a88e046fd12005055e939802e6c5f23"
+ dependencies:
+ esprima "~1.1.1"
+ estraverse "~1.5.0"
+ esutils "~1.0.0"
+ optionalDependencies:
+ source-map "~0.1.33"
+
+escope@^3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
+ dependencies:
+ es6-map "^0.1.3"
+ es6-weak-map "^2.0.1"
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+eslint-plugin-chai@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-chai/-/eslint-plugin-chai-0.0.1.tgz#9a1dea58b335c31242219d059b37ffb14309f6e1"
+
+eslint-plugin-mocha@^4.9.0:
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-4.11.0.tgz#91193a2f55e20a5e35974054a0089d30198ee578"
+ dependencies:
+ ramda "^0.24.1"
+
+eslint-scope@^3.7.1:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
+ dependencies:
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+eslint@^4.0.0, eslint@^4.2.0:
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.6.1.tgz#ddc7fc7fd70bf93205b0b3449bb16a1e9e7d4950"
+ dependencies:
+ ajv "^5.2.0"
+ babel-code-frame "^6.22.0"
+ chalk "^2.1.0"
+ concat-stream "^1.6.0"
+ cross-spawn "^5.1.0"
+ debug "^2.6.8"
+ doctrine "^2.0.0"
+ eslint-scope "^3.7.1"
+ espree "^3.5.0"
+ esquery "^1.0.0"
+ estraverse "^4.2.0"
+ esutils "^2.0.2"
+ file-entry-cache "^2.0.0"
+ functional-red-black-tree "^1.0.1"
+ glob "^7.1.2"
+ globals "^9.17.0"
+ ignore "^3.3.3"
+ imurmurhash "^0.1.4"
+ inquirer "^3.0.6"
+ is-resolvable "^1.0.0"
+ js-yaml "^3.9.1"
+ json-stable-stringify "^1.0.1"
+ levn "^0.3.0"
+ lodash "^4.17.4"
+ minimatch "^3.0.2"
+ mkdirp "^0.5.1"
+ natural-compare "^1.4.0"
+ optionator "^0.8.2"
+ path-is-inside "^1.0.2"
+ pluralize "^4.0.0"
+ progress "^2.0.0"
+ require-uncached "^1.0.3"
+ semver "^5.3.0"
+ strip-ansi "^4.0.0"
+ strip-json-comments "~2.0.1"
+ table "^4.0.1"
+ text-table "~0.2.0"
+
+espree@^3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d"
+ dependencies:
+ acorn "^5.1.1"
+ acorn-jsx "^3.0.0"
+
+esprima-fb@13001.1001.0-dev-harmony-fb:
+ version "13001.1001.0-dev-harmony-fb"
+ resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz#633acdb40d9bd4db8a1c1d68c06a942959fad2b0"
+
+esprima-fb@3001.1.0-dev-harmony-fb:
+ version "3001.1.0-dev-harmony-fb"
+ resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411"
+
+esprima@2.7.x, esprima@^2.7.1:
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+
+esprima@^3.1.3, esprima@~3.1.0:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+
+esprima@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
+
+esprima@~1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad"
+
+esprima@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.1.1.tgz#5b6f1547f4d102e670e140c509be6771d6aeb549"
+
+esquery@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+ dependencies:
+ estraverse "^4.0.0"
+
+esrecurse@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
+ dependencies:
+ estraverse "^4.1.0"
+ object-assign "^4.0.1"
+
+estraverse@^1.9.1:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
+
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
+estraverse@~1.3.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.3.2.tgz#37c2b893ef13d723f276d878d60d8535152a6c42"
+
+estraverse@~1.5.0:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71"
+
+esutils@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+esutils@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570"
+
+etag@~1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051"
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+
+eth-bin-to-ops@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/eth-bin-to-ops/-/eth-bin-to-ops-1.0.1.tgz#4d2703b9878825bc38c6259910e90b4db005c7de"
+ dependencies:
+ ethereumjs-vm "^2.0.0"
+ tape "^4.6.2"
+
+eth-block-tracker@^1.0.7:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-1.1.3.tgz#c46a0f2bced9b49b88c7f3918856d7ec57fbdc29"
+ dependencies:
+ async-eventemitter "^0.2.2"
+ babelify "^7.3.0"
+ eth-query "^2.1.0"
+ ethjs-util "^0.1.3"
+ pify "^2.3.0"
+ tape "^4.6.3"
+
+eth-block-tracker@^2.1.2:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.1.3.tgz#ef24ab415f18445bd5c0ef49b9ac248f847e34f9"
+ dependencies:
+ async-eventemitter "^0.2.2"
+ babelify "^7.3.0"
+ eth-query "^2.1.0"
+ ethjs-util "^0.1.3"
+ pify "^2.3.0"
+ tape "^4.6.3"
+
+eth-block-tracker@^2.2.0, eth-block-tracker@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.2.2.tgz#b3d72cd82ba5ee37471d22bac4f56387ee4137cf"
+ dependencies:
+ async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c
+ babelify "^7.3.0"
+ eth-query "^2.1.0"
+ ethjs-util "^0.1.3"
+ pify "^2.3.0"
+ tape "^4.6.3"
+
+eth-contract-metadata@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/eth-contract-metadata/-/eth-contract-metadata-1.1.5.tgz#301f51b0460b8dd044997dc05870751fb7f4cfcb"
+
+eth-ens-namehash@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-1.0.2.tgz#05ecdd6bac2d7fd7bc5ca84a993c6bad9da4edb9"
+ dependencies:
+ idna-uts46 "^1.0.1"
+ js-sha3 "^0.5.7"
+
+eth-hd-keyring@^1.1.1, eth-hd-keyring@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-1.2.0.tgz#40bcc7ea877ef5c746f54c0c87a6b39ceb5edde3"
+ dependencies:
+ bip39 "^2.2.0"
+ eth-sig-util "^1.1.0"
+ ethereumjs-util "^5.1.1"
+ ethereumjs-wallet "^0.6.0"
+ events "^1.1.1"
+
+eth-json-rpc-filters@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-1.2.1.tgz#96e1714272a0f7d6d8efef7af8d764988f73ffc1"
+ dependencies:
+ await-semaphore "^0.1.1"
+ eth-json-rpc-middleware "^1.0.0"
+ lodash.flatmap "^4.5.0"
+
+eth-json-rpc-middleware@^1.0.0, eth-json-rpc-middleware@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.2.7.tgz#7c36e0972945255bdb486f18df53d4314a1c048a"
+ dependencies:
+ async "^2.5.0"
+ eth-query "^2.1.2"
+ ethereumjs-block "^1.6.0"
+ ethereumjs-tx "^1.3.3"
+ ethereumjs-vm "^2.1.0"
+ fetch-ponyfill "^4.0.0"
+ json-rpc-error "^2.0.0"
+ json-stable-stringify "^1.0.1"
+ promise-to-callback "^1.0.0"
+ tape "^4.6.3"
+
+eth-keyring-controller@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-2.1.0.tgz#46b2c1597d9471aab5e4f792dc109084ed196f2d"
+ dependencies:
+ bip39 "^2.4.0"
+ bluebird "^3.5.0"
+ browser-passworder "^2.0.3"
+ eth-hd-keyring "^1.2.0"
+ eth-sig-util "^1.2.2"
+ eth-simple-keyring "^1.1.1"
+ ethereumjs-util "^5.1.2"
+ loglevel "^1.5.0"
+ obs-store "^2.4.1"
+ promise-filter "^1.1.0"
+
+eth-phishing-detect@^1.1.4:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/eth-phishing-detect/-/eth-phishing-detect-1.1.11.tgz#e29c38b84abed3d41df4131c56d6a41308c3e56d"
+ dependencies:
+ fast-levenshtein "^2.0.6"
+
+eth-query@^2.1.0, eth-query@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e"
+ dependencies:
+ json-rpc-random-id "^1.0.0"
+ xtend "^4.0.1"
+
+eth-sig-util@^1.1.0, eth-sig-util@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.2.2.tgz#7e982f5f8d94e79027d8c69e6006cdbd2f57942f"
+ dependencies:
+ ethereumjs-util "^5.1.1"
+
+eth-sig-util@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.3.0.tgz#14c1c02367a4264dbfeae611b4dc7f8d9d6ee4ba"
+ dependencies:
+ ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git"
+ ethereumjs-util "^5.1.1"
+
+eth-simple-keyring@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-1.1.1.tgz#6dd75d7cc6edea7c788cf19ef9431c830cd961ae"
+ dependencies:
+ eth-sig-util "^1.1.0"
+ ethereumjs-util "^5.1.1"
+ ethereumjs-wallet "^0.6.0"
+ events "^1.1.1"
+
+eth-token-tracker@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/eth-token-tracker/-/eth-token-tracker-1.1.4.tgz#29ff2457d66bfa3b8ee490e83ff40fd0cf2cec41"
+ dependencies:
+ deep-equal "^1.0.1"
+ eth-block-tracker "^1.0.7"
+ ethjs "^0.2.7"
+ ethjs-contract "^0.1.9"
+ ethjs-query "^0.2.6"
+ human-standard-token-abi "^1.0.2"
+
+ethereum-common@0.0.18, ethereum-common@^0.0.18:
+ version "0.0.18"
+ resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f"
+
+ethereum-common@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.1.0.tgz#874dd0fae5e962a56c50ebf28efa6fe39492b0e7"
+
+ethereum-ens-network-map@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.0.tgz#43cd7669ce950a789e151001118d4d65f210eeb7"
+
+ethereumjs-abi@^0.6.4:
+ version "0.6.4"
+ resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.4.tgz#9ba1bb056492d00c27279f6eccd4d58275912c1a"
+ dependencies:
+ bn.js "^4.10.0"
+ ethereumjs-util "^4.3.0"
+
+"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git":
+ version "0.6.4"
+ resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee6ded67235a98f3ef4ae2a338aee70a9f68fe20"
+ dependencies:
+ bn.js "^4.10.0"
+ ethereumjs-util "^4.3.0"
+
+ethereumjs-account@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.4.tgz#f8c30231bcb707f4514d8a052c1f9da103624d47"
+ dependencies:
+ ethereumjs-util "^4.0.1"
+ rlp "^2.0.0"
+
+ethereumjs-block@^1.2.2, ethereumjs-block@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.6.0.tgz#cded4962deaca1eef17372b4d290e84b35c84372"
+ dependencies:
+ async "^2.0.1"
+ ethereum-common "0.0.18"
+ ethereumjs-tx "^1.2.2"
+ ethereumjs-util "^5.0.0"
+ merkle-patricia-tree "^2.1.2"
+
+ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.0, ethereumjs-tx@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.3.tgz#ece051d3efdbe771ad2a518d61632ca2ab75ecbb"
+ dependencies:
+ ethereum-common "^0.0.18"
+ ethereumjs-util "^5.0.0"
+
+ethereumjs-util@4.5.0, ethereumjs-util@^4.0.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
+ dependencies:
+ bn.js "^4.8.0"
+ create-hash "^1.1.2"
+ keccakjs "^0.2.0"
+ rlp "^2.0.0"
+ secp256k1 "^3.0.1"
+
+ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.2.tgz#25ba0215cbb4c2f0b108a6f96af2a2e62e45921f"
+ dependencies:
+ babel-preset-es2015 "^6.24.0"
+ babelify "^7.3.0"
+ bn.js "^4.8.0"
+ create-hash "^1.1.2"
+ ethjs-util "^0.1.3"
+ keccak "^1.0.2"
+ rlp "^2.0.0"
+ secp256k1 "^3.0.1"
+
+"ethereumjs-util@github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9":
+ version "5.0.1"
+ resolved "https://codeload.github.com/ethereumjs/ethereumjs-util/tar.gz/ac5d0908536b447083ea422b435da27f26615de9"
+ dependencies:
+ bn.js "^4.8.0"
+ create-hash "^1.1.2"
+ keccak "^1.0.2"
+ rlp "^2.0.0"
+ secp256k1 "^3.0.1"
+
+ethereumjs-vm@^2.0.0, ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.2.1.tgz#183406cc40e4d9f4248e7e047dea7c191beab3a1"
+ dependencies:
+ async "^2.1.2"
+ async-eventemitter "^0.2.2"
+ ethereum-common "0.1.0"
+ ethereumjs-account "^2.0.3"
+ ethereumjs-block "^1.2.2"
+ ethereumjs-util "4.5.0"
+ fake-merkle-patricia-tree "^1.0.1"
+ functional-red-black-tree "^1.0.1"
+ merkle-patricia-tree "^2.1.2"
+
+ethereumjs-wallet@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb"
+ dependencies:
+ aes-js "^0.2.3"
+ bs58check "^1.0.8"
+ ethereumjs-util "^4.4.0"
+ hdkey "^0.7.0"
+ scrypt.js "^0.2.0"
+ utf8 "^2.1.1"
+ uuid "^2.0.1"
+
+ethjs-abi@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/ethjs-abi/-/ethjs-abi-0.2.0.tgz#d3e2c221011520fc499b71682036c14fcc2f5b25"
+ dependencies:
+ bn.js "4.11.6"
+ js-sha3 "0.5.5"
+ number-to-bn "1.7.0"
+
+ethjs-contract@0.1.9, ethjs-contract@^0.1.7, ethjs-contract@^0.1.9:
+ version "0.1.9"
+ resolved "https://registry.yarnpkg.com/ethjs-contract/-/ethjs-contract-0.1.9.tgz#1c2766896a56d47ec1d6d661829c49cc38a5520a"
+ dependencies:
+ ethjs-abi "0.2.0"
+ ethjs-filter "0.1.5"
+ ethjs-util "0.1.3"
+ js-sha3 "0.5.5"
+
+ethjs-ens@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ethjs-ens/-/ethjs-ens-2.0.1.tgz#eda0a21aacbdac2f60c4a01034df21c48a5a325b"
+ dependencies:
+ eth-ens-namehash "^1.0.2"
+ ethereum-ens-network-map "^1.0.0"
+ ethjs-contract "^0.1.7"
+ ethjs-query "^0.2.4"
+
+ethjs-filter@0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/ethjs-filter/-/ethjs-filter-0.1.5.tgz#0112af6017c24677e32b8fdeb20e6196019b7598"
+
+ethjs-format@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/ethjs-format/-/ethjs-format-0.2.0.tgz#b4aa513fc1d50270d8f102bf06f03c9490d31391"
+ dependencies:
+ bn.js "4.11.6"
+ ethjs-schema "0.1.5"
+ ethjs-util "0.1.3"
+ is-hex-prefixed "1.0.0"
+ number-to-bn "1.7.0"
+ strip-hex-prefix "1.0.0"
+
+ethjs-format@0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/ethjs-format/-/ethjs-format-0.2.2.tgz#d73b3a605c2e1257079f7077fd5448e998ce0fcd"
+ dependencies:
+ bn.js "4.11.6"
+ ethjs-schema "0.1.5"
+ ethjs-util "0.1.3"
+ is-hex-prefixed "1.0.0"
+ number-to-bn "1.7.0"
+ strip-hex-prefix "1.0.0"
+
+ethjs-provider-http@0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/ethjs-provider-http/-/ethjs-provider-http-0.1.6.tgz#1ec5d9b4be257ef1d56a500b22a741985e889420"
+ dependencies:
+ xhr2 "0.1.3"
+
+ethjs-query@0.2.6:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/ethjs-query/-/ethjs-query-0.2.6.tgz#9d8e6044b8bf76dd3340f843716a2259b9c91d3c"
+ dependencies:
+ ethjs-format "0.2.0"
+ ethjs-rpc "0.1.5"
+
+ethjs-query@^0.2.4, ethjs-query@^0.2.6, ethjs-query@^0.2.9:
+ version "0.2.9"
+ resolved "https://registry.yarnpkg.com/ethjs-query/-/ethjs-query-0.2.9.tgz#a26e6b4f38699e92f34b2184e75c7894329c42f1"
+ dependencies:
+ ethjs-format "0.2.2"
+ ethjs-rpc "0.1.5"
+
+ethjs-rpc@0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/ethjs-rpc/-/ethjs-rpc-0.1.5.tgz#099e22f27dc4c18b6978a485fc36b1b0f7969080"
+
+ethjs-schema@0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/ethjs-schema/-/ethjs-schema-0.1.5.tgz#59740e3b3977bcdbb9b11bc3068201e8aceabb0d"
+
+ethjs-unit@0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699"
+ dependencies:
+ bn.js "4.11.6"
+ number-to-bn "1.7.0"
+
+ethjs-util@0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.3.tgz#dfd5ea4a400dc5e421a889caf47e081ada78bb55"
+ dependencies:
+ is-hex-prefixed "1.0.0"
+ strip-hex-prefix "1.0.0"
+
+ethjs-util@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.4.tgz#1c8b6879257444ef4d3f3fbbac2ded12cd997d93"
+ dependencies:
+ is-hex-prefixed "1.0.0"
+ strip-hex-prefix "1.0.0"
+
+ethjs@^0.2.7, ethjs@^0.2.8:
+ version "0.2.8"
+ resolved "https://registry.yarnpkg.com/ethjs/-/ethjs-0.2.8.tgz#65ed276c5e58e89d51d4573585b7a16142ccf8f0"
+ dependencies:
+ bn.js "4.11.6"
+ ethjs-abi "0.2.0"
+ ethjs-contract "0.1.9"
+ ethjs-filter "0.1.5"
+ ethjs-provider-http "0.1.6"
+ ethjs-query "0.2.6"
+ ethjs-unit "0.1.6"
+ ethjs-util "0.1.3"
+ js-sha3 "0.5.5"
+ number-to-bn "1.7.0"
+
+eve-raphael@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30"
+
+event-emitter@^0.3.5, event-emitter@~0.3.5:
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
+ dependencies:
+ d "1"
+ es5-ext "~0.10.14"
+
+event-stream@^3.1.7:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
+ dependencies:
+ duplexer "~0.1.1"
+ from "~0"
+ map-stream "~0.1.0"
+ pause-stream "0.0.11"
+ split "0.3"
+ stream-combiner "~0.0.4"
+ through "~2.3.1"
+
+eventemitter3@1.x.x:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
+
+events-to-array@^1.0.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/events-to-array/-/events-to-array-1.1.2.tgz#2d41f563e1fe400ed4962fe1a4d5c6a7539df7f6"
+
+events@^1.0.0, events@^1.1.1, events@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+
+evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+ dependencies:
+ md5.js "^1.3.4"
+ safe-buffer "^5.1.1"
+
+execa@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
+ dependencies:
+ cross-spawn "^5.0.1"
+ get-stream "^3.0.0"
+ is-stream "^1.1.0"
+ npm-run-path "^2.0.0"
+ p-finally "^1.0.0"
+ signal-exit "^3.0.0"
+ strip-eof "^1.0.0"
+
+execall@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73"
+ dependencies:
+ clone-regexp "^1.0.0"
+
+expand-braces@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea"
+ dependencies:
+ array-slice "^0.2.3"
+ array-unique "^0.2.1"
+ braces "^0.1.2"
+
+expand-brackets@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+ dependencies:
+ is-posix-bracket "^0.1.0"
+
+expand-range@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044"
+ dependencies:
+ is-number "^0.1.1"
+ repeat-string "^0.2.2"
+
+expand-range@^1.8.1:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+ dependencies:
+ fill-range "^2.1.0"
+
+expand-template@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.1.0.tgz#e09efba977bf98f9ee0ed25abd0c692e02aec3fc"
+
+expand-tilde@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449"
+ dependencies:
+ os-homedir "^1.0.1"
+
+expand-tilde@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
+ dependencies:
+ homedir-polyfill "^1.0.1"
+
+express@^4.10.7:
+ version "4.15.4"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1"
+ dependencies:
+ accepts "~1.3.3"
+ array-flatten "1.1.1"
+ content-disposition "0.5.2"
+ content-type "~1.0.2"
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+ debug "2.6.8"
+ depd "~1.1.1"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.0"
+ finalhandler "~1.0.4"
+ fresh "0.5.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.1"
+ path-to-regexp "0.1.7"
+ proxy-addr "~1.1.5"
+ qs "6.5.0"
+ range-parser "~1.2.0"
+ send "0.15.4"
+ serve-static "1.12.4"
+ setprototypeof "1.0.3"
+ statuses "~1.3.1"
+ type-is "~1.6.15"
+ utils-merge "1.0.0"
+ vary "~1.1.1"
+
+express@^4.15.5:
+ version "4.16.0"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.16.0.tgz#b519638e4eb58e7178c81b498ef22f798cb2e255"
+ dependencies:
+ accepts "~1.3.4"
+ array-flatten "1.1.1"
+ body-parser "1.18.2"
+ content-disposition "0.5.2"
+ content-type "~1.0.4"
+ cookie "0.3.1"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "~1.1.1"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.1.0"
+ fresh "0.5.2"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.2"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.2"
+ qs "6.5.1"
+ range-parser "~1.2.0"
+ safe-buffer "5.1.1"
+ send "0.16.0"
+ serve-static "1.13.0"
+ setprototypeof "1.1.0"
+ statuses "~1.3.1"
+ type-is "~1.6.15"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+extend-shallow@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
+ dependencies:
+ is-extendable "^0.1.0"
+
+extend@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-1.3.0.tgz#d1516fb0ff5624d2ebf9123ea1dac5a1994004f8"
+
+extend@^3.0.0, extend@~3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+
+extension-link-enabler@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/extension-link-enabler/-/extension-link-enabler-1.0.0.tgz#57b919aeeedf38be97270b9898cee78a637e46f3"
+ dependencies:
+ extensionizer "^1.0.0"
+
+extensionizer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.0.tgz#01c209bbea6d9c0acba77129c3aa4a9a98fc3538"
+
+external-editor@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972"
+ dependencies:
+ iconv-lite "^0.4.17"
+ jschardet "^1.4.2"
+ tmp "^0.0.31"
+
+extglob@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+ dependencies:
+ is-extglob "^1.0.0"
+
+extsprintf@1.3.0, extsprintf@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+
+eyes@0.1.x:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
+
+fake-merkle-patricia-tree@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3"
+ dependencies:
+ checkpoint-store "^1.1.0"
+
+falafel@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c"
+ dependencies:
+ acorn "^5.0.0"
+ foreach "^2.0.5"
+ isarray "0.0.1"
+ object-keys "^1.0.6"
+
+fancy-log@^1.1.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948"
+ dependencies:
+ chalk "^1.1.1"
+ time-stamp "^1.0.0"
+
+fast-deep-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
+
+fast-json-patch@^2.0.4:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-2.0.5.tgz#a712e829be69ab707514440c5404bdd9b0d3c609"
+ dependencies:
+ deep-equal "^1.0.1"
+
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+
+faye-websocket@~0.7.2:
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.7.3.tgz#cc4074c7f4a4dfd03af54dd65c354b135132ce11"
+ dependencies:
+ websocket-driver ">=0.3.6"
+
+fbjs@^0.8.9:
+ version "0.8.15"
+ resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.15.tgz#4f0695fdfcc16c37c0b07facec8cb4c4091685b9"
+ dependencies:
+ core-js "^1.0.0"
+ isomorphic-fetch "^2.1.1"
+ loose-envify "^1.0.0"
+ object-assign "^4.1.0"
+ promise "^7.1.1"
+ setimmediate "^1.0.5"
+ ua-parser-js "^0.7.9"
+
+fetch-ponyfill@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893"
+ dependencies:
+ node-fetch "~1.7.1"
+
+figures@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+file-entry-cache@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
+ dependencies:
+ flat-cache "^1.2.1"
+ object-assign "^4.0.1"
+
+file-tree@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/file-tree/-/file-tree-1.0.0.tgz#fdad999cb7fa44438350b514c78f935b306e93e3"
+ dependencies:
+ async-reduce "0.0.1"
+ commondir "0.0.1"
+ flat "~1.0.0"
+
+filename-regex@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
+
+fill-range@^2.1.0:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
+ dependencies:
+ is-number "^2.1.0"
+ isobject "^2.0.0"
+ randomatic "^1.1.3"
+ repeat-element "^1.1.2"
+ repeat-string "^1.5.2"
+
+finalhandler@1.0.4, finalhandler@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7"
+ dependencies:
+ debug "2.6.8"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.1"
+ statuses "~1.3.1"
+ unpipe "~1.0.0"
+
+finalhandler@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.2"
+ statuses "~1.3.1"
+ unpipe "~1.0.0"
+
+find-cache-dir@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9"
+ dependencies:
+ commondir "^1.0.1"
+ mkdirp "^0.5.1"
+ pkg-dir "^1.0.0"
+
+find-global-packages@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/find-global-packages/-/find-global-packages-0.0.1.tgz#4ba7fdff17ee9fa7da833095f78b5e8cdbdf3e2b"
+ dependencies:
+ which "^1.0.5"
+
+find-up@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+ dependencies:
+ path-exists "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+find-up@^2.0.0, find-up@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ dependencies:
+ locate-path "^2.0.0"
+
+findup-sync@^0.4.2:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12"
+ dependencies:
+ detect-file "^0.1.0"
+ is-glob "^2.0.1"
+ micromatch "^2.3.7"
+ resolve-dir "^0.1.0"
+
+findup-sync@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16"
+ dependencies:
+ glob "~5.0.0"
+
+fined@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
+ dependencies:
+ expand-tilde "^2.0.2"
+ is-plain-object "^2.0.3"
+ object.defaults "^1.1.0"
+ object.pick "^1.2.0"
+ parse-filepath "^1.0.1"
+
+fireworm@^0.7.0:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/fireworm/-/fireworm-0.7.1.tgz#ccf20f7941f108883fcddb99383dbe6e1861c758"
+ dependencies:
+ async "~0.2.9"
+ is-type "0.0.1"
+ lodash.debounce "^3.1.1"
+ lodash.flatten "^3.0.2"
+ minimatch "^3.0.2"
+
+first-chunk-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e"
+
+first-chunk-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70"
+ dependencies:
+ readable-stream "^2.0.2"
+
+flagged-respawn@^0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-0.3.2.tgz#ff191eddcd7088a675b2610fffc976be9b8074b5"
+
+flat-cache@^1.2.1:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
+ dependencies:
+ circular-json "^0.3.1"
+ del "^2.0.2"
+ graceful-fs "^4.1.2"
+ write "^0.2.1"
+
+flat@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/flat/-/flat-1.0.0.tgz#01dfdd5bcbc149c66b35ed401e1d753f1aad8d59"
+
+flatten@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/flatten/-/flatten-0.0.1.tgz#554440766da0a0d603999f433453f6c2fc6a75c1"
+
+flatten@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
+
+flush-write-stream@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417"
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.4"
+
+for-each@^0.3.2, for-each@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4"
+ dependencies:
+ is-function "~1.0.0"
+
+for-in@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+
+for-own@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
+ dependencies:
+ for-in "^1.0.1"
+
+for-own@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
+ dependencies:
+ for-in "^1.0.1"
+
+foreach@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
+
+foreground-child@^1.5.3, foreground-child@^1.5.6:
+ version "1.5.6"
+ resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9"
+ dependencies:
+ cross-spawn "^4"
+ signal-exit "^3.0.0"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+fork-stream@^0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70"
+
+form-data@~2.1.1:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.5"
+ mime-types "^2.1.12"
+
+formatio@1.2.0, formatio@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
+ dependencies:
+ samsam "1.x"
+
+forwarded@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.1.tgz#8a4e30c640b05395399a3549c730257728048961"
+
+forwarded@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+
+fresh@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+
+from2@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+
+from@~0:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
+
+fs-access@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
+ dependencies:
+ null-check "^1.0.0"
+
+fs-exists-sync@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
+
+fs-extra@^0.30.0:
+ version "0.30.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^2.1.0"
+ klaw "^1.0.0"
+ path-is-absolute "^1.0.0"
+ rimraf "^2.2.8"
+
+fs-extra@^2.0.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35"
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^2.1.0"
+
+fs-promise@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854"
+ dependencies:
+ any-promise "^1.3.0"
+ fs-extra "^2.0.0"
+ mz "^2.6.0"
+ thenify-all "^1.6.0"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+fsevents@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4"
+ dependencies:
+ nan "^2.3.0"
+ node-pre-gyp "^0.6.36"
+
+fstream-ignore@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
+ dependencies:
+ fstream "^1.0.0"
+ inherits "2"
+ minimatch "^3.0.0"
+
+fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
+ dependencies:
+ graceful-fs "^4.1.2"
+ inherits "~2.0.0"
+ mkdirp ">=0.5 0"
+ rimraf "2"
+
+function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1, function-bind@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+
+function.prototype.name@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.0.3.tgz#0099ae5572e9dd6f03c97d023fd92bcc5e639eac"
+ dependencies:
+ define-properties "^1.1.2"
+ function-bind "^1.1.0"
+ is-callable "^1.1.3"
+
+functional-red-black-tree@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+
+fuse.js@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.1.0.tgz#9062146c471552189b0f678b4f5a155731ae3b3c"
+
+gather-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/gather-stream/-/gather-stream-1.0.0.tgz#b33994af457a8115700d410f317733cbe7a0904b"
+
+gauge@~2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+ dependencies:
+ aproba "^1.0.3"
+ console-control-strings "^1.0.0"
+ has-unicode "^2.0.0"
+ object-assign "^4.1.0"
+ signal-exit "^3.0.0"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+ wide-align "^1.1.0"
+
+gaze@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105"
+ dependencies:
+ globule "^1.0.0"
+
+get-caller-file@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
+
+get-func-name@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+
+get-stdin@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-3.0.2.tgz#c1ced24b9039b38ded85bdf161e57713b6dd4abe"
+
+get-stdin@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+
+get-stdin@^5.0.0, get-stdin@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
+
+get-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ dependencies:
+ assert-plus "^1.0.0"
+
+github-from-package@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
+
+gl-mat4@1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/gl-mat4/-/gl-mat4-1.1.4.tgz#1e895b55892e56a896867abd837d38f37a178086"
+
+gl-vec3@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/gl-vec3/-/gl-vec3-1.0.3.tgz#110fd897d0729f6398307381567d0944941bf22b"
+
+glob-all@^3.0.1:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab"
+ dependencies:
+ glob "^7.0.5"
+ yargs "~1.2.6"
+
+glob-base@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+ dependencies:
+ glob-parent "^2.0.0"
+ is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+ dependencies:
+ is-glob "^2.0.0"
+
+glob-parent@^3.0.0, glob-parent@^3.0.1:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
+ dependencies:
+ is-glob "^3.1.0"
+ path-dirname "^1.0.0"
+
+glob-stream@^5.3.2:
+ version "5.3.5"
+ resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22"
+ dependencies:
+ extend "^3.0.0"
+ glob "^5.0.3"
+ glob-parent "^3.0.0"
+ micromatch "^2.3.7"
+ ordered-read-streams "^0.3.0"
+ through2 "^0.6.0"
+ to-absolute-glob "^0.1.1"
+ unique-stream "^2.0.2"
+
+glob-watcher@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-3.2.0.tgz#ffc1a2d3d07783b672f5e21799a4d0b3fed92daf"
+ dependencies:
+ async-done "^1.2.0"
+ chokidar "^1.4.3"
+ lodash.debounce "^4.0.6"
+ object.defaults "^1.0.0"
+
+glob@7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.2"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.0.6, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^5.0.15, glob@^5.0.3, glob@~5.0.0:
+ version "5.0.15"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
+ dependencies:
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "2 || 3"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+global-modules@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d"
+ dependencies:
+ global-prefix "^0.1.4"
+ is-windows "^0.2.0"
+
+global-prefix@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f"
+ dependencies:
+ homedir-polyfill "^1.0.0"
+ ini "^1.3.4"
+ is-windows "^0.2.0"
+ which "^1.2.12"
+
+global@~4.3.0:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
+ dependencies:
+ min-document "^2.19.0"
+ process "~0.5.1"
+
+globals@^10.0.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-10.1.0.tgz#4425a1881be0d336b4a823a82a7be725d5dd987c"
+
+globals@^9.17.0, globals@^9.18.0:
+ version "9.18.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+
+globby@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+ dependencies:
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ glob "^7.0.3"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+globby@^6.0.0, globby@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
+ dependencies:
+ array-union "^1.0.1"
+ glob "^7.0.3"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+globjoin@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
+
+globule@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09"
+ dependencies:
+ glob "~7.1.1"
+ lodash "~4.17.4"
+ minimatch "~3.0.2"
+
+glogg@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5"
+ dependencies:
+ sparkles "^1.0.0"
+
+graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
+ version "4.1.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+"graceful-readlink@>= 1.0.0":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
+
+growl@1.10.3:
+ version "1.10.3"
+ resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f"
+
+growl@1.9.2:
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
+
+growly@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+
+gulp-autoprefixer@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/gulp-autoprefixer/-/gulp-autoprefixer-4.0.0.tgz#e00a8c571b85d06516ac26341be90dfd9fc1eab0"
+ dependencies:
+ autoprefixer "^7.0.0"
+ gulp-util "^3.0.0"
+ postcss "^6.0.1"
+ through2 "^2.0.0"
+ vinyl-sourcemaps-apply "^0.2.0"
+
+gulp-cli@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-1.4.0.tgz#6f5bbe2cd0bdb4849d12cf9e1246a5861f8b4f88"
+ dependencies:
+ archy "^1.0.0"
+ chalk "^1.1.0"
+ copy-props "^1.4.1"
+ fancy-log "^1.1.0"
+ gulplog "^1.0.0"
+ interpret "^1.0.0"
+ liftoff "^2.3.0"
+ lodash.isfunction "^3.0.8"
+ lodash.isplainobject "^4.0.4"
+ lodash.sortby "^4.5.0"
+ matchdep "^1.0.0"
+ mute-stdout "^1.0.0"
+ pretty-hrtime "^1.0.0"
+ semver-greatest-satisfied-range "^1.0.0"
+ tildify "^1.0.0"
+ v8flags "^2.0.9"
+ wreck "^6.3.0"
+ yargs "^3.28.0"
+
+gulp-eslint@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/gulp-eslint/-/gulp-eslint-4.0.0.tgz#16d9ea4d696e7b7a9d65eeb1aa5bc4ba0a22c7f7"
+ dependencies:
+ eslint "^4.0.0"
+ gulp-util "^3.0.8"
+
+gulp-if@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-2.0.2.tgz#a497b7e7573005041caa2bc8b7dda3c80444d629"
+ dependencies:
+ gulp-match "^1.0.3"
+ ternary-stream "^2.0.1"
+ through2 "^2.0.1"
+
+gulp-json-editor@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/gulp-json-editor/-/gulp-json-editor-2.2.1.tgz#7c4dd7477e8d06dc5dc49c0b81e745cdb04f97bb"
+ dependencies:
+ deepmerge "~0.2.7"
+ detect-indent "^2.0.0"
+ gulp-util "~3.0.0"
+ js-beautify "~1.5.4"
+ through2 "~0.5.0"
+
+gulp-livereload@^3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/gulp-livereload/-/gulp-livereload-3.8.1.tgz#00f744b2d749d3e9e3746589c8a44acac779b50f"
+ dependencies:
+ chalk "^0.5.1"
+ debug "^2.1.0"
+ event-stream "^3.1.7"
+ gulp-util "^3.0.2"
+ lodash.assign "^3.0.0"
+ mini-lr "^0.1.8"
+
+gulp-match@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.0.3.tgz#91c7c0d7f29becd6606d57d80a7f8776a87aba8e"
+ dependencies:
+ minimatch "^3.0.3"
+
+gulp-replace@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-0.6.1.tgz#11bf8c8fce533e33e2f6a8f2f430b955ba0be066"
+ dependencies:
+ istextorbinary "1.0.2"
+ readable-stream "^2.0.1"
+ replacestream "^4.0.0"
+
+gulp-sass@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-3.1.0.tgz#53dc4b68a1f5ddfe4424ab4c247655269a8b74b7"
+ dependencies:
+ gulp-util "^3.0"
+ lodash.clonedeep "^4.3.2"
+ node-sass "^4.2.0"
+ through2 "^2.0.0"
+ vinyl-sourcemaps-apply "^0.2.0"
+
+gulp-sourcemaps@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c"
+ dependencies:
+ convert-source-map "^1.1.1"
+ graceful-fs "^4.1.2"
+ strip-bom "^2.0.0"
+ through2 "^2.0.0"
+ vinyl "^1.0.0"
+
+gulp-sourcemaps@^2.6.0:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz#833a4e28f0b8f4661075032cd782417f7cd8fb0b"
+ dependencies:
+ "@gulp-sourcemaps/identity-map" "1.X"
+ "@gulp-sourcemaps/map-sources" "1.X"
+ acorn "4.X"
+ convert-source-map "1.X"
+ css "2.X"
+ debug-fabulous ">=0.1.1"
+ detect-newline "2.X"
+ graceful-fs "4.X"
+ source-map "0.X"
+ strip-bom-string "1.X"
+ through2 "2.X"
+ vinyl "1.X"
+
+gulp-stylefmt@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/gulp-stylefmt/-/gulp-stylefmt-1.1.0.tgz#7aea00a0a9bd2fbd8a2482dc01f133edca303d52"
+ dependencies:
+ gulp-util "^3.0.7"
+ postcss "^5.0.21"
+ postcss-scss "^0.4.0"
+ stylefmt "^5.0.4"
+ through2 "^2.0.1"
+
+gulp-stylelint@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/gulp-stylelint/-/gulp-stylelint-4.0.0.tgz#440fa7e6c447e92644700e1e2a06a73e6e457750"
+ dependencies:
+ chalk "^2.0.1"
+ deep-extend "^0.5.0"
+ gulp-util "^3.0.8"
+ mkdirp "^0.5.1"
+ promise "^8.0.1"
+ strip-ansi "^4.0.0"
+ stylelint "^8.0.0"
+ through2 "^2.0.3"
+
+gulp-util@^3.0, gulp-util@^3.0.0, gulp-util@^3.0.2, gulp-util@^3.0.7, gulp-util@^3.0.8, gulp-util@~3.0.0:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
+ dependencies:
+ array-differ "^1.0.0"
+ array-uniq "^1.0.2"
+ beeper "^1.0.0"
+ chalk "^1.0.0"
+ dateformat "^2.0.0"
+ fancy-log "^1.1.0"
+ gulplog "^1.0.0"
+ has-gulplog "^0.1.0"
+ lodash._reescape "^3.0.0"
+ lodash._reevaluate "^3.0.0"
+ lodash._reinterpolate "^3.0.0"
+ lodash.template "^3.0.0"
+ minimist "^1.1.0"
+ multipipe "^0.1.2"
+ object-assign "^3.0.0"
+ replace-ext "0.0.1"
+ through2 "^2.0.0"
+ vinyl "^0.5.0"
+
+gulp-watch@^4.3.5:
+ version "4.3.11"
+ resolved "https://registry.yarnpkg.com/gulp-watch/-/gulp-watch-4.3.11.tgz#162fc563de9fc770e91f9a7ce3955513a9a118c0"
+ dependencies:
+ anymatch "^1.3.0"
+ chokidar "^1.6.1"
+ glob-parent "^3.0.1"
+ gulp-util "^3.0.7"
+ object-assign "^4.1.0"
+ path-is-absolute "^1.0.1"
+ readable-stream "^2.2.2"
+ slash "^1.0.0"
+ vinyl "^1.2.0"
+ vinyl-file "^2.0.0"
+
+gulp-zip@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/gulp-zip/-/gulp-zip-4.0.0.tgz#1cefc08b4bf36df4b5b1e7c6b36ee55ebbe4a881"
+ dependencies:
+ get-stream "^3.0.0"
+ gulp-util "^3.0.0"
+ through2 "^2.0.1"
+ yazl "^2.1.0"
+
+"gulp@github:gulpjs/gulp#4.0":
+ version "4.0.0-alpha.2"
+ resolved "https://codeload.github.com/gulpjs/gulp/tar.gz/6d71a658c61edb3090221579d8f97dbe086ba2ed"
+ dependencies:
+ glob-watcher "^3.0.0"
+ gulp-cli "^1.0.0"
+ undertaker "^1.0.0"
+ vinyl-fs "^2.0.0"
+
+gulplog@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5"
+ dependencies:
+ glogg "^1.0.0"
+
+handlebars@^4.0.1, handlebars@^4.0.3:
+ version "4.0.10"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f"
+ dependencies:
+ async "^1.4.0"
+ optimist "^0.6.1"
+ source-map "^0.4.4"
+ optionalDependencies:
+ uglify-js "^2.6"
+
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
+ dependencies:
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
+
+has-ansi@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e"
+ dependencies:
+ ansi-regex "^0.2.0"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-binary@0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.6.tgz#25326f39cfa4f616ad8787894e3af2cfbc7b6e10"
+ dependencies:
+ isarray "0.0.1"
+
+has-binary@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c"
+ dependencies:
+ isarray "0.0.1"
+
+has-cors@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
+
+has-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+has-flag@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
+
+has-gulplog@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce"
+ dependencies:
+ sparkles "^1.0.0"
+
+has-unicode@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+
+has@^1.0.0, has@^1.0.1, has@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
+ dependencies:
+ function-bind "^1.0.2"
+
+hash-base@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
+ dependencies:
+ inherits "^2.0.1"
+
+hash-base@^3.0.0:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+hash.js@^1.0.0, hash.js@^1.0.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846"
+ dependencies:
+ inherits "^2.0.3"
+ minimalistic-assert "^1.0.0"
+
+hat@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a"
+
+hawk@~3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
+ dependencies:
+ boom "2.x.x"
+ cryptiles "2.x.x"
+ hoek "2.x.x"
+ sntp "1.x.x"
+
+hdkey@^0.7.0:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632"
+ dependencies:
+ coinstring "^2.0.0"
+ secp256k1 "^3.0.1"
+
+he@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
+
+hmac-drbg@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+ dependencies:
+ hash.js "^1.0.3"
+ minimalistic-assert "^1.0.0"
+ minimalistic-crypto-utils "^1.0.1"
+
+hoek@2.x.x:
+ version "2.16.3"
+ resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+
+hoist-non-react-statics@^2.2.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
+
+home-or-tmp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.1"
+
+homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc"
+ dependencies:
+ parse-passwd "^1.0.0"
+
+hosted-git-info@^2.1.4:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
+
+html-encoding-sniffer@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz#79bf7a785ea495fe66165e734153f363ff5437da"
+ dependencies:
+ whatwg-encoding "^1.0.1"
+
+html-select@^2.3.5:
+ version "2.3.24"
+ resolved "https://registry.yarnpkg.com/html-select/-/html-select-2.3.24.tgz#46ad6d712e732cf31c6739d5d0110a5fabf17585"
+ dependencies:
+ cssauron "^1.1.0"
+ duplexer2 "~0.0.2"
+ inherits "^2.0.1"
+ minimist "~0.0.8"
+ readable-stream "^1.0.27-1"
+ split "~0.3.0"
+ stream-splicer "^1.2.0"
+ through2 "^1.0.0"
+
+html-tags@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
+
+html-tokenize@^1.1.1:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/html-tokenize/-/html-tokenize-1.2.5.tgz#7e5ba99ecb51ef906ec9a7fcdee6ca3267c7897e"
+ dependencies:
+ inherits "~2.0.1"
+ minimist "~0.0.8"
+ readable-stream "~1.0.27-1"
+ through2 "~0.4.1"
+
+htmlescape@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351"
+
+htmlparser2@^3.9.1:
+ version "3.9.2"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+ dependencies:
+ domelementtype "^1.3.0"
+ domhandler "^2.3.0"
+ domutils "^1.5.1"
+ entities "^1.1.1"
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+
+http-errors@1.6.2, http-errors@~1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+ dependencies:
+ depd "1.1.1"
+ inherits "2.0.3"
+ setprototypeof "1.0.3"
+ statuses ">= 1.3.1 < 2"
+
+http-errors@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942"
+ dependencies:
+ inherits "~2.0.1"
+ statuses "1"
+
+http-parser-js@>=0.4.0:
+ version "0.4.5"
+ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.5.tgz#a3ecf39a667481a38ca60882ab57a2db578b9970"
+
+http-proxy@^1.13.0, http-proxy@^1.13.1:
+ version "1.16.2"
+ resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742"
+ dependencies:
+ eventemitter3 "1.x.x"
+ requires-port "1.x.x"
+
+http-signature@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+ dependencies:
+ assert-plus "^0.2.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+https-browserify@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
+
+https-browserify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
+
+human-standard-token-abi@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/human-standard-token-abi/-/human-standard-token-abi-1.0.2.tgz#207d7846796ee5bb85fdd336e769cb38045b2ae0"
+
+i@0.3.x:
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/i/-/i-0.3.5.tgz#1d2b854158ec8169113c6cb7f6b6801e99e211d5"
+
+iconv-lite@0.4.13:
+ version "0.4.13"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
+
+iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.5, iconv-lite@~0.4.13:
+ version "0.4.19"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+
+idb-global@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/idb-global/-/idb-global-2.1.0.tgz#2a3e09d1ed9df3a836d59aeea99bf74047b8cc8d"
+ dependencies:
+ obs-store "^2.4.1"
+
+identicon.js@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/identicon.js/-/identicon.js-2.3.1.tgz#0f16a0dd5e61e1a89699400cc192af4445506e5b"
+
+idna-uts46@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/idna-uts46/-/idna-uts46-1.1.0.tgz#be098b2b7c1cabfbef87a8b80f626fac37366aea"
+ dependencies:
+ punycode "^2.1.0"
+
+ieee754@^1.1.4:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
+
+iframe-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/iframe-stream/-/iframe-stream-3.0.0.tgz#030d8913a98beeebb10f8ef67de009bc2b9266d6"
+ dependencies:
+ post-message-stream "^3.0.0"
+
+iframe@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/iframe/-/iframe-1.0.0.tgz#58e74822b178a0579d09cd169640fb9537470ef5"
+
+ignore@^3.2.0, ignore@^3.3.3:
+ version "3.3.5"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6"
+
+ignorepatterns@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/ignorepatterns/-/ignorepatterns-1.1.0.tgz#ac8f436f2239b5dfb66d5f0d3a904a87ac67cc5e"
+
+immediate@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+
+in-publish@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51"
+
+indent-string@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+ dependencies:
+ repeating "^2.0.0"
+
+indexes-of@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
+
+indexof@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.3, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inherits@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+
+ini@^1.3.4, ini@~1.3.0:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
+
+inject-css@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/inject-css/-/inject-css-0.1.1.tgz#ef3ffc78ec026c96e2355da0df32917e3526415c"
+
+inline-source-map@~0.6.0:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5"
+ dependencies:
+ source-map "~0.5.3"
+
+inquirer@^3.0.6:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.3.tgz#1c7b1731cf77b934ec47d22c9ac5aa8fe7fbe095"
+ dependencies:
+ ansi-escapes "^2.0.0"
+ chalk "^2.0.0"
+ cli-cursor "^2.1.0"
+ cli-width "^2.0.0"
+ external-editor "^2.0.4"
+ figures "^2.0.0"
+ lodash "^4.3.0"
+ mute-stream "0.0.7"
+ run-async "^2.2.0"
+ rx-lite "^4.0.8"
+ rx-lite-aggregates "^4.0.8"
+ string-width "^2.1.0"
+ strip-ansi "^4.0.0"
+ through "^2.3.6"
+
+insert-module-globals@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.1.tgz#c03bf4e01cb086d5b5e5ace8ad0afe7889d638c3"
+ dependencies:
+ JSONStream "^1.0.3"
+ combine-source-map "~0.7.1"
+ concat-stream "~1.5.1"
+ is-buffer "^1.1.0"
+ lexical-scope "^1.2.0"
+ process "~0.11.0"
+ through2 "^2.0.0"
+ xtend "^4.0.0"
+
+interpret@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
+
+invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+ dependencies:
+ loose-envify "^1.0.0"
+
+invert-kv@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+
+ipaddr.js@1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
+
+ipaddr.js@1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0"
+
+irregular-plurals@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-1.3.0.tgz#7af06931bdf74be33dcf585a13e06fccc16caecf"
+
+is-absolute@^0.2.3:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb"
+ dependencies:
+ is-relative "^0.2.1"
+ is-windows "^0.2.0"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-binary-path@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+ dependencies:
+ binary-extensions "^1.0.0"
+
+is-buffer@^1.1.0, is-buffer@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
+
+is-builtin-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+ dependencies:
+ builtin-modules "^1.0.0"
+
+is-callable@^1.1.1, is-callable@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
+
+is-date-object@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+
+is-directory@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
+
+is-dotfile@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
+
+is-equal-shallow@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+ dependencies:
+ is-primitive "^2.0.0"
+
+is-extendable@^0.1.0, is-extendable@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+
+is-extglob@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+
+is-extglob@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+
+is-finite@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fn@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c"
+
+is-fullwidth-code-point@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+
+is-function@^1.0.1, is-function@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+ dependencies:
+ is-extglob "^1.0.0"
+
+is-glob@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
+ dependencies:
+ is-extglob "^2.1.0"
+
+is-hex-prefixed@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
+
+is-number@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806"
+
+is-number@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+ dependencies:
+ kind-of "^3.0.2"
+
+is-number@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+ dependencies:
+ kind-of "^3.0.2"
+
+is-path-cwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+
+is-path-in-cwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
+ dependencies:
+ is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f"
+ dependencies:
+ path-is-inside "^1.0.1"
+
+is-plain-object@^2.0.1, is-plain-object@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ dependencies:
+ isobject "^3.0.1"
+
+is-posix-bracket@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+
+is-primitive@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+
+is-promise@^2.1, is-promise@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
+is-regex@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+ dependencies:
+ has "^1.0.1"
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+
+is-relative@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5"
+ dependencies:
+ is-unc-path "^0.1.1"
+
+is-resolvable@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
+ dependencies:
+ tryit "^1.0.1"
+
+is-stream@^1.0.1, is-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+is-subset@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6"
+
+is-supported-regexp-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8"
+
+is-symbol@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
+
+is-type@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/is-type/-/is-type-0.0.1.tgz#f651d85c365d44955d14a51d8d7061f3f6b4779c"
+ dependencies:
+ core-util-is "~1.0.0"
+
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-unc-path@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9"
+ dependencies:
+ unc-path-regex "^0.1.0"
+
+is-utf8@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+is-valid-glob@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe"
+
+is-windows@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c"
+
+isarray@0.0.1, isarray@~0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
+isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isbinaryfile@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+isobject@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+ dependencies:
+ isarray "1.0.0"
+
+isobject@^3.0.0, isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+
+isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+ dependencies:
+ node-fetch "^1.0.1"
+ whatwg-fetch ">=0.10.0"
+
+isstream@0.1.x, isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+istanbul-lib-coverage@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da"
+
+istanbul-lib-hook@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc"
+ dependencies:
+ append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.8.0.tgz#66f6c9421cc9ec4704f76f2db084ba9078a2b532"
+ dependencies:
+ babel-generator "^6.18.0"
+ babel-template "^6.16.0"
+ babel-traverse "^6.18.0"
+ babel-types "^6.18.0"
+ babylon "^6.18.0"
+ istanbul-lib-coverage "^1.1.1"
+ semver "^5.3.0"
+
+istanbul-lib-report@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9"
+ dependencies:
+ istanbul-lib-coverage "^1.1.1"
+ mkdirp "^0.5.1"
+ path-parse "^1.0.5"
+ supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c"
+ dependencies:
+ debug "^2.6.3"
+ istanbul-lib-coverage "^1.1.1"
+ mkdirp "^0.5.1"
+ rimraf "^2.6.1"
+ source-map "^0.5.3"
+
+istanbul-reports@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.2.tgz#0fb2e3f6aa9922bd3ce45d05d8ab4d5e8e07bd4f"
+ dependencies:
+ handlebars "^4.0.3"
+
+istanbul@0.4.5:
+ version "0.4.5"
+ resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b"
+ dependencies:
+ abbrev "1.0.x"
+ async "1.x"
+ escodegen "1.8.x"
+ esprima "2.7.x"
+ glob "^5.0.15"
+ handlebars "^4.0.1"
+ js-yaml "3.x"
+ mkdirp "0.5.x"
+ nopt "3.x"
+ once "1.x"
+ resolve "1.1.x"
+ supports-color "^3.1.0"
+ which "^1.1.1"
+ wordwrap "^1.0.0"
+
+istextorbinary@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-1.0.2.tgz#ace19354d1a9a0173efeb1084ce0f87b0ad7decf"
+ dependencies:
+ binaryextensions "~1.0.0"
+ textextensions "~1.0.0"
+
+jazzicon@^1.2.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/jazzicon/-/jazzicon-1.5.0.tgz#d7f36b516023db39ee6eac117f4054e937b65e99"
+ dependencies:
+ color "^0.11.1"
+ mersenne-twister "^1.0.1"
+ raphael "^2.2.0"
+
+js-base64@^2.1.8, js-base64@^2.1.9:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.1.tgz#3705897c35fce0e202132630e750d8a17cd220ec"
+
+js-beautify@~1.5.4:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.5.10.tgz#4d95371702699344a516ca26bf59f0a27bb75719"
+ dependencies:
+ config-chain "~1.1.5"
+ mkdirp "~0.5.0"
+ nopt "~3.0.1"
+
+js-sha3@0.5.5:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a"
+
+js-sha3@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243"
+
+js-sha3@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7"
+
+js-tokens@^3.0.0, js-tokens@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-yaml@3.x, js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.4.3, js-yaml@^3.6.1, js-yaml@^3.9.1:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+
+jschardet@^1.4.2:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.1.tgz#c519f629f86b3a5bedba58a88d311309eec097f9"
+
+jsdom-global@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9"
+
+jsdom@^11.1.0:
+ version "11.2.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.2.0.tgz#4f6b8736af3357c3af7227a3b54a5bda1c513fd6"
+ dependencies:
+ abab "^1.0.3"
+ acorn "^4.0.4"
+ acorn-globals "^3.1.0"
+ array-equal "^1.0.0"
+ content-type-parser "^1.0.1"
+ cssom ">= 0.3.2 < 0.4.0"
+ cssstyle ">= 0.2.37 < 0.3.0"
+ escodegen "^1.6.1"
+ html-encoding-sniffer "^1.0.1"
+ nwmatcher "^1.4.1"
+ parse5 "^3.0.2"
+ pn "^1.0.0"
+ request "^2.79.0"
+ request-promise-native "^1.0.3"
+ sax "^1.2.1"
+ symbol-tree "^3.2.1"
+ tough-cookie "^2.3.2"
+ webidl-conversions "^4.0.0"
+ whatwg-encoding "^1.0.1"
+ whatwg-url "^6.1.0"
+ xml-name-validator "^2.0.1"
+
+jsesc@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+
+jshint-stylish@~2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/jshint-stylish/-/jshint-stylish-2.2.1.tgz#242082a2c035ae03fd81044e0570cc4208cf6e61"
+ dependencies:
+ beeper "^1.1.0"
+ chalk "^1.0.0"
+ log-symbols "^1.0.0"
+ plur "^2.1.0"
+ string-length "^1.0.0"
+ text-table "^0.2.0"
+
+json-loader@^0.5.4:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
+
+json-rpc-engine@^3.0.1, json-rpc-engine@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.1.0.tgz#09285363372857569d75f61df6591b1b0afb0758"
+ dependencies:
+ async "^2.0.1"
+ babel-preset-env "^1.3.2"
+ babelify "^7.3.0"
+
+json-rpc-engine@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.2.0.tgz#d34dff106c8339c337a894da801f73b1f77b1bc8"
+ dependencies:
+ async "^2.0.1"
+ babel-preset-env "^1.3.2"
+ babelify "^7.3.0"
+ json-rpc-error "^2.0.0"
+
+json-rpc-error@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02"
+ dependencies:
+ inherits "^2.0.1"
+
+json-rpc-middleware-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-rpc-middleware-stream/-/json-rpc-middleware-stream-1.0.0.tgz#84d0faefe123ce9cfc7a9753e6e5236b9a104522"
+ dependencies:
+ eth-block-tracker "^2.1.2"
+ ethjs-query "^0.2.9"
+ json-rpc-engine "^3.0.1"
+ readable-stream "^2.3.3"
+
+json-rpc-middleware-stream@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-rpc-middleware-stream/-/json-rpc-middleware-stream-1.0.1.tgz#c9b8a005c80af32e6df8bb88e6bdd1300484a4ed"
+ dependencies:
+ end-of-stream "^1.4.0"
+ eth-block-tracker "^2.1.2"
+ ethjs-query "^0.2.9"
+ json-rpc-engine "^3.0.1"
+ readable-stream "^2.3.3"
+
+json-rpc-random-id@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8"
+
+json-schema-traverse@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
+
+json-schema@0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+ dependencies:
+ jsonify "~0.0.0"
+
+json-stable-stringify@~0.0.0:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45"
+ dependencies:
+ jsonify "~0.0.0"
+
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+json3@3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
+
+json5@^0.5.0, json5@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+
+jsonfile@^2.1.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonfilter@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/jsonfilter/-/jsonfilter-1.1.2.tgz#21ef7cedc75193813c75932e96a98be205ba5a11"
+ dependencies:
+ JSONStream "^0.8.4"
+ minimist "^1.1.0"
+ stream-combiner "^0.2.1"
+ through2 "^0.6.3"
+
+jsonify@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsonparse@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64"
+
+jsonparse@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
+
+jsprim@^1.2.2:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
+ json-schema "0.2.3"
+ verror "1.10.0"
+
+jstransform@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-10.1.0.tgz#b4c49bf63f162c108b0348399a8737c713b0a83a"
+ dependencies:
+ base62 "0.1.1"
+ esprima-fb "13001.1001.0-dev-harmony-fb"
+ source-map "0.1.31"
+
+just-extend@^1.1.22:
+ version "1.1.22"
+ resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.22.tgz#3330af756cab6a542700c64b2e4e4aa062d52fff"
+
+karma-chrome-launcher@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
+ dependencies:
+ fs-access "^1.0.0"
+ which "^1.2.1"
+
+karma-cli@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-1.0.1.tgz#ae6c3c58a313a1d00b45164c455b9b86ce17f960"
+ dependencies:
+ resolve "^1.1.6"
+
+karma-firefox-launcher@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-1.0.1.tgz#ce58f47c2013a88156d55a5d61337c099cf5bb51"
+
+karma-qunit@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/karma-qunit/-/karma-qunit-1.2.1.tgz#88252afd2127bc03b0cc31978ed6882b139f470a"
+
+karma@^1.7.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/karma/-/karma-1.7.1.tgz#85cc08e9e0a22d7ce9cca37c4a1be824f6a2b1ae"
+ dependencies:
+ bluebird "^3.3.0"
+ body-parser "^1.16.1"
+ chokidar "^1.4.1"
+ colors "^1.1.0"
+ combine-lists "^1.0.0"
+ connect "^3.6.0"
+ core-js "^2.2.0"
+ di "^0.0.1"
+ dom-serialize "^2.2.0"
+ expand-braces "^0.1.1"
+ glob "^7.1.1"
+ graceful-fs "^4.1.2"
+ http-proxy "^1.13.0"
+ isbinaryfile "^3.0.0"
+ lodash "^3.8.0"
+ log4js "^0.6.31"
+ mime "^1.3.4"
+ minimatch "^3.0.2"
+ optimist "^0.6.1"
+ qjobs "^1.1.4"
+ range-parser "^1.2.0"
+ rimraf "^2.6.0"
+ safe-buffer "^5.0.1"
+ socket.io "1.7.3"
+ source-map "^0.5.3"
+ tmp "0.0.31"
+ useragent "^2.1.12"
+
+keccak@^1.0.2:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.3.0.tgz#3681bd99ad3d0354ddb29b9040c1b6560cce08ac"
+ dependencies:
+ bindings "^1.2.1"
+ inherits "^2.0.3"
+ nan "^2.2.1"
+ prebuild-install "^2.0.0"
+ safe-buffer "^5.1.0"
+
+keccakjs@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d"
+ dependencies:
+ browserify-sha3 "^0.0.1"
+ sha3 "^1.1.0"
+
+kind-of@^3.0.2, kind-of@^3.1.0:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+ dependencies:
+ is-buffer "^1.1.5"
+
+kind-of@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+ dependencies:
+ is-buffer "^1.1.5"
+
+klaw@^1.0.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
+ optionalDependencies:
+ graceful-fs "^4.1.9"
+
+known-css-properties@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.2.0.tgz#899c94be368e55b42d7db8d5be7d73a4a4a41454"
+
+known-css-properties@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.3.0.tgz#a3d135bbfc60ee8c6eacf2f7e7e6f2d4755e49a4"
+
+labeled-stream-splicer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59"
+ dependencies:
+ inherits "^2.0.1"
+ isarray "~0.0.1"
+ stream-splicer "^2.0.0"
+
+last-run@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b"
+ dependencies:
+ default-resolution "^2.0.0"
+ es6-weak-map "^2.0.1"
+
+lazy-cache@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+
+lazystream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
+ dependencies:
+ readable-stream "^2.0.5"
+
+lcid@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+ dependencies:
+ invert-kv "^1.0.0"
+
+lcov-parse@^0.0.10:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3"
+
+ldjson-stream@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ldjson-stream/-/ldjson-stream-1.2.1.tgz#91beceda5ac4ed2b17e649fb777e7abfa0189c2b"
+ dependencies:
+ split2 "^0.2.1"
+ through2 "^0.6.1"
+
+leftpad@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/leftpad/-/leftpad-0.0.0.tgz#020c9ad0787216ba0f30d79d479b4b355d7d39c3"
+
+level-codec@~7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7"
+
+level-errors@^1.0.3:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.1.tgz#52fdc2dbbaf395cf767db843929a38b7015678d2"
+ dependencies:
+ errno "~0.1.1"
+
+level-errors@~1.0.3:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859"
+ dependencies:
+ errno "~0.1.1"
+
+level-iterator-stream@~1.3.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed"
+ dependencies:
+ inherits "^2.0.1"
+ level-errors "^1.0.3"
+ readable-stream "^1.0.33"
+ xtend "^4.0.0"
+
+level-ws@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b"
+ dependencies:
+ readable-stream "~1.0.15"
+ xtend "~2.1.1"
+
+levelup@^1.2.1:
+ version "1.3.9"
+ resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab"
+ dependencies:
+ deferred-leveldown "~1.2.1"
+ level-codec "~7.0.0"
+ level-errors "~1.0.3"
+ level-iterator-stream "~1.3.0"
+ prr "~1.0.1"
+ semver "~5.4.1"
+ xtend "~4.0.0"
+
+levn@^0.3.0, levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+lexical-scope@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/lexical-scope/-/lexical-scope-1.2.0.tgz#fcea5edc704a4b3a8796cdca419c3a0afaf22df4"
+ dependencies:
+ astw "^2.0.0"
+
+liftoff@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385"
+ dependencies:
+ extend "^3.0.0"
+ findup-sync "^0.4.2"
+ fined "^1.0.1"
+ flagged-respawn "^0.3.2"
+ lodash.isplainobject "^4.0.4"
+ lodash.isstring "^4.0.1"
+ lodash.mapvalues "^4.4.0"
+ rechoir "^0.6.2"
+ resolve "^1.1.7"
+
+livereload-js@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.2.2.tgz#6c87257e648ab475bc24ea257457edcc1f8d0bc2"
+
+load-json-file@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^2.2.0"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+
+load-json-file@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^2.2.0"
+ pify "^2.0.0"
+ strip-bom "^3.0.0"
+
+loader-runner@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
+
+loader-utils@^0.2.16:
+ version "0.2.17"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+ dependencies:
+ big.js "^3.1.3"
+ emojis-list "^2.0.0"
+ json5 "^0.5.0"
+ object-assign "^4.0.1"
+
+locate-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ dependencies:
+ p-locate "^2.0.0"
+ path-exists "^3.0.0"
+
+lodash-es@^4.2.0, lodash-es@^4.2.1:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
+
+lodash._baseassign@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
+ dependencies:
+ lodash._basecopy "^3.0.0"
+ lodash.keys "^3.0.0"
+
+lodash._basecopy@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
+
+lodash._basecreate@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
+
+lodash._baseflatten@^3.0.0:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz#0770ff80131af6e34f3b511796a7ba5214e65ff7"
+ dependencies:
+ lodash.isarguments "^3.0.0"
+ lodash.isarray "^3.0.0"
+
+lodash._basetostring@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5"
+
+lodash._basevalues@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7"
+
+lodash._bindcallback@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
+
+lodash._createassigner@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11"
+ dependencies:
+ lodash._bindcallback "^3.0.0"
+ lodash._isiterateecall "^3.0.0"
+ lodash.restparam "^3.0.0"
+
+lodash._getnative@^3.0.0:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
+
+lodash._isiterateecall@^3.0.0:
+ version "3.0.9"
+ resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
+
+lodash._reescape@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a"
+
+lodash._reevaluate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed"
+
+lodash._reinterpolate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
+
+lodash._root@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
+
+lodash.assign@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa"
+ dependencies:
+ lodash._baseassign "^3.0.0"
+ lodash._createassigner "^3.0.0"
+ lodash.keys "^3.0.0"
+
+lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
+
+lodash.assignin@^4.0.9, lodash.assignin@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2"
+
+lodash.bind@^4.1.4:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35"
+
+lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.4.1:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+
+lodash.create@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
+ dependencies:
+ lodash._baseassign "^3.0.0"
+ lodash._basecreate "^3.0.0"
+ lodash._isiterateecall "^3.0.0"
+
+lodash.debounce@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5"
+ dependencies:
+ lodash._getnative "^3.0.0"
+
+lodash.debounce@^4.0.6:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+
+lodash.defaults@^4.0.1:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+
+lodash.escape@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698"
+ dependencies:
+ lodash._root "^3.0.0"
+
+lodash.filter@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace"
+
+lodash.find@^4.5.1:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1"
+
+lodash.flatmap@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e"
+
+lodash.flatten@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-3.0.2.tgz#de1cf57758f8f4479319d35c3e9cc60c4501938c"
+ dependencies:
+ lodash._baseflatten "^3.0.0"
+ lodash._isiterateecall "^3.0.0"
+
+lodash.flatten@^4.2.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+
+lodash.foreach@^4.3.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
+
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+
+lodash.isarguments@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
+
+lodash.isarray@^3.0.0:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
+
+lodash.isequal@^4.0.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
+
+lodash.isfunction@^3.0.8:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.8.tgz#4db709fc81bc4a8fd7127a458a5346c5cdce2c6b"
+
+lodash.isplainobject@^4.0.4, lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+
+lodash.isstring@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+
+lodash.keys@^3.0.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
+ dependencies:
+ lodash._getnative "^3.0.0"
+ lodash.isarguments "^3.0.0"
+ lodash.isarray "^3.0.0"
+
+lodash.map@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
+
+lodash.mapvalues@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c"
+
+lodash.memoize@~3.0.3:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f"
+
+lodash.merge@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5"
+
+lodash.mergewith@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
+
+lodash.pick@^4.2.1:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
+
+lodash.reduce@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b"
+
+lodash.reject@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415"
+
+lodash.restparam@^3.0.0:
+ version "3.6.1"
+ resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
+
+lodash.some@^4.4.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
+
+lodash.sortby@^4.5.0, lodash.sortby@^4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+
+lodash.template@^3.0.0:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f"
+ dependencies:
+ lodash._basecopy "^3.0.0"
+ lodash._basetostring "^3.0.0"
+ lodash._basevalues "^3.0.0"
+ lodash._isiterateecall "^3.0.0"
+ lodash._reinterpolate "^3.0.0"
+ lodash.escape "^3.0.0"
+ lodash.keys "^3.0.0"
+ lodash.restparam "^3.0.0"
+ lodash.templatesettings "^3.0.0"
+
+lodash.templatesettings@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5"
+ dependencies:
+ lodash._reinterpolate "^3.0.0"
+ lodash.escape "^3.0.0"
+
+lodash.uniqby@^4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302"
+
+lodash@^3.8.0:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
+
+lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@~4.17.2, lodash@~4.17.4:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+log-driver@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056"
+
+log-symbols@^1.0.0, log-symbols@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
+ dependencies:
+ chalk "^1.0.0"
+
+log-symbols@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.0.0.tgz#595e63be4d5c8cbf294a9e09e0d5629f5913fc0c"
+ dependencies:
+ chalk "^2.0.1"
+
+log4js@^0.6.31:
+ version "0.6.38"
+ resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd"
+ dependencies:
+ readable-stream "~1.0.2"
+ semver "~4.3.3"
+
+loglevel@^1.4.1, loglevel@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.5.0.tgz#3863984a2c326b986fbb965f378758a6dc8a4324"
+
+lolex@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
+
+lolex@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.1.2.tgz#2694b953c9ea4d013e5b8bfba891c991025b2629"
+
+longest@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
+ dependencies:
+ js-tokens "^3.0.0"
+
+loud-rejection@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+ dependencies:
+ currently-unhandled "^0.4.1"
+ signal-exit "^3.0.0"
+
+lru-cache@2.2.x:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
+
+lru-cache@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee"
+ dependencies:
+ pseudomap "^1.0.1"
+
+lru-cache@^4.0.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
+ dependencies:
+ pseudomap "^1.0.2"
+ yallist "^2.1.2"
+
+lru-queue@0.1:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
+ dependencies:
+ es5-ext "~0.10.2"
+
+ltgt@~2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.0.tgz#b65ba5fcb349a29924c8e333f7c6a5562f2e4842"
+
+make-iterator@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.0.tgz#57bef5dc85d23923ba23767324d8e8f8f3d9694b"
+ dependencies:
+ kind-of "^3.1.0"
+
+map-async@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/map-async/-/map-async-0.1.1.tgz#c897c0449f85864c74b5a3f196edb42156431745"
+
+map-cache@^0.2.0:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+
+map-stream@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
+
+matchdep@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-1.0.1.tgz#a57a33804491fbae208aba8f68380437abc2dca5"
+ dependencies:
+ findup-sync "~0.3.0"
+ micromatch "^2.3.7"
+ resolve "~1.1.6"
+ stack-trace "0.0.9"
+
+mathml-tag-names@^2.0.0, mathml-tag-names@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz#8d41268168bf86d1102b98109e28e531e7a34578"
+
+md5-hex@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4"
+ dependencies:
+ md5-o-matic "^0.1.1"
+
+md5-o-matic@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3"
+
+md5.js@^1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
+ dependencies:
+ hash-base "^3.0.0"
+ inherits "^2.0.1"
+
+"mdurl@~ 1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+
+mem@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
+ dependencies:
+ mimic-fn "^1.0.0"
+
+memdown@^1.0.0:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.2.7.tgz#64f2d6b511724c016f3cbd5a40b84349da247b0f"
+ dependencies:
+ abstract-leveldown "2.6.3"
+ functional-red-black-tree "^1.0.1"
+ immediate "^3.2.3"
+ inherits "~2.0.1"
+ ltgt "~2.2.0"
+
+memoizee@^0.4.5:
+ version "0.4.11"
+ resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.11.tgz#bde9817663c9e40fdb2a4ea1c367296087ae8c8f"
+ dependencies:
+ d "1"
+ es5-ext "^0.10.30"
+ es6-weak-map "^2.0.2"
+ event-emitter "^0.3.5"
+ is-promise "^2.1"
+ lru-queue "0.1"
+ next-tick "1"
+ timers-ext "^0.1.2"
+
+memory-fs@^0.4.0, memory-fs@~0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
+ dependencies:
+ errno "^0.1.3"
+ readable-stream "^2.0.1"
+
+memorystream@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
+
+meow@^3.3.0, meow@^3.7.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+ dependencies:
+ camelcase-keys "^2.0.0"
+ decamelize "^1.1.2"
+ loud-rejection "^1.0.0"
+ map-obj "^1.0.1"
+ minimist "^1.1.3"
+ normalize-package-data "^2.3.4"
+ object-assign "^4.0.1"
+ read-pkg-up "^1.0.1"
+ redent "^1.0.0"
+ trim-newlines "^1.0.0"
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+
+merge-source-map@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f"
+ dependencies:
+ source-map "^0.5.6"
+
+merge-stream@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
+ dependencies:
+ readable-stream "^2.0.1"
+
+merkle-patricia-tree@^2.1.2:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.2.0.tgz#7a4787b1262ab00fe9b204ab471b005332306efa"
+ dependencies:
+ async "^1.4.2"
+ ethereumjs-util "^4.0.0"
+ level-ws "0.0.0"
+ levelup "^1.2.1"
+ memdown "^1.0.0"
+ readable-stream "^2.0.0"
+ rlp "^2.0.0"
+ semaphore ">=1.0.1"
+
+mersenne-twister@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a"
+
+metamascara@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/metamascara/-/metamascara-1.3.1.tgz#a84d6f20ef4ba401ce44eba120857ee1d680747b"
+ dependencies:
+ iframe "^1.0.0"
+ iframe-stream "^3.0.0"
+ json-rpc-engine "^3.1.0"
+ json-rpc-middleware-stream "^1.0.0"
+ obj-multiplex "^1.0.0"
+ obs-store "^2.4.1"
+ pump "^1.0.2"
+
+metamask-logo@^2.1.2:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/metamask-logo/-/metamask-logo-2.1.3.tgz#175ce57ae50c7344b3b1dc32d2fd0b08e3978fd0"
+ dependencies:
+ gl-mat4 "1.1.4"
+ gl-vec3 "1.0.3"
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+
+micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7:
+ version "2.3.11"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+ dependencies:
+ arr-diff "^2.0.0"
+ array-unique "^0.2.1"
+ braces "^1.8.2"
+ expand-brackets "^0.1.4"
+ extglob "^0.3.1"
+ filename-regex "^2.0.0"
+ is-extglob "^1.0.0"
+ is-glob "^2.0.1"
+ kind-of "^3.0.2"
+ normalize-path "^2.0.1"
+ object.omit "^2.0.0"
+ parse-glob "^3.0.4"
+ regex-cache "^0.4.2"
+
+miller-rabin@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.0.tgz#4a62fb1d42933c05583982f4c716f6fb9e6c6d3d"
+ dependencies:
+ bn.js "^4.0.0"
+ brorand "^1.0.1"
+
+mime-db@~1.30.0:
+ version "1.30.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
+
+mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7:
+ version "2.1.17"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
+ dependencies:
+ mime-db "~1.30.0"
+
+mime@1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
+
+mime@1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+
+mime@^1.3.4:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.0.tgz#69e9e0db51d44f2a3b56e48b7817d7d137f1a343"
+
+mime@~1.2.9:
+ version "1.2.11"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10"
+
+mimic-fn@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
+
+min-document@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
+ dependencies:
+ dom-walk "^0.1.0"
+
+mini-lr@^0.1.8:
+ version "0.1.9"
+ resolved "https://registry.yarnpkg.com/mini-lr/-/mini-lr-0.1.9.tgz#02199d27347953d1fd1d6dbded4261f187b2d0f6"
+ dependencies:
+ body-parser "~1.14.0"
+ debug "^2.2.0"
+ faye-websocket "~0.7.2"
+ livereload-js "^2.2.0"
+ parseurl "~1.3.0"
+ qs "~2.2.3"
+
+minimalistic-assert@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
+
+minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+
+"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.5.tgz#d7aa327bcecf518f9106ac6b8f003fa3bcea8566"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de"
+
+minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+minimist@~0.0.1, minimist@~0.0.8:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+
+mississippi@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5"
+ dependencies:
+ concat-stream "^1.5.0"
+ duplexify "^3.4.2"
+ end-of-stream "^1.1.0"
+ flush-write-stream "^1.0.0"
+ from2 "^2.1.0"
+ parallel-transform "^1.1.0"
+ pump "^1.0.0"
+ pumpify "^1.3.3"
+ stream-each "^1.1.0"
+ through2 "^2.0.0"
+
+mkdirp@0.0.x:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.0.7.tgz#d89b4f0e4c3e5e5ca54235931675e094fe1a5072"
+
+mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ dependencies:
+ minimist "0.0.8"
+
+mocha-eslint@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/mocha-eslint/-/mocha-eslint-4.1.0.tgz#d08eba98665f7ce4ebef0d27c3a235409ebbb8ad"
+ dependencies:
+ chalk "^1.1.0"
+ eslint "^4.2.0"
+ glob-all "^3.0.1"
+ replaceall "^0.1.6"
+
+mocha-jsdom@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mocha-jsdom/-/mocha-jsdom-1.1.0.tgz#e1576fbd0601cc89d358a213a0e5585d1b7c7a01"
+
+mocha-sinon@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/mocha-sinon/-/mocha-sinon-2.0.0.tgz#723a9310e7d737d7b77c7a66821237425b032d48"
+
+mocha@^3.2.0:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d"
+ dependencies:
+ browser-stdout "1.3.0"
+ commander "2.9.0"
+ debug "2.6.8"
+ diff "3.2.0"
+ escape-string-regexp "1.0.5"
+ glob "7.1.1"
+ growl "1.9.2"
+ he "1.1.1"
+ json3 "3.3.2"
+ lodash.create "3.1.1"
+ mkdirp "0.5.1"
+ supports-color "3.1.2"
+
+mocha@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.0.1.tgz#0aee5a95cf69a4618820f5e51fa31717117daf1b"
+ dependencies:
+ browser-stdout "1.3.0"
+ commander "2.11.0"
+ debug "3.1.0"
+ diff "3.3.1"
+ escape-string-regexp "1.0.5"
+ glob "7.1.2"
+ growl "1.10.3"
+ he "1.1.1"
+ mkdirp "0.5.1"
+ supports-color "4.4.0"
+
+module-deps@^4.0.8:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd"
+ dependencies:
+ JSONStream "^1.0.3"
+ browser-resolve "^1.7.0"
+ cached-path-relative "^1.0.0"
+ concat-stream "~1.5.0"
+ defined "^1.0.0"
+ detective "^4.0.0"
+ duplexer2 "^0.1.2"
+ inherits "^2.0.1"
+ parents "^1.0.0"
+ readable-stream "^2.0.2"
+ resolve "^1.1.3"
+ stream-combiner2 "^1.1.1"
+ subarg "^1.0.0"
+ through2 "^2.0.0"
+ xtend "^4.0.0"
+
+ms@0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
+
+ms@0.7.2:
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+multimatch@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
+ dependencies:
+ array-differ "^1.0.0"
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ minimatch "^3.0.0"
+
+multipipe@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b"
+ dependencies:
+ duplexer2 "0.0.2"
+
+multiplex@^6.7.0:
+ version "6.7.0"
+ resolved "https://registry.yarnpkg.com/multiplex/-/multiplex-6.7.0.tgz#ff73e4e40079170c4442d160965658f8def960c2"
+ dependencies:
+ duplexify "^3.4.2"
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+ varint "^4.0.0"
+ xtend "^4.0.0"
+
+mustache@^2.2.1:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0"
+
+mute-stdout@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.0.tgz#5b32ea07eb43c9ded6130434cf926f46b2a7fd4d"
+
+mute-stream@0.0.7, mute-stream@~0.0.4:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+
+mz@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.6.0.tgz#c8b8521d958df0a4f2768025db69c719ee4ef1ce"
+ dependencies:
+ any-promise "^1.0.0"
+ object-assign "^4.0.1"
+ thenify-all "^1.0.0"
+
+nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.2:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46"
+
+native-promise-only@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
+ncp@1.0.x:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246"
+
+negotiator@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+
+next-tick@1:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
+
+nise@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/nise/-/nise-1.1.0.tgz#37e41b9bf0041ccb83d1bf03e79440bbc0db10ad"
+ dependencies:
+ formatio "^1.2.0"
+ just-extend "^1.1.22"
+ lolex "^1.6.0"
+ path-to-regexp "^1.7.0"
+ text-encoding "^0.6.4"
+
+nock@^9.0.14:
+ version "9.0.14"
+ resolved "https://registry.yarnpkg.com/nock/-/nock-9.0.14.tgz#2211550253173ce298bcd89fca825e83813ca72b"
+ dependencies:
+ chai ">=1.9.2 <4.0.0"
+ debug "^2.2.0"
+ deep-equal "^1.0.0"
+ json-stringify-safe "^5.0.1"
+ lodash "~4.17.2"
+ mkdirp "^0.5.0"
+ propagate "0.4.0"
+ qs "^6.0.2"
+ semver "^5.3.0"
+
+node-abi@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.1.1.tgz#c9cda256ec8aa99bcab2f6446db38af143338b2a"
+
+node-fetch@^1.0.1, node-fetch@~1.7.1:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
+ dependencies:
+ encoding "^0.1.11"
+ is-stream "^1.0.1"
+
+node-gyp@^3.3.1:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60"
+ dependencies:
+ fstream "^1.0.0"
+ glob "^7.0.3"
+ graceful-fs "^4.1.2"
+ minimatch "^3.0.2"
+ mkdirp "^0.5.0"
+ nopt "2 || 3"
+ npmlog "0 || 1 || 2 || 3 || 4"
+ osenv "0"
+ request "2"
+ rimraf "2"
+ semver "~5.3.0"
+ tar "^2.0.0"
+ which "1"
+
+node-libs-browser@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646"
+ dependencies:
+ assert "^1.1.1"
+ browserify-zlib "^0.1.4"
+ buffer "^4.3.0"
+ console-browserify "^1.1.0"
+ constants-browserify "^1.0.0"
+ crypto-browserify "^3.11.0"
+ domain-browser "^1.1.1"
+ events "^1.0.0"
+ https-browserify "0.0.1"
+ os-browserify "^0.2.0"
+ path-browserify "0.0.0"
+ process "^0.11.0"
+ punycode "^1.2.4"
+ querystring-es3 "^0.2.0"
+ readable-stream "^2.0.5"
+ stream-browserify "^2.0.1"
+ stream-http "^2.3.1"
+ string_decoder "^0.10.25"
+ timers-browserify "^2.0.2"
+ tty-browserify "0.0.0"
+ url "^0.11.0"
+ util "^0.10.3"
+ vm-browserify "0.0.4"
+
+node-notifier@^5.0.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff"
+ dependencies:
+ growly "^1.3.0"
+ semver "^5.3.0"
+ shellwords "^0.1.0"
+ which "^1.2.12"
+
+node-pre-gyp@^0.6.36:
+ version "0.6.37"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.37.tgz#3c872b236b2e266e4140578fe1ee88f693323a05"
+ dependencies:
+ mkdirp "^0.5.1"
+ nopt "^4.0.1"
+ npmlog "^4.0.2"
+ rc "^1.1.7"
+ request "^2.81.0"
+ rimraf "^2.6.1"
+ semver "^5.3.0"
+ tape "^4.6.3"
+ tar "^2.2.1"
+ tar-pack "^3.4.0"
+
+node-sass@^4.2.0:
+ version "4.5.3"
+ resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568"
+ dependencies:
+ async-foreach "^0.1.3"
+ chalk "^1.1.1"
+ cross-spawn "^3.0.0"
+ gaze "^1.0.0"
+ get-stdin "^4.0.1"
+ glob "^7.0.3"
+ in-publish "^2.0.0"
+ lodash.assign "^4.2.0"
+ lodash.clonedeep "^4.3.2"
+ lodash.mergewith "^4.6.0"
+ meow "^3.7.0"
+ mkdirp "^0.5.1"
+ nan "^2.3.2"
+ node-gyp "^3.3.1"
+ npmlog "^4.0.0"
+ request "^2.79.0"
+ sass-graph "^2.1.1"
+ stdout-stream "^1.4.0"
+
+noop-logger@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
+
+"nopt@2 || 3", nopt@3.x, nopt@~3.0.1:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ dependencies:
+ abbrev "1"
+
+nopt@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+ dependencies:
+ abbrev "1"
+ osenv "^0.1.4"
+
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+ dependencies:
+ hosted-git-info "^2.1.4"
+ is-builtin-module "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+ dependencies:
+ remove-trailing-separator "^1.0.1"
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+
+normalize-selector@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03"
+
+now-and-later@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee"
+ dependencies:
+ once "^1.3.2"
+
+npm-run-path@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+ dependencies:
+ path-key "^2.0.0"
+
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.1, npmlog@^4.0.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+ dependencies:
+ are-we-there-yet "~1.1.2"
+ console-control-strings "~1.1.0"
+ gauge "~2.7.3"
+ set-blocking "~2.0.0"
+
+nth-check@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
+ dependencies:
+ boolbase "~1.0.0"
+
+null-check@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
+
+num2fraction@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+
+number-is-nan@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+number-to-bn@1.7.0, number-to-bn@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0"
+ dependencies:
+ bn.js "4.11.6"
+ strip-hex-prefix "1.0.0"
+
+nwmatcher@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f"
+
+nyc@^11.0.3:
+ version "11.2.1"
+ resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.2.1.tgz#ad850afe9dbad7f4970728b4b2e47fed1c38721c"
+ dependencies:
+ archy "^1.0.0"
+ arrify "^1.0.1"
+ caching-transform "^1.0.0"
+ convert-source-map "^1.3.0"
+ debug-log "^1.0.1"
+ default-require-extensions "^1.0.0"
+ find-cache-dir "^0.1.1"
+ find-up "^2.1.0"
+ foreground-child "^1.5.3"
+ glob "^7.0.6"
+ istanbul-lib-coverage "^1.1.1"
+ istanbul-lib-hook "^1.0.7"
+ istanbul-lib-instrument "^1.8.0"
+ istanbul-lib-report "^1.1.1"
+ istanbul-lib-source-maps "^1.2.1"
+ istanbul-reports "^1.1.1"
+ md5-hex "^1.2.0"
+ merge-source-map "^1.0.2"
+ micromatch "^2.3.11"
+ mkdirp "^0.5.0"
+ resolve-from "^2.0.0"
+ rimraf "^2.5.4"
+ signal-exit "^3.0.1"
+ spawn-wrap "^1.3.8"
+ test-exclude "^4.1.1"
+ yargs "^8.0.1"
+ yargs-parser "^5.0.0"
+
+oauth-sign@~0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+
+obj-multiplex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/obj-multiplex/-/obj-multiplex-1.0.0.tgz#2f2ae6bfd4ae11befe742ea9ea5b36636eabffc1"
+ dependencies:
+ end-of-stream "^1.4.0"
+ once "^1.4.0"
+ readable-stream "^2.3.3"
+
+object-assign@3.0.0, object-assign@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
+
+object-assign@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
+
+object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+
+object-component@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
+
+object-inspect@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-0.4.0.tgz#f5157c116c1455b243b06ee97703392c5ad89fec"
+
+object-inspect@~1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.3.0.tgz#5b1eb8e6742e2ee83342a637034d844928ba2f6d"
+
+object-is@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6"
+
+object-keys@^1.0.10, object-keys@^1.0.6, object-keys@^1.0.8:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
+
+object-keys@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
+
+object.assign@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.0.4.tgz#b1c9cc044ef1b9fe63606fc141abbb32e14730cc"
+ dependencies:
+ define-properties "^1.1.2"
+ function-bind "^1.1.0"
+ object-keys "^1.0.10"
+
+object.defaults@^1.0.0, object.defaults@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
+ dependencies:
+ array-each "^1.0.1"
+ array-slice "^1.0.0"
+ for-own "^1.0.0"
+ isobject "^3.0.0"
+
+object.entries@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f"
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.6.1"
+ function-bind "^1.1.0"
+ has "^1.0.1"
+
+object.omit@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+ dependencies:
+ for-own "^0.1.4"
+ is-extendable "^0.1.1"
+
+object.pick@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
+ dependencies:
+ isobject "^3.0.1"
+
+object.reduce@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad"
+ dependencies:
+ for-own "^1.0.0"
+ make-iterator "^1.0.0"
+
+object.values@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a"
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.6.1"
+ function-bind "^1.1.0"
+ has "^1.0.1"
+
+obs-store@^2.3.1, obs-store@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/obs-store/-/obs-store-2.4.1.tgz#5425b85dabaf08d913464000ba65aaf25296492f"
+ dependencies:
+ babel-preset-es2015 "^6.22.0"
+ babelify "^7.3.0"
+ readable-stream "^2.2.2"
+ through2 "^2.0.3"
+ xtend "^4.0.1"
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ dependencies:
+ ee-first "1.1.1"
+
+once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ dependencies:
+ wrappy "1"
+
+onecolor@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.0.4.tgz#75a46f80da6c7aaa5b4daae17a47198bd9652494"
+
+onetime@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+ dependencies:
+ mimic-fn "^1.0.0"
+
+open@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/open/-/open-0.0.3.tgz#fa377f4ff308212d92a9b8e6395240854646a713"
+
+open@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc"
+
+opener@^1.3.0:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
+
+optimist@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+ dependencies:
+ minimist "~0.0.1"
+ wordwrap "~0.0.2"
+
+optionator@^0.8.1, optionator@^0.8.2:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.4"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ wordwrap "~1.0.0"
+
+options@>=0.0.5:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
+
+ordered-read-streams@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b"
+ dependencies:
+ is-stream "^1.0.1"
+ readable-stream "^2.0.1"
+
+os-browserify@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f"
+
+os-browserify@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54"
+
+os-homedir@^1.0.0, os-homedir@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
+os-locale@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+ dependencies:
+ lcid "^1.0.0"
+
+os-locale@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
+ dependencies:
+ execa "^0.7.0"
+ lcid "^1.0.0"
+ mem "^1.1.0"
+
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+osenv@0, osenv@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+outpipe@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/outpipe/-/outpipe-1.1.1.tgz#50cf8616365e87e031e29a5ec9339a3da4725fa2"
+ dependencies:
+ shell-quote "^1.4.2"
+
+p-finally@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+
+p-limit@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
+
+p-locate@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ dependencies:
+ p-limit "^1.1.0"
+
+p-map@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a"
+
+pako@~0.2.0:
+ version "0.2.9"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
+
+parallel-transform@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
+ dependencies:
+ cyclist "~0.2.2"
+ inherits "^2.0.3"
+ readable-stream "^2.1.5"
+
+parents@^1.0.0, parents@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751"
+ dependencies:
+ path-platform "~0.11.15"
+
+parse-asn1@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
+ dependencies:
+ asn1.js "^4.0.0"
+ browserify-aes "^1.0.0"
+ create-hash "^1.1.0"
+ evp_bytestokey "^1.0.0"
+ pbkdf2 "^3.0.3"
+
+parse-filepath@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73"
+ dependencies:
+ is-absolute "^0.2.3"
+ map-cache "^0.2.0"
+ path-root "^0.1.1"
+
+parse-glob@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+ dependencies:
+ glob-base "^0.3.0"
+ is-dotfile "^1.0.0"
+ is-extglob "^1.0.0"
+ is-glob "^2.0.0"
+
+parse-headers@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536"
+ dependencies:
+ for-each "^0.3.2"
+ trim "0.0.1"
+
+parse-json@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+ dependencies:
+ error-ex "^1.2.0"
+
+parse-passwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
+
+parse5@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.2.tgz#05eff57f0ef4577fb144a79f8b9a967a6cc44510"
+ dependencies:
+ "@types/node" "^6.0.46"
+
+parsejson@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab"
+ dependencies:
+ better-assert "~1.0.0"
+
+parseqs@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
+ dependencies:
+ better-assert "~1.0.0"
+
+parseuri@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
+ dependencies:
+ better-assert "~1.0.0"
+
+parseurl@~1.3.0, parseurl@~1.3.1, parseurl@~1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+
+pascalcase@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
+
+path-browserify@0.0.0, path-browserify@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
+
+path-dirname@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
+
+path-exists@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+ dependencies:
+ pinkie-promise "^2.0.0"
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+
+path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-is-inside@^1.0.1, path-is-inside@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+
+path-key@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+
+path-parse@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+
+path-platform@~0.11.15:
+ version "0.11.15"
+ resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2"
+
+path-root-regex@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d"
+
+path-root@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7"
+ dependencies:
+ path-root-regex "^0.1.0"
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+
+path-to-regexp@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
+ dependencies:
+ isarray "0.0.1"
+
+path-type@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+path-type@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
+ dependencies:
+ pify "^2.0.0"
+
+pathval@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
+
+pause-stream@0.0.11:
+ version "0.0.11"
+ resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
+ dependencies:
+ through "~2.3"
+
+pbkdf2@^3.0.3, pbkdf2@^3.0.9:
+ version "3.0.14"
+ resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
+ dependencies:
+ create-hash "^1.1.2"
+ create-hmac "^1.1.4"
+ ripemd160 "^2.0.1"
+ safe-buffer "^5.0.1"
+ sha.js "^2.4.8"
+
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
+pify@^2.0.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+
+ping-pong-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ping-pong-stream/-/ping-pong-stream-1.0.0.tgz#4c5eb09ba6adb021889dac0dcabfb8e57706854a"
+ dependencies:
+ end-of-stream "^1.1.0"
+ readable-stream "^2.1.5"
+ tape "^4.6.2"
+
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+pipetteur@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/pipetteur/-/pipetteur-2.0.3.tgz#1955760959e8d1a11cb2a50ec83eec470633e49f"
+ dependencies:
+ onecolor "^3.0.4"
+ synesthesia "^1.0.1"
+
+pkg-dir@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
+ dependencies:
+ find-up "^1.0.0"
+
+pkginfo@0.3.x:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21"
+
+pkginfo@0.x.x:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff"
+
+plucker@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/plucker/-/plucker-0.0.0.tgz#2ffa24e03ab2cffa4e75adc1df70f25623c45d09"
+
+plur@^2.0.0, plur@^2.1.0, plur@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a"
+ dependencies:
+ irregular-plurals "^1.0.0"
+
+pluralize@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762"
+
+pn@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/pn/-/pn-1.0.0.tgz#1cf5a30b0d806cd18f88fc41a6b5d4ad615b3ba9"
+
+pojo-migrator@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/pojo-migrator/-/pojo-migrator-2.1.0.tgz#3c2a3b9f80ba5a9fb7ebb921d3344db4efa5f669"
+
+polyfill-crypto.getrandomvalues@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/polyfill-crypto.getrandomvalues/-/polyfill-crypto.getrandomvalues-1.0.0.tgz#5c95602976ebb6155b163cb65d77b9eede3b61a4"
+ dependencies:
+ mersenne-twister "^1.0.1"
+
+portfinder@~0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-0.2.1.tgz#b2b9b0164f9e17fa3a9c7db2304d0a75140c71ad"
+ dependencies:
+ mkdirp "0.0.x"
+
+post-message-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/post-message-stream/-/post-message-stream-3.0.0.tgz#90d9f54bd209e6b6f5d74795b87588205b547048"
+ dependencies:
+ readable-stream "^2.1.4"
+
+postcss-less@^0.14.0:
+ version "0.14.0"
+ resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-0.14.0.tgz#c631b089c6cce422b9a10f3a958d2bedd3819324"
+ dependencies:
+ postcss "^5.0.21"
+
+postcss-less@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-1.1.0.tgz#bdcc76be64c4324d873fbc5cd9fa2e799e4305fa"
+ dependencies:
+ postcss "^5.2.16"
+
+postcss-media-query-parser@^0.2.0, postcss-media-query-parser@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
+
+postcss-reporter@^1.2.1, postcss-reporter@^1.3.3:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-1.4.1.tgz#c136f0a5b161915f379dd3765c61075f7e7b9af2"
+ dependencies:
+ chalk "^1.0.0"
+ lodash "^4.1.0"
+ log-symbols "^1.0.2"
+ postcss "^5.0.0"
+
+postcss-reporter@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-3.0.0.tgz#09ea0f37a444c5693878606e09b018ebeff7cf8f"
+ dependencies:
+ chalk "^1.0.0"
+ lodash "^4.1.0"
+ log-symbols "^1.0.2"
+ postcss "^5.0.0"
+
+postcss-reporter@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-5.0.0.tgz#a14177fd1342829d291653f2786efd67110332c3"
+ dependencies:
+ chalk "^2.0.1"
+ lodash "^4.17.4"
+ log-symbols "^2.0.0"
+ postcss "^6.0.8"
+
+postcss-resolve-nested-selector@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e"
+
+postcss-scss@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-0.4.1.tgz#ad771b81f0f72f5f4845d08aa60f93557653d54c"
+ dependencies:
+ postcss "^5.2.13"
+
+postcss-scss@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.2.tgz#ff45cf3354b879ee89a4eb68680f46ac9bb14f94"
+ dependencies:
+ postcss "^6.0.3"
+
+postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.1.1, postcss-selector-parser@^2.2.3:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90"
+ dependencies:
+ flatten "^1.0.2"
+ indexes-of "^1.0.1"
+ uniq "^1.0.1"
+
+postcss-sorting@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-sorting/-/postcss-sorting-2.1.0.tgz#32b1e9afa913bb225a6ad076d503d8f983bb4a82"
+ dependencies:
+ lodash "^4.17.4"
+ postcss "^5.2.17"
+
+postcss-value-parser@^3.1.1, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
+
+postcss@^5.0.0, postcss@^5.0.18, postcss@^5.0.20, postcss@^5.0.21, postcss@^5.0.4, postcss@^5.0.8, postcss@^5.2.13, postcss@^5.2.16, postcss@^5.2.17, postcss@^5.2.4, postcss@^5.2.5:
+ version "5.2.17"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.17.tgz#cf4f597b864d65c8a492b2eabe9d706c879c388b"
+ dependencies:
+ chalk "^1.1.3"
+ js-base64 "^2.1.9"
+ source-map "^0.5.6"
+ supports-color "^3.2.3"
+
+postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.3, postcss@^6.0.6, postcss@^6.0.8:
+ version "6.0.11"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.11.tgz#f48db210b1d37a7f7ab6499b7a54982997ab6f72"
+ dependencies:
+ chalk "^2.1.0"
+ source-map "^0.5.7"
+ supports-color "^4.4.0"
+
+prebuild-install@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.2.2.tgz#dd47c4d61f3754fb17bbf601759e5922e16e0671"
+ dependencies:
+ expand-template "^1.0.2"
+ github-from-package "0.0.0"
+ minimist "^1.2.0"
+ mkdirp "^0.5.1"
+ node-abi "^2.0.0"
+ noop-logger "^0.1.1"
+ npmlog "^4.0.1"
+ os-homedir "^1.0.1"
+ pump "^1.0.1"
+ rc "^1.1.6"
+ simple-get "^1.4.2"
+ tar-fs "^1.13.0"
+ tunnel-agent "^0.6.0"
+ xtend "4.0.1"
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+preserve@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+
+pretty-bytes@~0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-0.1.2.tgz#cd90294d58a1ca4e8a5d0fb9c8225998881acf00"
+
+pretty-hrtime@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
+
+printf@^0.2.3:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/printf/-/printf-0.2.5.tgz#c438ca2ca33e3927671db4ab69c0e52f936a4f0f"
+
+private@^0.1.6, private@^0.1.7, private@~0.1.5:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
+
+process-nextick-args@^1.0.7, process-nextick-args@~1.0.6:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+
+process@^0.11.0, process@~0.11.0:
+ version "0.11.10"
+ resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+
+process@~0.5.1:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
+
+progress@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
+
+promise-filter@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/promise-filter/-/promise-filter-1.1.0.tgz#7ec3ce990c867ccb9de8638dbd19ee17a52a4b59"
+ dependencies:
+ any-promise "^0.1.0"
+
+promise-to-callback@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7"
+ dependencies:
+ is-fn "^1.0.0"
+ set-immediate-shim "^1.0.1"
+
+promise@^7.1.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+ dependencies:
+ asap "~2.0.3"
+
+promise@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.1.tgz#e45d68b00a17647b6da711bf85ed6ed47208f450"
+ dependencies:
+ asap "~2.0.3"
+
+prompt@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe"
+ dependencies:
+ colors "^1.1.2"
+ pkginfo "0.x.x"
+ read "1.0.x"
+ revalidator "0.1.x"
+ utile "0.3.x"
+ winston "2.1.x"
+
+prop-types@^15.5.1, prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.8:
+ version "15.5.10"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
+ dependencies:
+ fbjs "^0.8.9"
+ loose-envify "^1.3.1"
+
+propagate@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/propagate/-/propagate-0.4.0.tgz#f3fcca0a6fe06736a7ba572966069617c130b481"
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+
+proxy-addr@~1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
+ dependencies:
+ forwarded "~0.1.0"
+ ipaddr.js "1.4.0"
+
+proxy-addr@~2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
+ dependencies:
+ forwarded "~0.1.2"
+ ipaddr.js "1.5.2"
+
+prr@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
+
+prr@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+
+pseudomap@^1.0.1, pseudomap@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+
+public-encrypt@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6"
+ dependencies:
+ bn.js "^4.1.0"
+ browserify-rsa "^4.0.0"
+ create-hash "^1.1.0"
+ parse-asn1 "^5.0.0"
+ randombytes "^2.0.1"
+
+pump@^1.0.0, pump@^1.0.1, pump@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51"
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pumpify@^1.3.3, pumpify@^1.3.4:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b"
+ dependencies:
+ duplexify "^3.1.2"
+ inherits "^2.0.1"
+ pump "^1.0.0"
+
+punycode@1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+
+punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+punycode@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"
+
+q@^1.1.2:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
+
+qjobs@^1.1.4:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73"
+
+qrcode-npm@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/qrcode-npm/-/qrcode-npm-0.0.3.tgz#77ee6fbefa9c0f29fa09d4d1520807c6a6042b9a"
+
+qs@5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-5.2.0.tgz#a9f31142af468cb72b25b30136ba2456834916be"
+
+qs@6.5.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
+
+qs@6.5.1, qs@^6.0.2, qs@^6.2.0:
+ version "6.5.1"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+
+qs@~2.2.3:
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.5.tgz#1088abaf9dcc0ae5ae45b709e6c6b5888b23923c"
+
+qs@~6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+
+querystring-es3@^0.2.0, querystring-es3@~0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+
+querystring@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+
+qunit@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/qunit/-/qunit-1.0.0.tgz#1d3dcfbfaec81979cb4bdaee45450bb5e5914f8c"
+ dependencies:
+ argsparser "^0.0.7"
+ cli-table "^0.3.0"
+ co "^4.6.0"
+ qunitjs "2.1.1"
+ tracejs "^0.1.8"
+ underscore "^1.6.0"
+ optionalDependencies:
+ istanbul "0.4.5"
+
+qunitjs@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/qunitjs/-/qunitjs-2.1.1.tgz#c3087c864d9a9443103bdbdecc0ef359c7a82281"
+
+quote-stream@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2"
+ dependencies:
+ buffer-equal "0.0.1"
+ minimist "^1.1.3"
+ through2 "^2.0.0"
+
+quote-stream@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-0.0.0.tgz#cde29e94c409b16e19dc7098b89b6658f9721d3b"
+ dependencies:
+ minimist "0.0.8"
+ through2 "~0.4.1"
+
+ramda@^0.24.1:
+ version "0.24.1"
+ resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857"
+
+randomatic@^1.1.3:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
+ dependencies:
+ is-number "^3.0.0"
+ kind-of "^4.0.0"
+
+randombytes@^2.0.0, randombytes@^2.0.1:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79"
+ dependencies:
+ safe-buffer "^5.1.0"
+
+range-parser@^1.2.0, range-parser@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+
+raphael@^2.2.0:
+ version "2.2.7"
+ resolved "https://registry.yarnpkg.com/raphael/-/raphael-2.2.7.tgz#231b19141f8d086986d8faceb66f8b562ee2c810"
+ dependencies:
+ eve-raphael "0.5.0"
+
+raw-body@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
+ dependencies:
+ bytes "3.0.0"
+ http-errors "1.6.2"
+ iconv-lite "0.4.19"
+ unpipe "1.0.0"
+
+raw-body@~2.1.5:
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774"
+ dependencies:
+ bytes "2.4.0"
+ iconv-lite "0.4.13"
+ unpipe "1.0.0"
+
+rc@^1.1.6, rc@^1.1.7:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
+ dependencies:
+ deep-extend "~0.4.0"
+ ini "~1.3.0"
+ minimist "^1.2.0"
+ strip-json-comments "~2.0.1"
+
+react-addons-css-transition-group@^15.6.0:
+ version "15.6.0"
+ resolved "https://registry.yarnpkg.com/react-addons-css-transition-group/-/react-addons-css-transition-group-15.6.0.tgz#69887cf6e4874d25cd66e22a699e29f0d648aba0"
+ dependencies:
+ react-transition-group "^1.2.0"
+
+react-addons-test-utils@^15.5.1:
+ version "15.6.0"
+ resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.0.tgz#062d36117fe8d18f3ba5e06eb33383b0b85ea5b9"
+
+react-dom@^15.0.2, react-dom@^15.5.4:
+ version "15.6.1"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.1.tgz#2cb0ed4191038e53c209eb3a79a23e2a4cf99470"
+ dependencies:
+ fbjs "^0.8.9"
+ loose-envify "^1.1.0"
+ object-assign "^4.1.0"
+ prop-types "^15.5.10"
+
+react-hyperscript@^2.4.0:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/react-hyperscript/-/react-hyperscript-2.4.2.tgz#c19b1f5a161ca2df10bcce6dd2299e8547a982fe"
+ dependencies:
+ react ">= 0.12.0 < 16.0.0"
+
+react-hyperscript@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/react-hyperscript/-/react-hyperscript-3.0.0.tgz#3c16010b33175de6bc01fd1ebad0a16a9a6dc9ab"
+
+react-input-autosize@^1.1.5:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-1.2.0.tgz#87241071159f742123897691da6796ec33b57d05"
+ dependencies:
+ create-react-class "^15.5.2"
+ prop-types "^15.5.8"
+
+react-markdown@^2.3.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-2.5.0.tgz#b1c61904fee5895886803bd9df7db23c3dc3a89e"
+ dependencies:
+ commonmark "^0.24.0"
+ commonmark-react-renderer "^4.2.4"
+ in-publish "^2.0.0"
+ prop-types "^15.5.1"
+
+react-redux@^5.0.5:
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946"
+ dependencies:
+ hoist-non-react-statics "^2.2.1"
+ invariant "^2.0.0"
+ lodash "^4.2.0"
+ lodash-es "^4.2.0"
+ loose-envify "^1.1.0"
+ prop-types "^15.5.10"
+
+react-select@^1.0.0-rc.2:
+ version "1.0.0-rc.7"
+ resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.0.0-rc.7.tgz#fab65abb7a6d51ccdde51d6ff6b594018fc208bc"
+ dependencies:
+ classnames "^2.2.4"
+ prop-types "^15.5.8"
+ react-input-autosize "^1.1.5"
+
+react-simple-file-input@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/react-simple-file-input/-/react-simple-file-input-1.0.0.tgz#0d5989b51b9bf2c25bb48a0c3fd7e73e413eaa48"
+
+react-test-renderer@^15.5.4:
+ version "15.6.1"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.6.1.tgz#026f4a5bb5552661fd2cc4bbcd0d4bc8a35ebf7e"
+ dependencies:
+ fbjs "^0.8.9"
+ object-assign "^4.1.0"
+
+react-testutils-additions@^15.2.0:
+ version "15.2.0"
+ resolved "https://registry.yarnpkg.com/react-testutils-additions/-/react-testutils-additions-15.2.0.tgz#7802a6f28dff9cfb673cbeaf32801cd6a054e6b7"
+ dependencies:
+ object-assign "3.0.0"
+ sizzle "2.3.3"
+
+react-tools@~0.13.0:
+ version "0.13.3"
+ resolved "https://registry.yarnpkg.com/react-tools/-/react-tools-0.13.3.tgz#da6ac7d4d7777a59a5e951cf46e72fd4b6b40a2c"
+ dependencies:
+ commoner "^0.10.0"
+ jstransform "^10.1.0"
+
+react-tooltip-component@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/react-tooltip-component/-/react-tooltip-component-0.3.0.tgz#fb3ec78c3270fe919692bc31f1404108bcf4785e"
+
+react-transition-group@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.0.tgz#b51fc921b0c3835a7ef7c571c79fc82c73e9204f"
+ dependencies:
+ chain-function "^1.0.0"
+ dom-helpers "^3.2.0"
+ loose-envify "^1.3.1"
+ prop-types "^15.5.6"
+ warning "^3.0.0"
+
+react-transition-group@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.2.0.tgz#793bf8cb15bfe91b3101b24bce1c1d2891659575"
+ dependencies:
+ chain-function "^1.0.0"
+ classnames "^2.2.5"
+ dom-helpers "^3.2.0"
+ loose-envify "^1.3.1"
+ prop-types "^15.5.8"
+ warning "^3.0.0"
+
+"react@>= 0.12.0 < 16.0.0", react@^15.0.2:
+ version "15.6.1"
+ resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"
+ dependencies:
+ create-react-class "^15.6.0"
+ fbjs "^0.8.9"
+ loose-envify "^1.1.0"
+ object-assign "^4.1.0"
+ prop-types "^15.5.10"
+
+reactify@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/reactify/-/reactify-1.1.1.tgz#a8f119596273c0d4bfb1abea0c14c2601ea03bba"
+ dependencies:
+ react-tools "~0.13.0"
+ through "~2.3.4"
+
+read-file-stdin@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/read-file-stdin/-/read-file-stdin-0.2.1.tgz#25eccff3a153b6809afacb23ee15387db9e0ee61"
+ dependencies:
+ gather-stream "^1.0.0"
+
+read-only-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0"
+ dependencies:
+ readable-stream "^2.0.2"
+
+read-pkg-up@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+ dependencies:
+ find-up "^1.0.0"
+ read-pkg "^1.0.0"
+
+read-pkg-up@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
+ dependencies:
+ find-up "^2.0.0"
+ read-pkg "^2.0.0"
+
+read-pkg@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+ dependencies:
+ load-json-file "^1.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^1.0.0"
+
+read-pkg@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
+ dependencies:
+ load-json-file "^2.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^2.0.0"
+
+read@1.0.x:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
+ dependencies:
+ mute-stream "~0.0.4"
+
+"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.15, readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.26, readable-stream@~1.0.27-1:
+ version "1.0.34"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
+"readable-stream@>=1.1.13-1 <1.2.0-0", readable-stream@^1.0.27-1, readable-stream@^1.0.33, readable-stream@^1.1.13-1, readable-stream@~1.1.9:
+ version "1.1.14"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
+readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9, readable-stream@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.0.3"
+ util-deprecate "~1.0.1"
+
+readable-stream@~2.0.0:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
+ string_decoder "~0.10.x"
+ util-deprecate "~1.0.1"
+
+readable-wrap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/readable-wrap/-/readable-wrap-1.0.0.tgz#3b5a211c631e12303a54991c806c17e7ae206bff"
+ dependencies:
+ readable-stream "^1.1.13-1"
+
+readdirp@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
+ dependencies:
+ graceful-fs "^4.1.2"
+ minimatch "^3.0.2"
+ readable-stream "^2.0.2"
+ set-immediate-shim "^1.0.1"
+
+recast@^0.11.17:
+ version "0.11.23"
+ resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
+ dependencies:
+ ast-types "0.9.6"
+ esprima "~3.1.0"
+ private "~0.1.5"
+ source-map "~0.5.0"
+
+rechoir@^0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+ dependencies:
+ resolve "^1.1.6"
+
+redent@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+ dependencies:
+ indent-string "^2.1.0"
+ strip-indent "^1.0.1"
+
+redux-logger@^3.0.6:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
+ dependencies:
+ deep-diff "^0.3.5"
+
+redux-thunk@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"
+
+redux@^3.0.5:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b"
+ dependencies:
+ lodash "^4.2.1"
+ lodash-es "^4.2.1"
+ loose-envify "^1.1.0"
+ symbol-observable "^1.0.3"
+
+regenerate@^1.2.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
+
+regenerator-runtime@^0.10.5:
+ version "0.10.5"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
+
+regenerator-runtime@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1"
+
+regenerator-transform@^0.10.0:
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
+ dependencies:
+ babel-runtime "^6.18.0"
+ babel-types "^6.19.0"
+ private "^0.1.6"
+
+regex-cache@^0.4.2:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
+ dependencies:
+ is-equal-shallow "^0.1.3"
+
+regexpu-core@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
+ dependencies:
+ regenerate "^1.2.1"
+ regjsgen "^0.2.0"
+ regjsparser "^0.1.4"
+
+regjsgen@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
+
+regjsparser@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
+ dependencies:
+ jsesc "~0.5.0"
+
+remove-trailing-separator@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+
+repeat-element@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
+
+repeat-string@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae"
+
+repeat-string@^1.5.2:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+
+repeating@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac"
+ dependencies:
+ is-finite "^1.0.0"
+
+repeating@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+ dependencies:
+ is-finite "^1.0.0"
+
+replace-ext@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924"
+
+replaceall@^0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e"
+
+replacestream@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.2.tgz#0c4140707e4f0323f50de044851708cf58bc37bd"
+ dependencies:
+ escape-string-regexp "^1.0.3"
+ object-assign "^4.0.1"
+ readable-stream "^2.0.2"
+
+request-promise-core@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6"
+ dependencies:
+ lodash "^4.13.1"
+
+request-promise-native@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.4.tgz#86988ec8eee408e45579fce83bfd05b3adf9a155"
+ dependencies:
+ request-promise-core "1.1.1"
+ stealthy-require "^1.1.0"
+ tough-cookie ">=2.3.0"
+
+request-promise@^4.2.1:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4"
+ dependencies:
+ bluebird "^3.5.0"
+ request-promise-core "1.1.1"
+ stealthy-require "^1.1.0"
+ tough-cookie ">=2.3.3"
+
+request@2, request@^2.67.0, request@^2.79.0, request@^2.81.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
+ dependencies:
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
+ caseless "~0.12.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.0"
+ forever-agent "~0.6.1"
+ form-data "~2.1.1"
+ har-validator "~4.2.1"
+ 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"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
+ tunnel-agent "^0.6.0"
+ uuid "^3.0.0"
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+
+require-from-string@^1.1.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418"
+
+require-main-filename@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+
+require-uncached@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
+ dependencies:
+ caller-path "^0.1.0"
+ resolve-from "^1.0.0"
+
+requires-port@1.x.x:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+
+resolve-dir@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e"
+ dependencies:
+ expand-tilde "^1.2.2"
+ global-modules "^0.2.3"
+
+resolve-from@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+
+resolve-from@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
+
+resolve-from@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
+
+resolve-url@~0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+
+resolve@1.1.7, resolve@1.1.x, resolve@~1.1.6:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+
+resolve@^0.6.1:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46"
+
+resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@~1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86"
+ dependencies:
+ path-parse "^1.0.5"
+
+response-stream@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/response-stream/-/response-stream-0.0.0.tgz#da4b17cc7684c98c962beb4d95f668c8dcad09d5"
+
+restore-cursor@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+ dependencies:
+ onetime "^2.0.0"
+ signal-exit "^3.0.2"
+
+resumer@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759"
+ dependencies:
+ through "~2.3.4"
+
+revalidator@0.1.x:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b"
+
+right-align@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+ dependencies:
+ align-text "^0.1.1"
+
+rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.4.4, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+ dependencies:
+ glob "^7.0.5"
+
+ripemd160@^2.0.0, ripemd160@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
+ dependencies:
+ hash-base "^2.0.0"
+ inherits "^2.0.1"
+
+rlp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.0.0.tgz#9db384ff4b89a8f61563d92395d8625b18f3afb0"
+
+run-async@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+ dependencies:
+ is-promise "^2.1.0"
+
+rx-lite-aggregates@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
+ dependencies:
+ rx-lite "*"
+
+rx-lite@*, rx-lite@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
+
+safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
+samsam@1.x, samsam@^1.1.3:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67"
+
+sandwich-expando@^1.0.5:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/sandwich-expando/-/sandwich-expando-1.1.1.tgz#83806fcca2375af8b6c30e6f52ed4f989debb165"
+ dependencies:
+ babel-preset-es2015 "^6.6.0"
+ babelify "^7.3.0"
+ brfs "^1.4.3"
+ raphael "^2.2.0"
+ react "^15.0.2"
+ react-dom "^15.0.2"
+ react-hyperscript "^2.4.0"
+
+sass-graph@^2.1.1:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
+ dependencies:
+ glob "^7.0.0"
+ lodash "^4.0.0"
+ scss-tokenizer "^0.2.3"
+ yargs "^7.0.0"
+
+sax@^1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+
+script-injector@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/script-injector/-/script-injector-1.0.0.tgz#f6f4c7f6a5dcc59e08246e76bdfc83a0a1406926"
+ dependencies:
+ duplexer2 "0.0.2"
+ through2 "^0.6.5"
+ trumpet "^1.7.1"
+
+scrypt.js@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada"
+ dependencies:
+ scrypt "^6.0.2"
+ scryptsy "^1.2.1"
+
+scrypt@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d"
+ dependencies:
+ nan "^2.0.8"
+
+scryptsy@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163"
+ dependencies:
+ pbkdf2 "^3.0.3"
+
+scss-tokenizer@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
+ dependencies:
+ js-base64 "^2.1.8"
+ source-map "^0.4.2"
+
+secp256k1@^3.0.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.3.0.tgz#50ec9b201ba401403dd13ccbf21d31eeb3ff43cf"
+ dependencies:
+ bindings "^1.2.1"
+ bip66 "^1.1.3"
+ bn.js "^4.11.3"
+ create-hash "^1.1.2"
+ drbg.js "^1.0.1"
+ elliptic "^6.2.3"
+ nan "^2.2.1"
+ prebuild-install "^2.0.0"
+ safe-buffer "^5.1.0"
+
+semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.0.5:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa"
+
+semver-greatest-satisfied-range@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b"
+ dependencies:
+ sver-compat "^1.5.0"
+
+"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@~5.4.1:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
+
+semver@~4.3.3:
+ version "4.3.6"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
+
+semver@~5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
+send@0.15.4:
+ version "0.15.4"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9"
+ dependencies:
+ debug "2.6.8"
+ depd "~1.1.1"
+ destroy "~1.0.4"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.0"
+ fresh "0.5.0"
+ http-errors "~1.6.2"
+ mime "1.3.4"
+ ms "2.0.0"
+ on-finished "~2.3.0"
+ range-parser "~1.2.0"
+ statuses "~1.3.1"
+
+send@0.16.0:
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.16.0.tgz#16338dbb9a2ede4ad57b48420ec3b82d8e80a57b"
+ dependencies:
+ debug "2.6.9"
+ depd "~1.1.1"
+ destroy "~1.0.4"
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "~1.6.2"
+ mime "1.4.1"
+ ms "2.0.0"
+ on-finished "~2.3.0"
+ range-parser "~1.2.0"
+ statuses "~1.3.1"
+
+serve-static@1.12.4:
+ version "1.12.4"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961"
+ dependencies:
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ parseurl "~1.3.1"
+ send "0.15.4"
+
+serve-static@1.13.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.0.tgz#810c91db800e94ba287eae6b4e06caab9fdc16f1"
+ dependencies:
+ encodeurl "~1.0.1"
+ escape-html "~1.0.3"
+ parseurl "~1.3.2"
+ send "0.16.0"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+
+set-immediate-shim@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+
+setimmediate@^1.0.4, setimmediate@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+
+setprototypeof@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+
+setprototypeof@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+
+sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4:
+ version "2.4.8"
+ resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f"
+ dependencies:
+ inherits "^2.0.1"
+
+sha3@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.0.tgz#6989f1b70a498705876a373e2c62ace96aa9399a"
+ dependencies:
+ nan "^2.0.5"
+
+shallow-copy@0.0.1, shallow-copy@~0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
+
+shasum@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f"
+ dependencies:
+ json-stable-stringify "~0.0.0"
+ sha.js "~2.4.4"
+
+shebang-command@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ dependencies:
+ shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+
+shell-quote@^1.4.2, shell-quote@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767"
+ dependencies:
+ array-filter "~0.0.0"
+ array-map "~0.0.0"
+ array-reduce "~0.0.0"
+ jsonify "~0.0.0"
+
+shellwords@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
+
+sigmund@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
+
+signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+
+simple-get@^1.4.2:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb"
+ dependencies:
+ once "^1.3.1"
+ unzip-response "^1.0.0"
+ xtend "^4.0.0"
+
+sinon@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.0.0.tgz#a54a5f0237aa1dd2215e5e81c89b42b50c4fdb6b"
+ dependencies:
+ diff "^3.1.0"
+ formatio "1.2.0"
+ lodash.get "^4.4.2"
+ lolex "^2.1.2"
+ native-promise-only "^0.8.1"
+ nise "^1.1.0"
+ path-to-regexp "^1.7.0"
+ samsam "^1.1.3"
+ text-encoding "0.6.4"
+ type-detect "^4.0.0"
+
+sizzle@2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/sizzle/-/sizzle-2.3.3.tgz#4eb078c37231a56b52e4193f701e7ef8937e606b"
+
+slash@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+
+slice-ansi@0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+
+slide@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+
+sntp@1.x.x:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
+ dependencies:
+ hoek "2.x.x"
+
+socket.io-adapter@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b"
+ dependencies:
+ debug "2.3.3"
+ socket.io-parser "2.3.1"
+
+socket.io-client@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.6.0.tgz#5b668f4f771304dfeed179064708386fa6717853"
+ dependencies:
+ backo2 "1.0.2"
+ component-bind "1.0.0"
+ component-emitter "1.2.1"
+ debug "2.3.3"
+ engine.io-client "1.8.0"
+ has-binary "0.1.7"
+ indexof "0.0.1"
+ object-component "0.0.3"
+ parseuri "0.0.5"
+ socket.io-parser "2.3.1"
+ to-array "0.1.4"
+
+socket.io-client@1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.3.tgz#b30e86aa10d5ef3546601c09cde4765e381da377"
+ dependencies:
+ backo2 "1.0.2"
+ component-bind "1.0.0"
+ component-emitter "1.2.1"
+ debug "2.3.3"
+ engine.io-client "1.8.3"
+ has-binary "0.1.7"
+ indexof "0.0.1"
+ object-component "0.0.3"
+ parseuri "0.0.5"
+ socket.io-parser "2.3.1"
+ to-array "0.1.4"
+
+socket.io-parser@2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0"
+ dependencies:
+ component-emitter "1.1.2"
+ debug "2.2.0"
+ isarray "0.0.1"
+ json3 "3.3.2"
+
+socket.io@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.6.0.tgz#3e40d932637e6bd923981b25caf7c53e83b6e2e1"
+ dependencies:
+ debug "2.3.3"
+ engine.io "1.8.0"
+ has-binary "0.1.7"
+ object-assign "4.1.0"
+ socket.io-adapter "0.5.0"
+ socket.io-client "1.6.0"
+ socket.io-parser "2.3.1"
+
+socket.io@1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.3.tgz#b8af9caba00949e568e369f1327ea9be9ea2461b"
+ dependencies:
+ debug "2.3.3"
+ engine.io "1.8.3"
+ has-binary "0.1.7"
+ object-assign "4.1.0"
+ socket.io-adapter "0.5.0"
+ socket.io-client "1.7.3"
+ socket.io-parser "2.3.1"
+
+solc@^0.4.2:
+ version "0.4.16"
+ resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.16.tgz#809a5b1257c7c200e11a841b377eaec274698539"
+ dependencies:
+ fs-extra "^0.30.0"
+ memorystream "^0.3.1"
+ require-from-string "^1.1.0"
+ semver "^5.3.0"
+ yargs "^4.7.1"
+
+source-list-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
+
+source-map-resolve@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761"
+ dependencies:
+ atob "~1.1.0"
+ resolve-url "~0.2.1"
+ source-map-url "~0.3.0"
+ urix "~0.1.0"
+
+source-map-support@^0.4.15:
+ version "0.4.18"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+ dependencies:
+ source-map "^0.5.6"
+
+source-map-url@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9"
+
+source-map@0.1.31:
+ version "0.1.31"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.31.tgz#9f704d0d69d9e138a81badf6ebb4fde33d151c61"
+ dependencies:
+ amdefine ">=0.0.4"
+
+source-map@0.X, "source-map@>= 0.1.2", source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+
+source-map@^0.1.38, source-map@~0.1.33:
+ version "0.1.43"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
+ dependencies:
+ amdefine ">=0.0.4"
+
+source-map@^0.4.2, source-map@^0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
+ dependencies:
+ amdefine ">=0.0.4"
+
+source-map@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
+ dependencies:
+ amdefine ">=0.0.4"
+
+sparkles@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3"
+
+spawn-args@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/spawn-args/-/spawn-args-0.2.0.tgz#fb7d0bd1d70fd4316bd9e3dec389e65f9d6361bb"
+
+spawn-wrap@^1.3.8:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.8.tgz#fa2a79b990cbb0bb0018dca6748d88367b19ec31"
+ dependencies:
+ foreground-child "^1.5.6"
+ mkdirp "^0.5.0"
+ os-homedir "^1.0.1"
+ rimraf "^2.3.3"
+ signal-exit "^3.0.2"
+ which "^1.2.4"
+
+spdx-correct@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+ dependencies:
+ spdx-license-ids "^1.0.2"
+
+spdx-expression-parse@~1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+
+spdx-license-ids@^1.0.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+
+specificity@^0.3.0, specificity@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.3.1.tgz#f1b068424ce317ae07478d95de3c21cf85e8d567"
+
+split2@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/split2/-/split2-0.2.1.tgz#02ddac9adc03ec0bb78c1282ec079ca6e85ae900"
+ dependencies:
+ through2 "~0.6.1"
+
+split@0.3, split@~0.3.0:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
+ dependencies:
+ through "2"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+sshpk@^1.7.0:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ dashdash "^1.12.0"
+ getpass "^0.1.1"
+ optionalDependencies:
+ bcrypt-pbkdf "^1.0.0"
+ ecc-jsbn "~0.1.1"
+ jsbn "~0.1.0"
+ tweetnacl "~0.14.0"
+
+stack-trace@0.0.9:
+ version "0.0.9"
+ resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
+
+stack-trace@0.0.x:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
+
+static-eval@~0.2.0:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-0.2.4.tgz#b7d34d838937b969f9641ca07d48f8ede263ea7b"
+ dependencies:
+ escodegen "~0.0.24"
+
+static-module@^1.1.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/static-module/-/static-module-1.5.0.tgz#27da9883c41a8cd09236f842f0c1ebc6edf63d86"
+ dependencies:
+ concat-stream "~1.6.0"
+ duplexer2 "~0.0.2"
+ escodegen "~1.3.2"
+ falafel "^2.1.0"
+ has "^1.0.0"
+ object-inspect "~0.4.0"
+ quote-stream "~0.0.0"
+ readable-stream "~1.0.27-1"
+ shallow-copy "~0.0.1"
+ static-eval "~0.2.0"
+ through2 "~0.4.1"
+
+statuses@1, "statuses@>= 1.3.1 < 2", statuses@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
+
+stdin@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/stdin/-/stdin-0.0.1.tgz#d3041981aaec3dfdbc77a1b38d6372e38f5fb71e"
+
+stdout-stream@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b"
+ dependencies:
+ readable-stream "^2.0.1"
+
+stealthy-require@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+
+stream-browserify@^2.0.0, stream-browserify@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
+ dependencies:
+ inherits "~2.0.1"
+ readable-stream "^2.0.2"
+
+stream-combiner2@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe"
+ dependencies:
+ duplexer2 "~0.1.0"
+ readable-stream "^2.0.2"
+
+stream-combiner@^0.2.1:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858"
+ dependencies:
+ duplexer "~0.1.1"
+ through "~2.3.4"
+
+stream-combiner@~0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
+ dependencies:
+ duplexer "~0.1.1"
+
+stream-each@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.0.tgz#1e95d47573f580d814dc0ff8cd0f66f1ce53c991"
+ dependencies:
+ end-of-stream "^1.1.0"
+ stream-shift "^1.0.0"
+
+stream-exhaust@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d"
+
+stream-http@^2.0.0, stream-http@^2.3.1:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad"
+ dependencies:
+ builtin-status-codes "^3.0.0"
+ inherits "^2.0.1"
+ readable-stream "^2.2.6"
+ to-arraybuffer "^1.0.0"
+ xtend "^4.0.0"
+
+stream-shift@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+
+stream-splicer@^1.2.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-1.3.2.tgz#3c0441be15b9bf4e226275e6dc83964745546661"
+ dependencies:
+ indexof "0.0.1"
+ inherits "^2.0.1"
+ isarray "~0.0.1"
+ readable-stream "^1.1.13-1"
+ readable-wrap "^1.0.0"
+ through2 "^1.0.0"
+
+stream-splicer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83"
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+
+string-length@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
+ dependencies:
+ strip-ansi "^3.0.0"
+
+string-width@^1.0.1, string-width@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ strip-ansi "^3.0.0"
+
+string-width@^2.0.0, string-width@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+ dependencies:
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^4.0.0"
+
+string.prototype.repeat@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf"
+
+string.prototype.trim@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.5.0"
+ function-bind "^1.0.2"
+
+string_decoder@^0.10.25, string_decoder@~0.10.x:
+ version "0.10.31"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+string_decoder@~1.0.0, string_decoder@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
+ dependencies:
+ safe-buffer "~5.1.0"
+
+stringstream@~0.0.4:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+
+strip-ansi@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220"
+ dependencies:
+ ansi-regex "^0.2.1"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+ dependencies:
+ ansi-regex "^3.0.0"
+
+strip-bom-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee"
+ dependencies:
+ first-chunk-stream "^1.0.0"
+ strip-bom "^2.0.0"
+
+strip-bom-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca"
+ dependencies:
+ first-chunk-stream "^2.0.0"
+ strip-bom "^2.0.0"
+
+strip-bom-string@1.X:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92"
+
+strip-bom@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+ dependencies:
+ is-utf8 "^0.2.0"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+
+strip-eof@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+
+strip-hex-prefix@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
+ dependencies:
+ is-hex-prefixed "1.0.0"
+
+strip-indent@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+ dependencies:
+ get-stdin "^4.0.1"
+
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+style-search@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
+
+styled_string@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/styled_string/-/styled_string-0.0.1.tgz#d22782bd81295459bc4f1df18c4bad8e94dd124a"
+
+stylefmt@^5.0.4:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/stylefmt/-/stylefmt-5.3.2.tgz#32013437aa54d8c5253cbc107ac914dfb5ee9eea"
+ dependencies:
+ chalk "^1.1.3"
+ css-color-list "0.0.1"
+ diff "^3.1.0"
+ editorconfig "^0.13.2"
+ globby "^6.1.0"
+ minimist "^1.2.0"
+ postcss "^5.2.5"
+ postcss-scss "^0.4.0"
+ postcss-sorting "^2.0.1"
+ postcss-value-parser "^3.3.0"
+ stdin "0.0.1"
+ stylelint "^7.5.0"
+ stylelint-order "0.4.x"
+
+stylehacks@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-2.3.2.tgz#64c83e0438a68c9edf449e8c552a7d9ab6009b0b"
+ dependencies:
+ browserslist "^1.1.3"
+ chalk "^1.1.1"
+ log-symbols "^1.0.2"
+ minimist "^1.2.0"
+ plur "^2.1.2"
+ postcss "^5.0.18"
+ postcss-reporter "^1.3.3"
+ postcss-selector-parser "^2.0.0"
+ read-file-stdin "^0.2.1"
+ text-table "^0.2.0"
+ write-file-stdout "0.0.2"
+
+stylelint-config-recommended@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-1.0.0.tgz#752c17fc68fa64cd5e7589e24f6e46e77e14a735"
+
+stylelint-config-standard@^17.0.0:
+ version "17.0.0"
+ resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-17.0.0.tgz#42103a090054ee2a3dde9ecaed55e5d4d9d059fc"
+ dependencies:
+ stylelint-config-recommended "^1.0.0"
+
+stylelint-order@0.4.x:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-0.4.4.tgz#db7dfca0541b5062010c7e2e21e745791fc088ac"
+ dependencies:
+ lodash "^4.17.4"
+ postcss "^5.2.16"
+ stylelint "^7.9.0"
+
+stylelint@^7.5.0, stylelint@^7.9.0:
+ version "7.13.0"
+ resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-7.13.0.tgz#111f97b6da72e775c80800d6bb6f5f869997785d"
+ dependencies:
+ autoprefixer "^6.0.0"
+ balanced-match "^0.4.0"
+ chalk "^2.0.1"
+ colorguard "^1.2.0"
+ cosmiconfig "^2.1.1"
+ debug "^2.6.0"
+ doiuse "^2.4.1"
+ execall "^1.0.0"
+ file-entry-cache "^2.0.0"
+ get-stdin "^5.0.0"
+ globby "^6.0.0"
+ globjoin "^0.1.4"
+ html-tags "^2.0.0"
+ ignore "^3.2.0"
+ imurmurhash "^0.1.4"
+ known-css-properties "^0.2.0"
+ lodash "^4.17.4"
+ log-symbols "^1.0.2"
+ mathml-tag-names "^2.0.0"
+ meow "^3.3.0"
+ micromatch "^2.3.11"
+ normalize-selector "^0.2.0"
+ pify "^2.3.0"
+ postcss "^5.0.20"
+ postcss-less "^0.14.0"
+ postcss-media-query-parser "^0.2.0"
+ postcss-reporter "^3.0.0"
+ postcss-resolve-nested-selector "^0.1.1"
+ postcss-scss "^0.4.0"
+ postcss-selector-parser "^2.1.1"
+ postcss-value-parser "^3.1.1"
+ resolve-from "^3.0.0"
+ specificity "^0.3.0"
+ string-width "^2.0.0"
+ style-search "^0.1.0"
+ stylehacks "^2.3.2"
+ sugarss "^0.2.0"
+ svg-tags "^1.0.0"
+ table "^4.0.1"
+
+stylelint@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-8.1.1.tgz#9feeed699598b27427715551ed7786db341c19ad"
+ dependencies:
+ autoprefixer "^7.1.2"
+ balanced-match "^1.0.0"
+ chalk "^2.0.1"
+ cosmiconfig "^2.1.3"
+ debug "^3.0.0"
+ execall "^1.0.0"
+ file-entry-cache "^2.0.0"
+ get-stdin "^5.0.1"
+ globby "^6.1.0"
+ globjoin "^0.1.4"
+ html-tags "^2.0.0"
+ ignore "^3.3.3"
+ imurmurhash "^0.1.4"
+ known-css-properties "^0.3.0"
+ lodash "^4.17.4"
+ log-symbols "^2.0.0"
+ mathml-tag-names "^2.0.1"
+ meow "^3.7.0"
+ micromatch "^2.3.11"
+ normalize-selector "^0.2.0"
+ pify "^3.0.0"
+ postcss "^6.0.6"
+ postcss-less "^1.1.0"
+ postcss-media-query-parser "^0.2.3"
+ postcss-reporter "^5.0.0"
+ postcss-resolve-nested-selector "^0.1.1"
+ postcss-scss "^1.0.2"
+ postcss-selector-parser "^2.2.3"
+ postcss-value-parser "^3.3.0"
+ resolve-from "^3.0.0"
+ specificity "^0.3.1"
+ string-width "^2.1.0"
+ style-search "^0.1.0"
+ sugarss "^1.0.0"
+ svg-tags "^1.0.0"
+ table "^4.0.1"
+
+subarg@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2"
+ dependencies:
+ minimist "^1.1.0"
+
+sugarss@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-0.2.0.tgz#ac34237563327c6ff897b64742bf6aec190ad39e"
+ dependencies:
+ postcss "^5.2.4"
+
+sugarss@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.0.tgz#65e51b3958432fb70d5451a68bb33e32d0cf1ef7"
+ dependencies:
+ postcss "^6.0.0"
+
+supports-color@3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
+ dependencies:
+ has-flag "^1.0.0"
+
+supports-color@4.4.0, supports-color@^4.0.0, supports-color@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e"
+ dependencies:
+ has-flag "^2.0.0"
+
+supports-color@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ dependencies:
+ has-flag "^1.0.0"
+
+sver-compat@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8"
+ dependencies:
+ es6-iterator "^2.0.1"
+ es6-symbol "^3.1.1"
+
+svg-tags@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
+
+sw-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/sw-stream/-/sw-stream-2.0.0.tgz#628ebbeeb9eee0b66b03ec52fc55fcc4eeb23cf3"
+ dependencies:
+ end-of-stream "^1.1.0"
+ pump "^1.0.2"
+ readable-stream "^2.2.2"
+ through2 "^2.0.3"
+
+symbol-observable@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
+
+symbol-tree@^3.2.1:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
+
+synesthesia@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/synesthesia/-/synesthesia-1.0.1.tgz#5ef95ea548c0d5c6e6f9bb4b0d0731dff864a777"
+ dependencies:
+ css-color-names "0.0.3"
+
+syntax-error@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.3.0.tgz#1ed9266c4d40be75dc55bf9bb1cb77062bb96ca1"
+ dependencies:
+ acorn "^4.0.3"
+
+table@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435"
+ dependencies:
+ ajv "^4.7.0"
+ ajv-keywords "^1.0.0"
+ chalk "^1.1.1"
+ lodash "^4.0.0"
+ slice-ansi "0.0.4"
+ string-width "^2.0.0"
+
+tap-parser@^5.1.0:
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-5.4.0.tgz#6907e89725d7b7fa6ae41ee2c464c3db43188aec"
+ dependencies:
+ events-to-array "^1.0.1"
+ js-yaml "^3.2.7"
+ optionalDependencies:
+ readable-stream "^2"
+
+tapable@^0.2.7, tapable@~0.2.5:
+ version "0.2.8"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
+
+tape@^4.4.0, tape@^4.5.1, tape@^4.6.0, tape@^4.6.2, tape@^4.6.3:
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/tape/-/tape-4.8.0.tgz#f6a9fec41cc50a1de50fa33603ab580991f6068e"
+ dependencies:
+ deep-equal "~1.0.1"
+ defined "~1.0.0"
+ for-each "~0.3.2"
+ function-bind "~1.1.0"
+ glob "~7.1.2"
+ has "~1.0.1"
+ inherits "~2.0.3"
+ minimist "~1.2.0"
+ object-inspect "~1.3.0"
+ resolve "~1.4.0"
+ resumer "~0.0.0"
+ string.prototype.trim "~1.1.2"
+ through "~2.3.8"
+
+tar-fs@^1.13.0:
+ version "1.15.3"
+ resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.15.3.tgz#eccf935e941493d8151028e636e51ce4c3ca7f20"
+ dependencies:
+ chownr "^1.0.1"
+ mkdirp "^0.5.1"
+ pump "^1.0.0"
+ tar-stream "^1.1.2"
+
+tar-pack@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
+ dependencies:
+ debug "^2.2.0"
+ fstream "^1.0.10"
+ fstream-ignore "^1.0.5"
+ once "^1.3.3"
+ readable-stream "^2.1.4"
+ rimraf "^2.5.1"
+ tar "^2.2.1"
+ uid-number "^0.0.6"
+
+tar-stream@^1.1.2:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016"
+ dependencies:
+ bl "^1.0.0"
+ end-of-stream "^1.0.0"
+ readable-stream "^2.0.0"
+ xtend "^4.0.0"
+
+tar@^2.0.0, tar@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
+ dependencies:
+ block-stream "*"
+ fstream "^1.0.2"
+ inherits "2"
+
+ternary-stream@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-2.0.1.tgz#064e489b4b5bf60ba6a6b7bc7f2f5c274ecf8269"
+ dependencies:
+ duplexify "^3.5.0"
+ fork-stream "^0.0.4"
+ merge-stream "^1.0.0"
+ through2 "^2.0.1"
+
+test-exclude@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26"
+ dependencies:
+ arrify "^1.0.1"
+ micromatch "^2.3.11"
+ object-assign "^4.1.0"
+ read-pkg-up "^1.0.1"
+ require-main-filename "^1.0.1"
+
+testem@^1.10.3:
+ version "1.18.4"
+ resolved "https://registry.yarnpkg.com/testem/-/testem-1.18.4.tgz#e45fed922bec2f54a616c43f11922598ac97eb41"
+ dependencies:
+ backbone "^1.1.2"
+ bluebird "^3.4.6"
+ charm "^1.0.0"
+ commander "^2.6.0"
+ consolidate "^0.14.0"
+ cross-spawn "^5.1.0"
+ express "^4.10.7"
+ fireworm "^0.7.0"
+ glob "^7.0.4"
+ http-proxy "^1.13.1"
+ js-yaml "^3.2.5"
+ lodash.assignin "^4.1.0"
+ lodash.clonedeep "^4.4.1"
+ lodash.find "^4.5.1"
+ lodash.uniqby "^4.7.0"
+ mkdirp "^0.5.1"
+ mustache "^2.2.1"
+ node-notifier "^5.0.1"
+ npmlog "^4.0.0"
+ printf "^0.2.3"
+ rimraf "^2.4.4"
+ socket.io "1.6.0"
+ spawn-args "^0.2.0"
+ styled_string "0.0.1"
+ tap-parser "^5.1.0"
+ xmldom "^0.1.19"
+
+text-encoding@0.6.4, text-encoding@^0.6.4:
+ version "0.6.4"
+ resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
+
+text-table@^0.2.0, text-table@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+textarea-caret@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/textarea-caret/-/textarea-caret-3.0.2.tgz#f360c48699aa1abf718680a43a31a850665c2caf"
+
+textextensions@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-1.0.2.tgz#65486393ee1f2bb039a60cbba05b0b68bd9501d2"
+
+thenify-all@^1.0.0, thenify-all@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
+ dependencies:
+ thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839"
+ dependencies:
+ any-promise "^1.0.0"
+
+through2-filter@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec"
+ dependencies:
+ through2 "~2.0.0"
+ xtend "~4.0.0"
+
+through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
+ dependencies:
+ readable-stream "^2.1.5"
+ xtend "~4.0.1"
+
+through2@^0.6.0, through2@^0.6.1, through2@^0.6.3, through2@^0.6.5, through2@~0.6.1:
+ version "0.6.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
+ dependencies:
+ readable-stream ">=1.0.33-1 <1.1.0-0"
+ xtend ">=4.0.0 <4.1.0-0"
+
+through2@^1.0.0, through2@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-1.1.1.tgz#0847cbc4449f3405574dbdccd9bb841b83ac3545"
+ dependencies:
+ readable-stream ">=1.1.13-1 <1.2.0-0"
+ xtend ">=4.0.0 <4.1.0-0"
+
+through2@~0.4.1:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b"
+ dependencies:
+ readable-stream "~1.0.17"
+ xtend "~2.1.1"
+
+through2@~0.5.0:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7"
+ dependencies:
+ readable-stream "~1.0.17"
+ xtend "~3.0.0"
+
+through@2, "through@>=2.2.7 <3", through@X.X.X, through@^2.3.4, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
+through@~2.2.0:
+ version "2.2.7"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.2.7.tgz#6e8e21200191d4eb6a99f6f010df46aa1c6eb2bd"
+
+tildify@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a"
+ dependencies:
+ os-homedir "^1.0.0"
+
+time-stamp@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3"
+
+timers-browserify@^1.0.1:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
+ dependencies:
+ process "~0.11.0"
+
+timers-browserify@^2.0.2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6"
+ dependencies:
+ setimmediate "^1.0.4"
+
+timers-ext@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.2.tgz#61cc47a76c1abd3195f14527f978d58ae94c5204"
+ dependencies:
+ es5-ext "~0.10.14"
+ next-tick "1"
+
+tmp@0.0.31, tmp@^0.0.31:
+ version "0.0.31"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"
+ dependencies:
+ os-tmpdir "~1.0.1"
+
+tmp@0.0.x:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ dependencies:
+ os-tmpdir "~1.0.2"
+
+to-absolute-glob@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f"
+ dependencies:
+ extend-shallow "^2.0.1"
+
+to-array@0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
+
+to-arraybuffer@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
+
+to-fast-properties@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+
+to-utf8@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852"
+
+toggle-selection@^1.0.3:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
+
+tough-cookie@>=2.3.0, tough-cookie@^2.3.2, tough-cookie@~2.3.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
+ dependencies:
+ punycode "^1.4.1"
+
+tough-cookie@>=2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
+ dependencies:
+ punycode "^1.4.1"
+
+tr46@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+ dependencies:
+ punycode "^2.1.0"
+
+tracejs@^0.1.8:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/tracejs/-/tracejs-0.1.8.tgz#6c26787b1853f1371634622c1c80bc44026c5d70"
+
+traverse@~0.6.3:
+ version "0.6.6"
+ resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
+
+trim-newlines@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+
+trim-right@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+
+trim@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
+
+trumpet@^1.7.1:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/trumpet/-/trumpet-1.7.2.tgz#b02c69e465d171f55e44924bf9b5bdd20974c830"
+ dependencies:
+ duplexer2 "~0.0.2"
+ html-select "^2.3.5"
+ html-tokenize "^1.1.1"
+ inherits "^2.0.0"
+ readable-stream "^1.0.27-1"
+ through2 "^1.0.0"
+
+tryit@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
+
+tty-browserify@0.0.0, tty-browserify@~0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ dependencies:
+ prelude-ls "~1.1.2"
+
+type-detect@0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
+
+type-detect@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
+
+type-detect@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
+
+type-is@~1.6.10, type-is@~1.6.15:
+ version "1.6.15"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.15"
+
+typedarray@^0.0.6, typedarray@~0.0.5:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+
+ua-parser-js@^0.7.9:
+ version "0.7.14"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.14.tgz#110d53fa4c3f326c121292bbeac904d2e03387ca"
+
+uglify-es@^3.0.15:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.0.tgz#b4ca636bde6467e82a061ea7f2c124899d82bd2c"
+ dependencies:
+ commander "~2.11.0"
+ source-map "~0.5.1"
+
+uglify-js@^2.6, uglify-js@^2.8.27:
+ version "2.8.29"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+ dependencies:
+ source-map "~0.5.1"
+ yargs "~3.10.0"
+ optionalDependencies:
+ uglify-to-browserify "~1.0.0"
+
+uglify-to-browserify@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+
+uglifyify@^4.0.2:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/uglifyify/-/uglifyify-4.0.3.tgz#ff16ce11033faa54f782a050e0a77a55e7416724"
+ dependencies:
+ convert-source-map "~1.1.0"
+ extend "^1.2.1"
+ minimatch "^3.0.2"
+ through "~2.3.4"
+ uglify-es "^3.0.15"
+
+uid-number@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+
+ultron@1.0.x:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
+
+umd@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.1.tgz#8ae556e11011f63c2596708a8837259f01b3d60e"
+
+unc-path-regex@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
+
+underscore@>=1.8.3, underscore@^1.6.0:
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
+
+undertaker-registry@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.0.tgz#2da716c765999d8c94b9f9ed2c006df4923b052b"
+
+undertaker@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.0.tgz#339da4646252d082dc378e708067299750e11b49"
+ dependencies:
+ arr-flatten "^1.0.1"
+ arr-map "^2.0.0"
+ bach "^1.0.0"
+ collection-map "^1.0.0"
+ es6-weak-map "^2.0.1"
+ last-run "^1.1.0"
+ object.defaults "^1.0.0"
+ object.reduce "^1.0.0"
+ undertaker-registry "^1.0.0"
+
+uniq@^1.0.0, uniq@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
+
+unique-stream@^2.0.2:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369"
+ dependencies:
+ json-stable-stringify "^1.0.0"
+ through2-filter "^2.0.0"
+
+unorm@^1.3.3:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+
+unzip-response@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
+
+urix@^0.1.0, urix@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+
+url@^0.11.0, url@~0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+ dependencies:
+ punycode "1.3.2"
+ querystring "0.2.0"
+
+user-home@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
+
+useragent@^2.1.12:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e"
+ dependencies:
+ lru-cache "2.2.x"
+ tmp "0.0.x"
+
+utf8@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96"
+
+util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+util@0.10.3, util@^0.10.3, util@~0.10.1:
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+ dependencies:
+ inherits "2.0.1"
+
+utile@0.3.x:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a"
+ dependencies:
+ async "~0.9.0"
+ deep-equal "~0.2.1"
+ i "0.3.x"
+ mkdirp "0.x.x"
+ ncp "1.0.x"
+ rimraf "2.x.x"
+
+utils-merge@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+
+uuid@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
+
+uuid@^3.0.0, uuid@^3.0.1:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
+
+v8flags@^2.0.9:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
+ dependencies:
+ user-home "^1.1.1"
+
+vali-date@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
+
+valid-url@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
+
+validate-npm-package-license@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+ dependencies:
+ spdx-correct "~1.0.0"
+ spdx-expression-parse "~1.0.0"
+
+varint@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/varint/-/varint-4.0.1.tgz#490829b942d248463b2b35097995c3bf737198e9"
+
+vary@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+ dependencies:
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
+
+vinyl-buffer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-buffer/-/vinyl-buffer-1.0.0.tgz#ca067ea08431d507722b1de5083f602616ebc234"
+ dependencies:
+ bl "^0.9.1"
+ through2 "^0.6.1"
+
+vinyl-file@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a"
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.3.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+ strip-bom-stream "^2.0.0"
+ vinyl "^1.1.0"
+
+vinyl-fs@^2.0.0:
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239"
+ dependencies:
+ duplexify "^3.2.0"
+ glob-stream "^5.3.2"
+ graceful-fs "^4.0.0"
+ gulp-sourcemaps "1.6.0"
+ is-valid-glob "^0.3.0"
+ lazystream "^1.0.0"
+ lodash.isequal "^4.0.0"
+ merge-stream "^1.0.0"
+ mkdirp "^0.5.0"
+ object-assign "^4.0.0"
+ readable-stream "^2.0.4"
+ strip-bom "^2.0.0"
+ strip-bom-stream "^1.0.0"
+ through2 "^2.0.0"
+ through2-filter "^2.0.0"
+ vali-date "^1.0.0"
+ vinyl "^1.0.0"
+
+vinyl-source-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz#44cbe5108205279deb0c5653c094a2887938b1ab"
+ dependencies:
+ through2 "^0.6.1"
+ vinyl "^0.4.3"
+
+vinyl-sourcemaps-apply@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
+ dependencies:
+ source-map "^0.5.1"
+
+vinyl@1.X, vinyl@^1.0.0, vinyl@^1.1.0, vinyl@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
+ dependencies:
+ clone "^1.0.0"
+ clone-stats "^0.0.1"
+ replace-ext "0.0.1"
+
+vinyl@^0.4.3:
+ version "0.4.6"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
+ dependencies:
+ clone "^0.2.0"
+ clone-stats "^0.0.1"
+
+vinyl@^0.5.0:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde"
+ dependencies:
+ clone "^1.0.0"
+ clone-stats "^0.0.1"
+ replace-ext "0.0.1"
+
+vm-browserify@0.0.4, vm-browserify@~0.0.1:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
+ dependencies:
+ indexof "0.0.1"
+
+void-elements@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
+
+vreme@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/vreme/-/vreme-3.0.2.tgz#4721376b449457fefde8a849d3340933b90b5686"
+
+warning@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
+ dependencies:
+ loose-envify "^1.0.0"
+
+watchify@^3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/watchify/-/watchify-3.9.0.tgz#f075fd2e8a86acde84cedba6e5c2a0bedd523d9e"
+ dependencies:
+ anymatch "^1.3.0"
+ browserify "^14.0.0"
+ chokidar "^1.0.0"
+ defined "^1.0.0"
+ outpipe "^1.1.0"
+ through2 "^2.0.0"
+ xtend "^4.0.0"
+
+watchpack@^1.3.1:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac"
+ dependencies:
+ async "^2.1.2"
+ chokidar "^1.7.0"
+ graceful-fs "^4.1.2"
+
+weak@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/weak/-/weak-1.0.1.tgz#ab99aab30706959aa0200cb8cf545bb9cb33b99e"
+ dependencies:
+ bindings "^1.2.1"
+ nan "^2.0.5"
+
+web3-provider-engine@^13.3.1:
+ version "13.3.2"
+ resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.3.2.tgz#a5954aa637f96f0dde5131bc20a6ce9e33e6fcd1"
+ dependencies:
+ async "^2.5.0"
+ clone "^2.0.0"
+ eth-block-tracker "^2.2.2"
+ eth-sig-util "^1.3.0"
+ ethereumjs-block "^1.2.2"
+ ethereumjs-tx "^1.2.0"
+ ethereumjs-util "^5.1.1"
+ ethereumjs-vm "^2.0.2"
+ fetch-ponyfill "^4.0.0"
+ json-rpc-error "^2.0.0"
+ json-stable-stringify "^1.0.1"
+ promise-to-callback "^1.0.0"
+ readable-stream "^2.2.9"
+ request "^2.67.0"
+ semaphore "^1.0.3"
+ solc "^0.4.2"
+ tape "^4.4.0"
+ xhr "^2.2.0"
+ xtend "^4.0.1"
+
+web3-stream-provider@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/web3-stream-provider/-/web3-stream-provider-3.0.1.tgz#f5a593a8eefe808f85eb5fb1f344e5838050f814"
+ dependencies:
+ readable-stream "^2.0.5"
+
+web3@^0.18.4:
+ version "0.18.4"
+ resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d"
+ dependencies:
+ bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
+ crypto-js "^3.1.4"
+ utf8 "^2.1.1"
+ xhr2 "*"
+ xmlhttprequest "*"
+
+web3@^0.20.1:
+ version "0.20.1"
+ resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.1.tgz#fb262e9ad71552167a6af012fdd420de017032f0"
+ dependencies:
+ bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git"
+ crypto-js "^3.1.4"
+ utf8 "^2.1.1"
+ xhr2 "*"
+ xmlhttprequest "*"
+
+webidl-conversions@^4.0.0, webidl-conversions@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+
+webpack-sources@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"
+ dependencies:
+ source-list-map "^2.0.0"
+ source-map "~0.5.3"
+
+webpack@^2.2.1:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.7.0.tgz#b2a1226804373ffd3d03ea9c6bd525067034f6b1"
+ dependencies:
+ acorn "^5.0.0"
+ acorn-dynamic-import "^2.0.0"
+ ajv "^4.7.0"
+ ajv-keywords "^1.1.1"
+ async "^2.1.2"
+ enhanced-resolve "^3.3.0"
+ interpret "^1.0.0"
+ json-loader "^0.5.4"
+ json5 "^0.5.1"
+ loader-runner "^2.3.0"
+ loader-utils "^0.2.16"
+ memory-fs "~0.4.1"
+ mkdirp "~0.5.0"
+ node-libs-browser "^2.0.0"
+ source-map "^0.5.3"
+ supports-color "^3.1.0"
+ tapable "~0.2.5"
+ uglify-js "^2.8.27"
+ watchpack "^1.3.1"
+ webpack-sources "^1.0.1"
+ yargs "^6.0.0"
+
+websocket-driver@>=0.3.6:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb"
+ dependencies:
+ http-parser-js ">=0.4.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.2.tgz#0e18781de629a18308ce1481650f67ffa2693a5d"
+
+whatwg-encoding@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4"
+ dependencies:
+ iconv-lite "0.4.13"
+
+whatwg-fetch@>=0.10.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
+
+whatwg-url@^6.1.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.2.1.tgz#db8fb96d7f02661af266e3cefc18425923900a00"
+ dependencies:
+ lodash.sortby "^4.7.0"
+ tr46 "^1.0.0"
+ webidl-conversions "^4.0.1"
+
+which-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+
+which-module@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+
+which@1, which@^1.0.5, which@^1.1.1, which@^1.2.1, which@^1.2.12, which@^1.2.4, which@^1.2.9:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
+ dependencies:
+ isexe "^2.0.0"
+
+which@~1.0.5:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.0.9.tgz#460c1da0f810103d0321a9b633af9e575e64486f"
+
+wide-align@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
+ dependencies:
+ string-width "^1.0.2"
+
+window-size@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+
+window-size@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
+
+window-size@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
+
+winston@2.1.x:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e"
+ dependencies:
+ async "~1.0.0"
+ colors "1.0.x"
+ cycle "1.0.x"
+ eyes "0.1.x"
+ isstream "0.1.x"
+ pkginfo "0.3.x"
+ stack-trace "0.0.x"
+
+wordwrap@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+
+wordwrap@^1.0.0, wordwrap@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+
+wordwrap@~0.0.2:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+
+wrap-ansi@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+wreck@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/wreck/-/wreck-6.3.0.tgz#a1369769f07bbb62d6a378336a7871fc773c740b"
+ dependencies:
+ boom "2.x.x"
+ hoek "2.x.x"
+
+write-file-atomic@^1.1.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ slide "^1.1.5"
+
+write-file-stdout@0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/write-file-stdout/-/write-file-stdout-0.0.2.tgz#c252d7c7c5b1b402897630e3453c7bfe690d9ca1"
+
+write@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+ dependencies:
+ mkdirp "^0.5.1"
+
+ws@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018"
+ dependencies:
+ options ">=0.0.5"
+ ultron "1.0.x"
+
+ws@1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f"
+ dependencies:
+ options ">=0.0.5"
+ ultron "1.0.x"
+
+wtf-8@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a"
+
+xhr2@*:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f"
+
+xhr2@0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.3.tgz#cbfc4759a69b4a888e78cf4f20b051038757bd11"
+
+xhr@^2.2.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.4.0.tgz#e16e66a45f869861eeefab416d5eff722dc40993"
+ dependencies:
+ global "~4.3.0"
+ is-function "^1.0.1"
+ parse-headers "^2.0.0"
+ xtend "^4.0.0"
+
+xml-name-validator@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
+
+xmldom@^0.1.19:
+ version "0.1.27"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
+
+xmlhttprequest-ssl@1.5.3:
+ version "1.5.3"
+ resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d"
+
+xmlhttprequest@*:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
+
+xss-filters@^1.2.6:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/xss-filters/-/xss-filters-1.2.7.tgz#59fa1de201f36f2f3470dcac5f58ccc2830b0a9a"
+
+xtend@4.0.1, "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+xtend@~2.1.1, xtend@~2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b"
+ dependencies:
+ object-keys "~0.4.0"
+
+xtend@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a"
+
+y18n@^3.2.0, y18n@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+
+yallist@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+
+yargs-parser@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4"
+ dependencies:
+ camelcase "^3.0.0"
+ lodash.assign "^4.0.6"
+
+yargs-parser@^4.2.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
+ dependencies:
+ camelcase "^3.0.0"
+
+yargs-parser@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
+ dependencies:
+ camelcase "^3.0.0"
+
+yargs-parser@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9"
+ dependencies:
+ camelcase "^4.1.0"
+
+yargs@^1.2.6:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.3.3.tgz#054de8b61f22eefdb7207059eaef9d6b83fb931a"
+
+yargs@^3.28.0, yargs@^3.5.4:
+ version "3.32.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995"
+ dependencies:
+ camelcase "^2.0.1"
+ cliui "^3.0.3"
+ decamelize "^1.1.1"
+ os-locale "^1.4.0"
+ string-width "^1.0.1"
+ window-size "^0.1.4"
+ y18n "^3.2.0"
+
+yargs@^4.7.1:
+ version "4.8.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
+ dependencies:
+ cliui "^3.2.0"
+ decamelize "^1.1.1"
+ get-caller-file "^1.0.1"
+ lodash.assign "^4.0.3"
+ os-locale "^1.4.0"
+ read-pkg-up "^1.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^1.0.1"
+ which-module "^1.0.0"
+ window-size "^0.2.0"
+ y18n "^3.2.1"
+ yargs-parser "^2.4.1"
+
+yargs@^6.0.0, yargs@^6.5.0:
+ version "6.6.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
+ dependencies:
+ camelcase "^3.0.0"
+ cliui "^3.2.0"
+ decamelize "^1.1.1"
+ get-caller-file "^1.0.1"
+ os-locale "^1.4.0"
+ read-pkg-up "^1.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^1.0.2"
+ which-module "^1.0.0"
+ y18n "^3.2.1"
+ yargs-parser "^4.2.0"
+
+yargs@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
+ dependencies:
+ camelcase "^3.0.0"
+ cliui "^3.2.0"
+ decamelize "^1.1.1"
+ get-caller-file "^1.0.1"
+ os-locale "^1.4.0"
+ read-pkg-up "^1.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^1.0.2"
+ which-module "^1.0.0"
+ y18n "^3.2.1"
+ yargs-parser "^5.0.0"
+
+yargs@^8.0.1:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360"
+ dependencies:
+ camelcase "^4.1.0"
+ cliui "^3.2.0"
+ decamelize "^1.1.1"
+ get-caller-file "^1.0.1"
+ os-locale "^2.0.0"
+ read-pkg-up "^2.0.0"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^2.0.0"
+ which-module "^2.0.0"
+ y18n "^3.2.1"
+ yargs-parser "^7.0.0"
+
+yargs@~1.2.6:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b"
+ dependencies:
+ minimist "^0.1.0"
+
+yargs@~3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+ dependencies:
+ camelcase "^1.0.2"
+ cliui "^2.1.0"
+ decamelize "^1.0.0"
+ window-size "0.1.0"
+
+yazl@^2.1.0:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.2.tgz#14cb19083e1e25a70092c1588aabe0f4e4dd4d88"
+ dependencies:
+ buffer-crc32 "~0.2.3"
+
+yeast@0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"