diff --git a/.travis.yml b/.travis.yml index b5d161ddf..a53c67052 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,17 +11,17 @@ node_js: - "4" before_script: - - "npm install" - - "npm install -g electron-prebuilt@1.0.1" + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - "sleep 3" # give xvfb some time to start + - "curl https://install.meteor.com/ | sh" + - "npm install -g electron-prebuilt@1.2.2" - "npm install -g meteor-build-client" - - "gulp update-nodes" script: - - "npm test" + - "npm run ci" notifications: email: - mist@ethereum.org - - diff --git a/README.md b/README.md index 5cdb9269b..811aec818 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,13 @@ Once a Mist version is released the Meteor frontend part is bundled using `meteo Requirements: -* Electron v1.2.2 +* Electron v1.2.5 * Node v4.3.0 or above To run mist in development you need [Node.js NPM](https://nodejs.org) and [Meteor](https://www.meteor.com/install) and electron installed: $ curl https://install.meteor.com/ | sh - $ npm install -g electron-prebuilt@1.2.2 + $ npm install -g electron-prebuilt@1.2.5 $ npm install -g gulp ### Installation @@ -86,13 +86,13 @@ In the original window you can then start Mist using wallet mode: $ electron . --mode wallet -### Passing options to Geth +### Passing options to Geth/Eth -You can pass command-line options directly to Geth by placing them after `--` in -the command-line invocation: +You can pass command-line options directly to Geth/Eth by prefixing them +with `--node-`: ```bash -$ electron . --mode mist -- --rpcport 19343 --networkid 2 +$ electron . --mode mist --node-rpcport 19343 --node-networkid 2 ``` @@ -102,9 +102,12 @@ To run a private network you will need to set the `networkdid`, `ipcpath` and `datadir` flags: ```bash -$ electron . -- --networkid 1234 --ipcpath ~/Library/Ethereum/geth.ipc --datadir ~/Library/Ethereum/privatenet +$ electron . --ipcpath ~/Library/Ethereum/geth.ipc --node-networkid 1234 --node-datadir ~/Library/Ethereum/privatenet ``` +_NOTE: since `ipcpath` is also a Mist option you do not need to also include a +`--node-ipcpath` option._ + You can also run `geth` separately yourself with the same options prior to start Mist normally. @@ -117,13 +120,8 @@ To create a binaries you need to install the following tools: // tools for the windows binaries $ brew install Caskroom/cask/xquartz $ brew install wine - - // install meteor-build-client $ npm install -g meteor-build-client - // install gulp - $ npm install -g gulp - To generate the binaries simply run: $ cd mist diff --git a/gulpfile.js b/gulpfile.js index b4e26211c..8da1d14bc 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -7,9 +7,10 @@ var packager = require('electron-packager'); var spawn = require('child_process').spawn; var merge = require('merge-stream'); var rename = require("gulp-rename"); -var download = require('gulp-download'); +var download = require('gulp-download-stream'); var decompress = require('gulp-decompress'); var tap = require("gulp-tap"); +const mocha = require('gulp-spawn-mocha'); // const zip = require('gulp-zip'); // var zip = require('gulp-zip'); // var zip = require('gulp-jszip'); @@ -38,7 +39,7 @@ var type = 'mist'; var filenameLowercase = 'mist'; var filenameUppercase = 'Mist'; var applicationName = 'Mist'; -var electronVersion = '1.2.2'; +var electronVersion = '1.2.5'; var gethVersion = '1.4.7'; var nodeUrls = { 'darwin-x64': 'https://github.com/ethereum/go-ethereum/releases/download/v1.4.7/geth-OSX-2016061509421-1.4.7-667a386.zip', @@ -81,7 +82,6 @@ if(_.contains(options.platform, 'all')) { 'win32-x64' ]; } -console.log('Bundling platforms: ', osVersions); // Helpers @@ -278,7 +278,7 @@ gulp.task('bundling-interface', ['clean:dist', 'copy-files'], function(cb) { } else { console.log('Pulling https://github.com/ethereum/meteor-dapp-wallet/tree/'+ options.walletSource +' "'+ options.walletSource +'" branch...'); exec('cd interface/ && meteor-build-client ../dist_'+ type +'/app/interface/ -p "" &&'+ - 'cd ../dist_'+ type +'/ && git clone https://github.com/ethereum/meteor-dapp-wallet.git && cd meteor-dapp-wallet/app && meteor-build-client ../../app/interface/wallet -p "" && cd ../../ && rm -rf meteor-dapp-wallet', function (err, stdout, stderr) { + 'cd ../dist_'+ type +'/ && git clone --depth 1 https://github.com/ethereum/meteor-dapp-wallet.git && cd meteor-dapp-wallet/app && meteor-build-client ../../app/interface/wallet -p "" && cd ../../ && rm -rf meteor-dapp-wallet', function (err, stdout, stderr) { console.log(stdout); console.log(stderr); @@ -299,6 +299,8 @@ gulp.task('copy-i18n', ['copy-files', 'bundling-interface'], function() { }); gulp.task('create-binaries', ['copy-i18n'], function(cb) { + console.log('Bundling platforms: ', osVersions); + packager({ dir: './dist_'+ type +'/app/', out: './dist_'+ type +'/', @@ -499,8 +501,8 @@ gulp.task('taskQueue', [ 'create-binaries', 'change-files', //'cleanup-files', - 'rename-folders', - // 'zip' + 'rename-folders' + // 'zip', ]); // DOWNLOAD nodes @@ -531,6 +533,20 @@ gulp.task('wallet-checksums', [ 'getChecksums' ]); -gulp.task('default', ['mist']); +gulp.task('test-wallet', function() { + return gulp.src([ + './test/wallet/*.test.js' + ]) + .pipe(mocha({ + timeout: 60000, + ui: 'exports', + reporter: 'spec' + })); +}); + + + +gulp.task('default', ['mist']); + diff --git a/interface/.meteor/release b/interface/.meteor/release index 940e0b5d4..b2d8cda2d 100644 --- a/interface/.meteor/release +++ b/interface/.meteor/release @@ -1 +1 @@ -METEOR@1.3.2.4 +METEOR@1.3.3 diff --git a/interface/.meteor/versions b/interface/.meteor/versions index 3d3aa60d2..6eaecfd85 100644 --- a/interface/.meteor/versions +++ b/interface/.meteor/versions @@ -2,41 +2,41 @@ agnito:simptip@0.0.1 aldeed:simple-schema@1.3.3 alexvandesande:identicon@2.0.2 -allow-deny@1.0.4 +allow-deny@1.0.5 amplify@1.0.0 -autoupdate@1.2.9 -babel-compiler@6.6.4 -babel-runtime@0.1.8 -base64@1.0.8 -binary-heap@1.0.8 -blaze@2.1.7 +autoupdate@1.2.10 +babel-compiler@6.8.0 +babel-runtime@0.1.9 +base64@1.0.9 +binary-heap@1.0.9 +blaze@2.1.8 blaze-html-templates@1.0.4 -blaze-tools@1.0.8 -boilerplate-generator@1.0.8 -caching-compiler@1.0.4 +blaze-tools@1.0.9 +boilerplate-generator@1.0.9 +caching-compiler@1.0.5 caching-html-compiler@1.0.6 -callback-hook@1.0.8 +callback-hook@1.0.9 cfs:http-methods@0.0.32 -check@1.2.1 +check@1.2.2 chuangbo:cookie@1.1.0 -coffeescript@1.0.17 +coffeescript@1.1.0 cosmos:browserify@0.10.0 ddp@1.2.5 -ddp-client@1.2.7 -ddp-common@1.2.5 -ddp-server@1.2.6 +ddp-client@1.2.8 +ddp-common@1.2.6 +ddp-server@1.2.7 deps@1.0.12 -diff-sequence@1.0.5 -ecmascript@0.4.3 -ecmascript-runtime@0.2.10 -ejson@1.0.11 +diff-sequence@1.0.6 +ecmascript@0.4.4 +ecmascript-runtime@0.2.11 +ejson@1.0.12 ethereum:accounts@0.3.10 ethereum:blocks@0.3.1 -ethereum:dapp-styles@0.5.1 -ethereum:elements@0.7.0 +ethereum:dapp-styles@0.5.5 +ethereum:elements@0.7.1 ethereum:tools@0.5.2 ethereum:web3@0.15.3 -fastclick@1.0.11 +fastclick@1.0.12 frozeman:animation-helper@0.2.6 frozeman:global-notifications@0.2.1 frozeman:persistent-minimongo@0.1.8 @@ -44,59 +44,59 @@ frozeman:persistent-minimongo2@0.3.4 frozeman:reactive-timer@0.1.7 frozeman:storage@0.1.9 frozeman:template-var@1.2.3 -geojson-utils@1.0.8 +geojson-utils@1.0.9 hot-code-push@1.0.4 -html-tools@1.0.9 -htmljs@1.0.9 -http@1.1.5 -id-map@1.0.7 +html-tools@1.0.10 +htmljs@1.0.10 +http@1.1.6 +id-map@1.0.8 jeeeyul:moment-with-langs@2.12.1 -jquery@1.11.8 -launch-screen@1.0.11 -less@2.6.0 +jquery@1.11.9 +launch-screen@1.0.12 +less@2.6.1 livedata@1.0.18 -localstorage@1.0.9 -logging@1.0.12 -meteor@1.1.14 +localstorage@1.0.11 +logging@1.0.13 +meteor@1.1.15 meteor-base@1.0.4 meteorspark:util@0.2.0 -minifier-css@1.1.11 -minifier-js@1.1.11 -minimongo@1.0.16 +minifier-css@1.1.12 +minifier-js@1.1.12 +minimongo@1.0.17 mobile-experience@1.0.4 mobile-status-bar@1.0.12 -modules@0.6.1 -modules-runtime@0.6.3 -mongo@1.1.7 -mongo-id@1.0.4 +modules@0.6.2 +modules-runtime@0.6.4 +mongo@1.1.8 +mongo-id@1.0.5 mrt:jquery-ui-sortable@1.10.3 -npm-mongo@1.4.43 +npm-mongo@1.4.44 numeral:numeral@1.5.3_1 -observe-sequence@1.0.11 -ordered-dict@1.0.7 -promise@0.6.7 +observe-sequence@1.0.12 +ordered-dict@1.0.8 +promise@0.7.2 raix:eventemitter@0.1.3 raix:handlebar-helpers@0.2.5 random@1.0.9 -reactive-dict@1.1.7 -reactive-var@1.0.9 -reload@1.1.8 -retry@1.0.7 -routepolicy@1.0.10 +reactive-dict@1.1.8 +reactive-var@1.0.10 +reload@1.1.9 +retry@1.0.8 +routepolicy@1.0.11 sacha:spin@2.3.1 -session@1.1.5 -spacebars@1.0.11 -spacebars-compiler@1.0.11 -standard-minifier-css@1.0.6 -standard-minifier-js@1.0.6 +session@1.1.6 +spacebars@1.0.12 +spacebars-compiler@1.0.12 +standard-minifier-css@1.0.7 +standard-minifier-js@1.0.7 standard-minifiers@1.0.6 -tap:i18n@1.8.0 +tap:i18n@1.8.2 tap:i18n-bundler@0.3.0 -templating@1.1.9 +templating@1.1.10 templating-tools@1.0.4 -tracker@1.0.13 +tracker@1.0.14 ui@1.0.11 -underscore@1.0.8 -url@1.0.9 -webapp@1.2.8 +underscore@1.0.9 +url@1.0.10 +webapp@1.2.9 webapp-hashing@1.0.9 diff --git a/interface/client/appStart.js b/interface/client/appStart.js index c44ecd32c..c579dce44 100644 --- a/interface/client/appStart.js +++ b/interface/client/appStart.js @@ -7,7 +7,7 @@ if(location.hash) // set browser as default tab if(!LocalStore.get('selectedTab')) - LocalStore.set('selectedTab', 'browser'); + LocalStore.set('selectedTab', 'wallet'); /** The init function of Mist @@ -31,20 +31,16 @@ mistInit = function(){ url: 'https://ethereum.org', position: 0 }); - - // wait for accounts and blocks to be initialized below - Meteor.setTimeout(function() { - Tabs.insert({ - _id: 'wallet', - url: 'https://wallet.ethereum.org', - position: 1, - permissions: { - accounts: web3.eth.accounts - } - }); - }, 1500); } + Tabs.upsert({_id: 'wallet'}, { + url: 'https://wallet.ethereum.org', + position: 1, + permissions: { + admin: true + } + }); + EthAccounts.init(); EthBlocks.init(); }; diff --git a/interface/client/styles/menu.import.less b/interface/client/styles/menu.import.less index 486912d3f..ab3ceb7cd 100644 --- a/interface/client/styles/menu.import.less +++ b/interface/client/styles/menu.import.less @@ -210,11 +210,10 @@ aside.sidebar { } .see-all { - // display: none; position: absolute; + margin-top: -4px; top: @gridHeight * 10; width: 100%; - // background-color: #FFF; button { font-style: italic; diff --git a/interface/client/templates/elements/img.js b/interface/client/templates/elements/img.js index cc0e0fa61..6e7e33502 100644 --- a/interface/client/templates/elements/img.js +++ b/interface/client/templates/elements/img.js @@ -11,11 +11,6 @@ The img template @constructor */ -Template['elements_img'].onRendered(function(){ - -}); - - Template['elements_img'].helpers({ /** This helper will preload the image, and then inject it later after its loaded diff --git a/interface/client/templates/layout/browserBar.js b/interface/client/templates/layout/browserBar.js index 8e1b876cb..9eb30aaf7 100644 --- a/interface/client/templates/layout/browserBar.js +++ b/interface/client/templates/layout/browserBar.js @@ -11,6 +11,7 @@ The browserBar template @constructor */ + Template['layout_browserBar'].onRendered(function(){ var template = this; }); diff --git a/interface/client/templates/popupWindows/onboardingScreen.html b/interface/client/templates/popupWindows/onboardingScreen.html index c540d653b..4774ffbab 100644 --- a/interface/client/templates/popupWindows/onboardingScreen.html +++ b/interface/client/templates/popupWindows/onboardingScreen.html @@ -154,7 +154,7 @@

{{i18n "mist.popupWindows.onboar


- +

@@ -178,8 +178,11 @@

{{i18n "mist.popupWindows.onboarding.protectTitle"}}

{{i18n "mist.popupWindows.onboarding.creating"}}

{{else}} - - + + +

+ + {{/if}} diff --git a/interface/client/templates/popupWindows/onboardingScreen.js b/interface/client/templates/popupWindows/onboardingScreen.js index 74cf65db8..e40996e08 100644 --- a/interface/client/templates/popupWindows/onboardingScreen.js +++ b/interface/client/templates/popupWindows/onboardingScreen.js @@ -254,9 +254,9 @@ Template['popupWindows_onboardingScreen_importAccount'].events({ /** On show password - @event click #show-password + @event click .show-password */ - 'click #show-password': function(e){ + 'click .show-password': function(e){ TemplateVar.set('showPassword', e.currentTarget.checked) }, /** @@ -322,6 +322,18 @@ The onboardingScreen password template @constructor */ +Template['popupWindows_onboardingScreen_password'].helpers({ + /** + Show password + + @method showPassword + */ + 'passwordInputType': function() { + return TemplateVar.get('passwordInputType')? 'text' : 'password' ; + } +}) + + Template['popupWindows_onboardingScreen_password'].events({ /** Clear the form @@ -333,6 +345,14 @@ Template['popupWindows_onboardingScreen_password'].events({ template.find('input.password-repeat').value = ''; }, /** + On show password + + @event click .show-password + */ + 'click .show-password': function(e){ + TemplateVar.set('passwordInputType', e.currentTarget.checked) + }, + /** Password checks @event click button[type="button"] diff --git a/interface/client/templates/popupWindows/splashScreen.html b/interface/client/templates/popupWindows/splashScreen.html index 1cf165530..008408034 100644 --- a/interface/client/templates/popupWindows/splashScreen.html +++ b/interface/client/templates/popupWindows/splashScreen.html @@ -21,7 +21,9 @@

{{#if TemplateVar.get "showProgressBar"}} - + {{#if TemplateVar.get "showStateProgressBar"}} + + {{/if}} {{/if}} \ No newline at end of file diff --git a/interface/client/templates/popupWindows/splashScreen.js b/interface/client/templates/popupWindows/splashScreen.js index b588ce249..8d47c9e0e 100644 --- a/interface/client/templates/popupWindows/splashScreen.js +++ b/interface/client/templates/popupWindows/splashScreen.js @@ -100,8 +100,10 @@ Template['popupWindows_splashScreen'].onCreated(function(){ if(web3.net.peerCount > 0) { // Check which state we are - if ( lastSyncData.pulledStates != Math.round(lastSyncData._displayState) - || lastSyncData.knownStates != Math.round(lastSyncData._displayKnownStates)) { + if ( 0 < lastSyncData._displayKnownStates && ( + lastSyncData.pulledStates != Math.round(lastSyncData._displayState) + || lastSyncData.knownStates != Math.round(lastSyncData._displayKnownStates)) + ) { // Mostly downloading new states translationString = 'mist.startScreen.nodeSyncInfoStates'; @@ -181,16 +183,13 @@ Template['popupWindows_splashScreen'].helpers({ if (!(syncData._displayBlock > -1)) { // initialize the display numbers syncData._displayBlock = Number(syncData.currentBlock); - syncData._displayState = Number(syncData.pulledStates); - syncData._displayKnownStates = Number(syncData.knownStates); - + syncData._displayState = Number(syncData.pulledStates || 0); + syncData._displayKnownStates = Number(syncData.knownStates || 0); } else { // Increment each them slowly to match target number - syncData._displayBlock = syncData._displayBlock + (Number(syncData.currentBlock) - syncData._displayBlock) / 10; - - syncData._displayState = syncData._displayState + (Number(syncData.pulledStates) - syncData._displayState) / 10; - - syncData._displayKnownStates = syncData._displayKnownStates + (Number(syncData.knownStates) - syncData._displayKnownStates) / 10; + syncData._displayBlock += (Number(syncData.currentBlock) - syncData._displayBlock) / 10; + syncData._displayState += (Number(syncData.pulledStates || 0) - syncData._displayState) / 10; + syncData._displayKnownStates += (Number(syncData.knownStates || 0) - syncData._displayKnownStates) / 10; }; // Create the fancy strings @@ -202,7 +201,10 @@ Template['popupWindows_splashScreen'].helpers({ var translatedMessage = TAPi18n.__(translationString, syncData); // Calculates both progress bars - var stateProgress = (lastSyncData._displayState / lastSyncData._displayKnownStates) * 100; + var stateProgress = null; + if (0 < lastSyncData._displayKnownStates) { + stateProgress = (lastSyncData._displayState / lastSyncData._displayKnownStates) * 100; + } var progress = ((lastSyncData._displayBlock - Number(lastSyncData.startingBlock)) / (Number(lastSyncData._highestBlock) - Number(lastSyncData.startingBlock))) * 100 ; @@ -214,7 +216,10 @@ Template['popupWindows_splashScreen'].helpers({ if(_.isFinite(progress)) { TemplateVar.set(template, 'showProgressBar', true); TemplateVar.set(template, 'progress', progress); - TemplateVar.set(template, 'stateProgress', stateProgress); + if (null !== stateProgress) { + TemplateVar.set(template, 'showStateProgressBar', true); + TemplateVar.set(template, 'stateProgress', stateProgress); + } } }, 100); diff --git a/interface/client/templates/views/tab.html b/interface/client/templates/views/tab.html index ee2637a60..86838dc2e 100644 --- a/interface/client/templates/views/tab.html +++ b/interface/client/templates/views/tab.html @@ -1,14 +1,14 @@ \ No newline at end of file diff --git a/interface/i18n/app.en.i18n.json b/interface/i18n/app.en.i18n.json index c9474bad0..17dcaea12 100644 --- a/interface/i18n/app.en.i18n.json +++ b/interface/i18n/app.en.i18n.json @@ -11,7 +11,7 @@ "ok": "OK", "cancel": "Cancel", "save": "Save", - "edit": "edit", + "edit": "Edit", "send": "Send", "next": "Next", "previous": "Previous", @@ -31,4 +31,4 @@ "on": "on", "per": "per" } -} \ No newline at end of file +} diff --git a/interface/i18n/app.kr.i18n.json b/interface/i18n/app.kr.i18n.json deleted file mode 100644 index dd15718b3..000000000 --- a/interface/i18n/app.kr.i18n.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "app": { - "loading": "로딩 중...", - "offline": "연결실패, 오프라인입니까?", - "logginIn": "로그인 중..." - }, - "error": { - "insufficientRights": "요청하신 명령을 실행할 권한이 없습니다." - }, - "buttons": { - "ok": "확인", - "cancel": "취소", - "save": "저장", - "edit": "수정", - "send": "보내기", - "next": "다음", - "previous": "이전", - "back": "뒤로", - "skip": "건너뛰기", - "sending": "보내는 중...", - "create": "만들기", - "tryToReconnect": "재연결 시도" - }, - "commonWords": { - "you": "당신", - "send": "보내기", - "or": "또는", - "of": "의", - "with": "와", - "and": "그리고", - "on": "위에", - "per": "당" - } -} diff --git a/interface/i18n/app.al.i18n.json b/interface/i18n/app.sq.i18n.json similarity index 100% rename from interface/i18n/app.al.i18n.json rename to interface/i18n/app.sq.i18n.json diff --git a/interface/i18n/mist.de.i18n.json b/interface/i18n/mist.de.i18n.json index a403a5926..7369a5f8e 100644 --- a/interface/i18n/mist.de.i18n.json +++ b/interface/i18n/mist.de.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "Über __app__", + "checkForUpdates": "Nach Aktualisierungen suchen...", + "services": "Dienste", "hide": "__app__ ausblenden", "hideOthers": "Andere ausblenden", "showAll": "Alle einblenden", @@ -20,7 +22,8 @@ }, "view": { "label": "Ansicht", - "fullscreen": "Vollbildmodus" + "fullscreen": "Vollbildmodus", + "languages": "Change language" }, "accounts": { "label": "Konten", @@ -95,7 +98,7 @@ "nodeConnectionTimeout": "Ethereum Node konnte nicht gestartet werden!
Wenn Sie Geth installiert haben,, verwenden Sie bitte diesen Befehl, um Geth zu starten:
geth --ipcpath __path__

oder senden Sie einen Fehlerreport", "nodeBinaryNotFound": "Keine Programmdatei für den Ethereum Node gefunden!
Bitte starten Sie den Ethereum Node manuell. ", "nodeSyncing": "Ethereum Node muss synchronisiert werden, bitte warten...", - "nodeSyncInfo": "Block __currentBlock__ von __highestBlock__ wird heruntergeladen.", + "nodeSyncInfo": "Block __displayBlock__ von __highestBlock__ wird heruntergeladen.", "nodeSyncConnecting": "Suche nach Peers...", "nodeSyncProcessing": "Blöcke werden verarbeitet, bitte warten...", "peerSearchTimeout": "Peer-Suche überspringen" diff --git a/interface/i18n/mist.en.i18n.json b/interface/i18n/mist.en.i18n.json index fcf65e8c3..7dff2bf58 100644 --- a/interface/i18n/mist.en.i18n.json +++ b/interface/i18n/mist.en.i18n.json @@ -2,9 +2,10 @@ "mist": { "applicationMenu": { "app": { - "checkForUpdates": "Check for updates...", "label": "__app__", "about": "About __app__", + "checkForUpdates": "Check for updates...", + "services": "Services", "hide": "Hide __app__", "hideOthers": "Hide Others", "showAll": "Show All", @@ -21,7 +22,25 @@ }, "view": { "label": "View", - "fullscreen": "Toggle Fullscreen" + "fullscreen": "Toggle Fullscreen", + "languages": "Change language", + "default": "Default", + "langCodes" : { + "de": "Deutsch", + "en": "English", + "es": "Español", + "fa": "فارسى", + "fr": "Français", + "it": "Italiano", + "ja": "日本語", + "ko": "한국어 ", + "nl": "Nederlands", + "nb": "Norsk", + "pt": "Português", + "sq": "Shqip", + "zh": "普通話", + "zh-TW": "國語" + } }, "accounts": { "label": "Accounts", @@ -148,7 +167,7 @@ "title": { "sendTransaction": "Send transaction", "contractExecution": "Execute contract", - "createContract": "Create contract" + "createContract": "Create contract" }, "contractExecutionInfo": "You are about to execute a function on a contract. This might involve transfer of value.", "contractCreationInfo": "You are about to create a contract from the provided data.", @@ -156,7 +175,7 @@ "unlocking": "Confirming...", "createContract": "Create contract", "estimatedFee": "Estimated fee consumption", - "estimatedGasError": "Data can't be executed, so it will use all provided gas.", + "estimatedGasError": "Execution failed. Consumed all provided gas.", "gasPrice": "Gas price", "perMillionGas": "ether per million gas", "gasLimit": "Provide maximum fee", @@ -170,7 +189,7 @@ } }, "onboarding": { - "description" : "Ethereum is a decentralized platform for building apps on a blockchain: tamper-proof software that can transfer value and property and lives forever", + "description" : "Ethereum is a public blockchain that features a turing complete programming for building solid, decentralized applications.", "goToTestnet" : "Use the test network", "goToTestnetDescription" : "Test the technology freely in a sandboxed testnet, without using real ether.", "gotoMainnet" : "Use the main network", @@ -199,7 +218,7 @@ "syncMessageWithStates": "Block __displayBlock__ of __highestBlockString__ (Chain structure __statesPercent__%)", "tutorial1Description" : "

Now the only thing left to do is wait for the download to finish. Here's some reading suggestions:

Make your own money

Make a cryptocurrency with a fixed market supply, tokens representing real world assets, etc

", "tutorial2Description" : "

Create a crowdsale

Raise funds for a common goal, fully trustable without a third party. Sidestep the hurdle of traditional funding system and go directly to the source by funding an organization via the blockchain.

", - "tutorial3Description" : "

Blockchain Organization

Create an autonomous organization with unbreakable rules on how money can be spent and who can make the decisions. Let your backers take an active role on how the money is spent

", + "tutorial3Description" : "

Create a blockchain organization

Create an autonomous organization with rules on spending money and making decisions for you and your investors.

", "buttons": { "showPassword": "Show password", "importAccount": "Import account", @@ -219,4 +238,4 @@ "checksumAlert":"This address looks valid, but it doesn't have some security features that will protect you against typos, so double check you have the right one. If provided, check if the security icon matches.", "identiconHelper": "This is a security icon, if there's any change on the address the resulting icon should be a completely different one" } -} \ No newline at end of file +} diff --git a/interface/i18n/mist.es.i18n.json b/interface/i18n/mist.es.i18n.json index cd47f84d4..be592ce81 100644 --- a/interface/i18n/mist.es.i18n.json +++ b/interface/i18n/mist.es.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "Sobre __app__", + "checkForUpdates": "Buscar actualización...", + "services": "Servicios", "hide": "Ocultar __app__", "hideOthers": "Ocultar otros", "showAll": "Mostrar todo", @@ -20,7 +22,8 @@ }, "view": { "label": "Ver", - "fullscreen": "Pantalla Completa" + "fullscreen": "Pantalla Completa", + "languages": "Change language" }, "accounts": { "label": "Cuentas", @@ -95,7 +98,7 @@ "nodeConnectionTimeout": "No se pudo iniciar un nodo Ethereum!
Si has instalado Geth, utiliza este comando para ejecutarlo:
geth --ipcpath __path__

O informa del problema ", "nodeBinaryNotFound": "No se ha encontrado el binario del nodo Ethereum!
Por favor, inicie antes uno manualmente. ", "nodeSyncing": "El nodo de Ethereum necesita sincronizarse, por favor espere...", - "nodeSyncInfo": "Descargando bloque __currentBlock__ de __highestBlock__.", + "nodeSyncInfo": "Descargando bloque __displayBlock__ de __highestBlock__.", "nodeSyncConnecting": "Buscando pares...", "nodeSyncProcessing": "Procesando bloques, por favor espere...", "peerSearchTimeout": "Omitir la búsqueda de pares" diff --git a/interface/i18n/mist.fa.i18n.json b/interface/i18n/mist.fa.i18n.json new file mode 100644 index 000000000..732e0297b --- /dev/null +++ b/interface/i18n/mist.fa.i18n.json @@ -0,0 +1,4 @@ +{ + "mist": { + } +} \ No newline at end of file diff --git a/interface/i18n/mist.fr.i18n.json b/interface/i18n/mist.fr.i18n.json index 2dcb6addb..a9572049c 100644 --- a/interface/i18n/mist.fr.i18n.json +++ b/interface/i18n/mist.fr.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "À propos de __app__", + "checkForUpdates": "Chercher des mises à jour...", + "services": "Services", "hide": "Masquer __app__", "hideOthers": "Masquer les autres", "showAll": "Afficher tout", @@ -20,7 +22,8 @@ }, "view": { "label": "Voir", - "fullscreen": "Basculer en mode plein écran" + "fullscreen": "Basculer en mode plein écran", + "languages": "Change language" }, "accounts": { "label": "Comptes", @@ -93,7 +96,7 @@ "nodeConnectionTimeout": "Echec du démarrage du nœud Ethereum !
Si vous avez installé Geth, utilisez cette commande pour le lancer :
geth --ipcpath __path__

Ou signalez le problème ", "nodeBinaryNotFound": "Pas de binaire du nœud Ethereum trouvé !
Veuillez en lancer d'abord un manuellement. ", "nodeSyncing": "Le nœud Ethereum se synchronise, veuillez patienter...", - "nodeSyncInfo": "Télechargement du bloc __currentBlock__ depuis le bloc __highestBlock__.", + "nodeSyncInfo": "Télechargement du bloc __displayBlock__ depuis le bloc __highestBlock__.", "nodeSyncConnecting": "À la recherche de pairs...", "nodeSyncProcessing": "Traitement de bloc, veuillez patienter...", "peerSearchTimeout": "Recherche de pairs ignorée" diff --git a/interface/i18n/mist.it.i18n.json b/interface/i18n/mist.it.i18n.json index a6828b5fc..b021b4e01 100644 --- a/interface/i18n/mist.it.i18n.json +++ b/interface/i18n/mist.it.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "Info su __app__", + "checkForUpdates": "Controlla aggiornamenti...", + "services": "Servizi", "hide": "Nascondi __app__", "hideOthers": "Nascondi il resto", "showAll": "Mostra tutto", @@ -20,7 +22,8 @@ }, "view": { "label": "Visualizza", - "fullscreen": "Schermo intero" + "fullscreen": "Schermo intero", + "languages": "Change language" }, "accounts": { "label": "Accounts", @@ -95,7 +98,7 @@ "nodeConnectionTimeout": "Impossibile avviare un nodo Ethereum!
Se hai installato Geth, usa questo comando per eseguirlo:
geth --ipcpath __path__

o riporta il problema ", "nodeBinaryNotFound": "Impossibile trovare l'eseguibile del nodo Ethereum !
Per favore avvialo manualmente prima. ", "nodeSyncing": "Il nodo Ethereum deve sincronizzarsi, attendere prego...", - "nodeSyncInfo": "Scaricamento blocco __currentBlock__ di __highestBlock__.", + "nodeSyncInfo": "Scaricamento blocco __displayBlock__ di __highestBlock__.", "nodeSyncConnecting": "Alla ricerca di nodi...", "nodeSyncProcessing": "Elaborazione blocchi, attendere prego...", "privateChainTimeout": "Salta ricerca di nodi" diff --git a/interface/i18n/mist.ja.i18n.json b/interface/i18n/mist.ja.i18n.json index 6f8c67df9..a5f71d637 100644 --- a/interface/i18n/mist.ja.i18n.json +++ b/interface/i18n/mist.ja.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "__app__ について", + "checkForUpdates": "アップデートの確認...", + "services": "サービス", "hide": "__app__ を隠す", "hideOthers": "ほかを隠す", "showAll": "すべてを表示", @@ -20,7 +22,8 @@ }, "view": { "label": "ビュー", - "fullscreen": "フルスクリーンをトグルする" + "fullscreen": "フルスクリーンをトグルする", + "languages": "Change language" }, "accounts": { "label": "アカウント", @@ -93,7 +96,7 @@ "nodeConnectionTimeout": "Ethereum nodeをスタート出来ませんでした!
もしGethをインストールしているならば,このコマンドを使ってみてください:
geth --ipcpath __path__

もしくは問題を報告して下さい。 ", "nodeBinaryNotFound": "Ethereum node バイナリーが見つかりませんでした。
手動でスタートして下さい。 ", "nodeSyncing": "Ethereum node は同期中です...", - "nodeSyncInfo": "blockをダウンロードしています。 __currentBlock__ of __highestBlock__.", + "nodeSyncInfo": "blockをダウンロードしています。 __displayBlock__ of __highestBlock__.", "nodeSyncConnecting": "ピアーを探しています。...", "nodeSyncProcessing": "ブロックを処理しています...", "peerSearchTimeout": "ピアーの検索を中止しています" diff --git a/interface/i18n/mist.ko.i18n.json b/interface/i18n/mist.ko.i18n.json index 7d9a58298..de3d33d5d 100644 --- a/interface/i18n/mist.ko.i18n.json +++ b/interface/i18n/mist.ko.i18n.json @@ -4,6 +4,11 @@ "app": { "label": "__app__", "about": "__app__에 대하여", + "checkForUpdates": "업데이트 확인...", + "services": "서비스", + "hide": "__app__ 숨기기", + "hideOthers": "다른 창 숨기기", + "showAll": "모두 보기", "quit": "__app__ 종료" }, "edit": { @@ -17,7 +22,8 @@ }, "view": { "label": "보기", - "fullscreen": "전체화면으로" + "fullscreen": "전체화면으로", + "languages": "Change language" }, "accounts": { "label": "계정", diff --git a/interface/i18n/mist.kr.i18n.json b/interface/i18n/mist.kr.i18n.json index 7d9a58298..419380b57 100644 --- a/interface/i18n/mist.kr.i18n.json +++ b/interface/i18n/mist.kr.i18n.json @@ -4,6 +4,7 @@ "app": { "label": "__app__", "about": "__app__에 대하여", + "services": "Services", "quit": "__app__ 종료" }, "edit": { diff --git a/interface/i18n/mist.nb.i18n.json b/interface/i18n/mist.nb.i18n.json index 992b92e4f..3c19bae06 100644 --- a/interface/i18n/mist.nb.i18n.json +++ b/interface/i18n/mist.nb.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "Om __app__", + "checkForUpdates": "Se etter oppdateringer...", + "services": "Tjenester", "hide": "Skjul __app__", "hideOthers": "Skjul Andre", "showAll": "Vis Alle", @@ -20,7 +22,8 @@ }, "view": { "label": "Vis", - "fullscreen": "Veksle Mellom Fullskjerm" + "fullscreen": "Veksle Mellom Fullskjerm", + "languages": "Change language" }, "accounts": { "label": "Kontoer", diff --git a/interface/i18n/mist.nl.i18n.json b/interface/i18n/mist.nl.i18n.json index fa302238b..0798797f0 100644 --- a/interface/i18n/mist.nl.i18n.json +++ b/interface/i18n/mist.nl.i18n.json @@ -4,6 +4,11 @@ "app": { "label": "__app__", "about": "Over __app__", + "checkForUpdates": "Op updates controleren...", + "services": "Diensten", + "hide": "__app__ verbergen", + "hideOthers": "Andere verbergen", + "showAll": "Alles weergeven", "quit": "__app__ afsluiten" }, "edit": { diff --git a/interface/i18n/mist.pt.i18n.json b/interface/i18n/mist.pt.i18n.json index c40d8ceb2..a7f518684 100644 --- a/interface/i18n/mist.pt.i18n.json +++ b/interface/i18n/mist.pt.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "Sobre __app__", + "checkForUpdates": "Procurar Atualizações...", + "services": "Serviços", "hide": "Ocultar o __app__", "hideOthers": "Ocultar Outros", "showAll": "Mostrar Todos", @@ -20,7 +22,8 @@ }, "view": { "label": "Ver", - "fullscreen": "Modo de tela cheia" + "fullscreen": "Modo de tela cheia", + "languages": "Change language" }, "accounts": { "label": "Contas", @@ -95,7 +98,8 @@ "nodeConnectionTimeout": "Não pode inicializar um Node!
Instale um manualmente, e use esse comando para executa-lo:
geth --ipcpath __path__

Caso não consiga, entre em contato ", "nodeBinaryNotFound": "Nó não encontrado!
Instale um manualmente", "nodeSyncing": "Sincronizando, favor aguarde...", - "nodeSyncInfo": "Carregando bloco __currentBlock__ de __highestBlock__.", + "nodeSyncInfoStates": "Carregando bloco __displayBlock__ de __highestBlock__,
Lendo estrutura __displayState__ de __displayKnownStates__", + "nodeSyncInfo": "Carregando bloco __displayBlock__ de __highestBlock__.", "nodeSyncConnecting": "Procurando outros nós...", "nodeSyncProcessing": "Processando blocos recebidos, favor aguarde...", "peerSearchTimeout": "Não procure nós agora", diff --git a/interface/i18n/mist.al.i18n.json b/interface/i18n/mist.sq.i18n.json similarity index 100% rename from interface/i18n/mist.al.i18n.json rename to interface/i18n/mist.sq.i18n.json diff --git a/interface/i18n/mist.zh-TW.i18n.json b/interface/i18n/mist.zh-TW.i18n.json index 3b98fc915..c5cbdbcd6 100644 --- a/interface/i18n/mist.zh-TW.i18n.json +++ b/interface/i18n/mist.zh-TW.i18n.json @@ -4,6 +4,11 @@ "app": { "label": "__app__", "about": "關於__app__", + "checkForUpdates": "檢查更新...", + "services": "服務", + "hide": "隱藏 __app__", + "hideOthers": "隱藏其他", + "showAll": "顯示全部", "quit": "退出__app__" }, "edit": { @@ -17,7 +22,9 @@ }, "view": { "label": "檢視", - "fullscreen": "全螢幕" + "fullscreen": "全螢幕", + "languages": "語言", + "languages": "Change language" }, "accounts": { "label": "帳號", @@ -92,7 +99,7 @@ "nodeConnectionTimeout": "無法開啓以太坊節點!
如果您已經安裝Geth,使用此命令運行:
geth --ipcpath __path__

或者上報此問題 ", "nodeBinaryNotFound": "找不到以太坊節點安裝文件!
請事先手動開啓一個節點 ", "nodeSyncing": "需要同步以太坊節點,請等待……", - "nodeSyncInfo": "正在下載第__currentBlock__塊,共__highestBlock__。", + "nodeSyncInfo": "正在下載第__displayBlock__塊,共__highestBlock__。", "nodeSyncConnecting": "正在查找節點……", "nodeSyncProcessing": "正在處理區塊,請等待……", "peerSearchTimeout": "跳過節點搜索" diff --git a/interface/i18n/mist.zh.i18n.json b/interface/i18n/mist.zh.i18n.json index 4417653f2..1ac2209c0 100644 --- a/interface/i18n/mist.zh.i18n.json +++ b/interface/i18n/mist.zh.i18n.json @@ -4,6 +4,8 @@ "app": { "label": "__app__", "about": "关于__app__", + "checkForUpdates": "检测更新...", + "services": "服务", "hide": "隐藏 __app__", "hideOthers": "隐藏 其它", "showAll": "显示 全部", @@ -20,7 +22,8 @@ }, "view": { "label": "视图", - "fullscreen": "全屏切换" + "fullscreen": "全屏切换", + "languages": "Change language" }, "accounts": { "label": "账户", @@ -95,7 +98,7 @@ "nodeConnectionTimeout": "无法开启以太坊节点!
如果你已经安装Geth,使用此命令运行:
geth --ipcpath __path__

或者上报此问题 ", "nodeBinaryNotFound": "找不到以太坊节点安装文件!
请事先手动开启一个节点 ", "nodeSyncing": "需要同步以太坊节点,请等待……", - "nodeSyncInfo": "正在下载第__currentBlock__块,共__highestBlock__。", + "nodeSyncInfo": "正在下载第__displayBlock__块,共__highestBlock__。", "nodeSyncConnecting": "正在查找节点……", "nodeSyncProcessing": "正在处理区块,请等待……", "peerSearchTimeout": "跳过节点搜索" diff --git a/interface/project-tap.i18n b/interface/project-tap.i18n index 87c9f099a..aca5b36a1 100644 --- a/interface/project-tap.i18n +++ b/interface/project-tap.i18n @@ -1,5 +1,5 @@ { "helper_name": "i18n", - "supported_languages": ["de", "en", "es", "fr", "ja", "ko", "nb", "pt", "zh", "zh-TW"], + "supported_languages": ["de", "en", "es", "fa", "fr", "it", "ja", "ko", "nb", "nl", "pt", "sq", "zh", "zh-TW"], "cdn_path": "i18n" } diff --git a/main.js b/main.js index dc11d3aca..2d5a438a4 100644 --- a/main.js +++ b/main.js @@ -21,6 +21,7 @@ const logger = require('./modules/utils/logger'); const Sockets = require('./modules/sockets'); const Windows = require('./modules/windows'); + const Settings = require('./modules/settings'); Settings.init(); @@ -38,6 +39,10 @@ if (Settings.cli.ignoreGpuBlacklist) { // logging setup const log = logger.create('main'); +if (Settings.inTestMode) { + log.info('TEST MODE'); +} + // GLOBAL Variables global.path = { HOME: app.getPath('home'), @@ -129,35 +134,36 @@ app.on('open-url', function (e, url) { }); -var killedSockets = false; +var killedSocketsAndNodes = false; app.on('before-quit', function(event){ - if(!killedSockets) { + if(!killedSocketsAndNodes) { + log.info('Defer quitting until sockets and node are shut down'); + event.preventDefault(); - } - // sockets manager - Sockets.destroyAll() - .catch((err) => { - log.error('Error shutting down sockets'); - }); + // sockets manager + Sockets.destroyAll() + .catch((err) => { + log.error('Error shutting down sockets'); + }); - // delay quit, so the sockets can close - setTimeout(function(){ - killedSockets = true; + // delay quit, so the sockets can close + setTimeout(function(){ + ethereumNode.stop().then(function() { + killedSocketsAndNodes = true; - ethereumNode.stop().then(function() { - app.quit(); - }); - }, 500); + app.quit(); + }); + }, 500); + } else { + log.info('About to quit...'); + } }); -const NODE_TYPE = 'geth'; - - var mainWindow; var splashWindow; @@ -169,7 +175,9 @@ app.on('ready', function() { Windows.init(); // check for update - require('./modules/updateChecker').run(); + if (!Settings.inTestMode) { + require('./modules/updateChecker').run(); + } // initialize the web3 IPC provider backend ipcProviderBackend.init(); @@ -190,6 +198,7 @@ app.on('ready', function() { width: 1024 + 208, height: 720, webPreferences: { + nodeIntegration: true, preload: __dirname +'/modules/preloader/mistUI.js', 'overlay-fullscreen-video': true, 'overlay-scrollbars': true @@ -215,22 +224,24 @@ app.on('ready', function() { }); } - splashWindow = Windows.create('splash', { - primary: true, - url: global.interfacePopupsUrl + '#splashScreen_'+ global.mode, - show: true, - electronOptions: { - width: 400, - height: 230, - resizable: false, - backgroundColor: '#F6F6F6', - useContentSize: true, - frame: false, - webPreferences: { - preload: __dirname +'/modules/preloader/splashScreen.js', + if (!Settings.inTestMode) { + splashWindow = Windows.create('splash', { + primary: true, + url: global.interfacePopupsUrl + '#splashScreen_'+ global.mode, + show: true, + electronOptions: { + width: 400, + height: 230, + resizable: false, + backgroundColor: '#F6F6F6', + useContentSize: true, + frame: false, + webPreferences: { + preload: __dirname +'/modules/preloader/splashScreen.js', + } } - } - }); + }); + } // check time sync // var ntpClient = require('ntp-client'); @@ -253,7 +264,7 @@ app.on('ready', function() { }); - splashWindow.on('ready', function() { + const kickStart = function() { // node connection stuff ethereumNode.on('nodeConnectionTimeout', function() { Windows.broadcast('uiAction_nodeStatus', 'connectionTimeout'); @@ -358,15 +369,21 @@ app.on('ready', function() { resolve(); }); - splashWindow.hide(); + if (splashWindow) { + splashWindow.hide(); + } }); } }) .then(function doSync() { // we're going to do the sync - so show splash - splashWindow.show(); + if (splashWindow) { + splashWindow.show(); + } - return syncResultPromise; + if (!Settings.inTestMode) { + return syncResultPromise; + } }) .then(function allDone() { startMainWindow(); @@ -375,7 +392,14 @@ app.on('ready', function() { log.error('Error starting up node and/or syncing', err); }); /* socket connected to geth */; - }); /* on splash screen loaded */ + }; /* kick start */ + + + if (splashWindow) { + splashWindow.on('ready', kickStart); + } else { + kickStart(); + } }); /* on app ready */ @@ -390,7 +414,9 @@ var startMainWindow = function() { log.info('Loading Interface at '+ global.interfaceAppUrl); mainWindow.on('ready', function() { - splashWindow.close(); + if (splashWindow) { + splashWindow.close(); + } mainWindow.show(); }); diff --git a/modules/ethereumNode.js b/modules/ethereumNode.js index cc4b31696..8cf2a3f8f 100644 --- a/modules/ethereumNode.js +++ b/modules/ethereumNode.js @@ -24,7 +24,7 @@ const DEFAULT_NETWORK = 'main'; const UNABLE_TO_BIND_PORT_ERROR = 'unableToBindPort'; const UNABLE_TO_SPAWN_ERROR = 'unableToSpan'; const PASSWORD_WRONG_ERROR = 'badPassword'; - +const NODE_START_WAIT_MS = 3000; /** @@ -143,7 +143,7 @@ class EthereumNode extends EventEmitter { return this._start(this.defaultNodeType, this.defaultNetwork) .catch((err) => { log.error('Failed to start node', err); - + throw err; }); }); @@ -289,8 +289,8 @@ class EthereumNode extends EventEmitter { this._saveUserData('network', this._network); return this._socket.connect({ path: ipcPath }, { - timeout: 30000 /* 30s */ - }) + timeout: 30000 /* 30s */ + }) .then(() => { this.state = STATES.CONNECTED; }) @@ -336,60 +336,8 @@ class EthereumNode extends EventEmitter { log.debug(`Start node using ${binPath}`); return new Q((resolve, reject) => { - if ('eth' === nodeType) { - let modalWindow = Windows.createPopup('unlockMasterPassword', { - electronOptions: { - width: 400, - height: 220, - }, - useWeb3: false, - }); - - let called = false; - - modalWindow.on('closed', () => { - if (!called) { - app.quit(); - } - }); - - let popupCallback = function(err) { - if (err && _.get(modalWindow,'webContents')) { - log.error('unlockMasterPassword error', err); - - if(UNABLE_TO_SPAWN_ERROR === err) { - modalWindow.close(); - modalWindow = null; - } else { - modalWindow.webContents.send('data', { - masterPasswordWrong: true - }); - } - } else { - called = true; - modalWindow.close(); - modalWindow = null; - ipc.removeAllListeners('backendAction_unlockedMasterPassword'); - } - }; - - ipc.on('backendAction_unlockedMasterPassword', (ev, err, pw) => { - if (_.get(modalWindow, 'webContents') && ev.sender.getId() === modalWindow.webContents.getId()) { - if (!err) { - this.__startProcess(nodeType, network, binPath, pw, popupCallback) - .then(resolve, reject); - } else { - app.quit(); - } - - return; - } - }); - } else { - this.__startProcess(nodeType, network, binPath) - .then(resolve, reject); - } - + this.__startProcess(nodeType, network, binPath) + .then(resolve, reject); }); } @@ -397,7 +345,7 @@ class EthereumNode extends EventEmitter { /** * @return {Promise} */ - __startProcess (nodeType, network, binPath, pw, popupCallback) { + __startProcess (nodeType, network, binPath) { return new Q((resolve, reject) => { log.trace('Rotate log file'); @@ -421,8 +369,7 @@ class EthereumNode extends EventEmitter { else { args = (nodeType === 'geth') ? ['--fast', '--cache', '512'] - : ['--unsafe-transactions', '--master', pw]; - pw = null; + : ['--unsafe-transactions']; } let nodeOptions = Settings.nodeOptions; @@ -442,10 +389,6 @@ class EthereumNode extends EventEmitter { if (STATES.STARTING === this.state) { this.state = STATES.ERROR; - if (popupCallback) { - popupCallback(UNABLE_TO_SPAWN_ERROR); - } - log.info('Node startup error'); // TODO: detect this properly @@ -455,17 +398,6 @@ class EthereumNode extends EventEmitter { } }); - // node quit, e.g. master pw wrong - proc.once('exit', () => { - if ('eth' === nodeType) { - log.warn('Password wrong!'); - - if (popupCallback) { - popupCallback(PASSWORD_WRONG_ERROR); - } - } - }); - // we need to read the buff to prevent node from not working proc.stderr.pipe( fs.createWriteStream(this._buildFilePath('node.log'), { flags: 'a' }) @@ -510,20 +442,17 @@ class EthereumNode extends EventEmitter { // when data is first received this.once('data', () => { /* - Assume startup succeeded after 5 seconds. At this point - IPC connections are usually possible. + We wait a short while before marking startup as successful + because we may want to parse the initial node output for + errors, etc (see geth port-binding error above) */ setTimeout(() => { if (STATES.STARTING === this.state) { - log.info('4s elapsed, assuming node started up successfully'); - - if (popupCallback) { - popupCallback(); - } + log.info(`${NODE_START_WAIT_MS}ms elapsed, assuming node started up successfully`); resolve(proc); } - }, 4000); + }, NODE_START_WAIT_MS); }) }); }); @@ -571,8 +500,8 @@ class EthereumNode extends EventEmitter { _loadDefaults () { log.trace('Load defaults'); - this.defaultNodeType = this._loadUserData('node') || DEFAULT_NODE_TYPE; - this.defaultNetwork = this._loadUserData('network') || DEFAULT_NETWORK; + this.defaultNodeType = Settings.nodeType || this._loadUserData('node') || DEFAULT_NODE_TYPE; + this.defaultNetwork = Settings.network || this._loadUserData('network') || DEFAULT_NETWORK; } diff --git a/modules/ipc/ipcProviderBackend.js b/modules/ipc/ipcProviderBackend.js index cea9892e5..984358cc0 100644 --- a/modules/ipc/ipcProviderBackend.js +++ b/modules/ipc/ipcProviderBackend.js @@ -112,9 +112,9 @@ class IpcProviderBackend { log.trace('Notification received', ownerId, data); if (data.error) { - data = this._makeErrorResponsePayload({}, data); + data = this._makeErrorResponsePayload(data, data); } else { - data = this._makeResponsePayload({}, data); + data = this._makeResponsePayload(data, data); } owner.send('ipcProvider-data', JSON.stringify(data)); @@ -384,8 +384,10 @@ class IpcProviderBackend { }); } - delete ret.params; - delete ret.method; + if(item.id) { + delete ret.params; + delete ret.method; + } ret.jsonrpc = '2.0'; diff --git a/modules/ipc/methods/base.js b/modules/ipc/methods/base.js index 4be499431..b446ed95e 100644 --- a/modules/ipc/methods/base.js +++ b/modules/ipc/methods/base.js @@ -79,8 +79,10 @@ module.exports = class BaseProcessor { _isAdminConnection (conn) { // main window or popupwindows - always allow requests let wnd = Windows.getById(conn.id); + let tab = Tabs.findOne({ webviewId: conn.id }); - return (wnd && ('main' === wnd.type || wnd.isPopup)); + return ((wnd && ('main' === wnd.type || wnd.isPopup)) || + (tab && _.get(tab, 'permissions.admin') === true)); } diff --git a/modules/menuItems.js b/modules/menuItems.js index 4bee3cb5d..f03faead6 100644 --- a/modules/menuItems.js +++ b/modules/menuItems.js @@ -56,7 +56,7 @@ var menuTempl = function(webviews) { click: function(){ Windows.createPopup('about', { electronOptions: { - width: 420, + width: 420, height: 230, alwaysOnTop: true, } @@ -72,7 +72,7 @@ var menuTempl = function(webviews) { type: 'separator' }, { - label: 'Services', + label: i18n.t('mist.applicationMenu.app.services', {app: global.appName}), role: 'services', submenu: [] }, @@ -124,7 +124,7 @@ var menuTempl = function(webviews) { { label: i18n.t('mist.applicationMenu.accounts.importPresale'), accelerator: 'CommandOrControl+I', - enabled: ethereumNode.isMainNetwork, + enabled: ethereumNode.isMainNetwork, click: function(){ Windows.createPopup('importAccount', { electronOptions: { @@ -132,7 +132,7 @@ var menuTempl = function(webviews) { } }); } - }, + }, { type: 'separator' }, @@ -150,7 +150,7 @@ var menuTempl = function(webviews) { path = global.path.APPDATA + '\\Web3\\keys'; else path += '/.web3/keys'; - + // geth } else { if(process.platform === 'darwin') @@ -218,6 +218,33 @@ var menuTempl = function(webviews) { ] }) + let genSwitchLanguageFunc = (lang_code) => function(menuItem, browserWindow){ + browserWindow.webContents.executeJavaScript( + `TAPi18n.setLanguage("${lang_code}");` + ); + ipc.emit("backendAction_setLanguage", {}, lang_code); + } + + let languageMenu = + Object.keys(i18n.options.resources) + .filter(lang_code => lang_code != 'dev') + .map(lang_code => { + menuItem = { + label: i18n.t('mist.applicationMenu.view.langCodes.' + lang_code), + type: 'checkbox', + checked: (global.language.substr(0,2) === lang_code), + click: genSwitchLanguageFunc(lang_code) + } + return menuItem + }); + let defaultLang = app.getLocale().substr(0,2); + languageMenu.unshift({ + label: i18n.t('mist.applicationMenu.view.default'), + click: genSwitchLanguageFunc(defaultLang) + }, { + type: 'separator' + }); + // VIEW menu.push({ label: i18n.t('mist.applicationMenu.view.label'), @@ -230,6 +257,10 @@ var menuTempl = function(webviews) { mainWindow.window.setFullScreen(!mainWindow.window.isFullScreen()); } + }, + { + label: i18n.t('mist.applicationMenu.view.languages'), + submenu: languageMenu } ] }) @@ -307,7 +338,7 @@ var menuTempl = function(webviews) { - + // add node switching menu devToolsMenu.push({ @@ -355,7 +386,7 @@ var menuTempl = function(webviews) { }, { label: 'Testnet (Morden)', - accelerator: 'CommandOrControl+Shift+2', + accelerator: 'CommandOrControl+Shift+2', checked: ethereumNode.isOwnNode && ethereumNode.isTestNetwork, enabled: ethereumNode.isOwnNode && !ethereumNode.isTestNetwork, type: 'checkbox', @@ -378,7 +409,7 @@ var menuTempl = function(webviews) { if (ret.result) { global.mining = true; createMenu(webviews); - } + } }) .catch((err) => { log.error('miner_start', err); @@ -391,7 +422,7 @@ var menuTempl = function(webviews) { if (ret.result) { global.mining = false; createMenu(webviews); - } + } }) .catch((err) => { log.error('miner_stop', err); diff --git a/modules/mistAPI.js b/modules/mistAPI.js index 8d49ce0af..37b157cf7 100644 --- a/modules/mistAPI.js +++ b/modules/mistAPI.js @@ -8,8 +8,6 @@ const remote = electron.remote; const ipc = electron.ipcRenderer; module.exports = function(isWallet) { - - var queue = []; var prefix = 'entry_'; diff --git a/modules/preloader/browser.js b/modules/preloader/browser.js index 6131eb265..7e405d9aa 100644 --- a/modules/preloader/browser.js +++ b/modules/preloader/browser.js @@ -1,7 +1,7 @@ /** @module preloader browser */ -require('./consoleLogCapture')('browser'); +require('./include/common')('browser'); const electron = require('electron'); const ipc = electron.ipcRenderer; const shell = electron.shell; @@ -13,7 +13,7 @@ var Web3 = require('web3'); require('../getFavicon.js'); require('../getMetaTags.js'); require('../openExternal.js'); -require('./setBasePath')('interface'); +require('./include/setBasePath')('interface'); // register with window manager ipc.send('backendAction_setWindowId'); diff --git a/modules/preloader/commonGlobals.js b/modules/preloader/commonGlobals.js new file mode 100644 index 000000000..e69de29bb diff --git a/modules/preloader/dapps.js b/modules/preloader/dapps.js index e0b936d45..98ed54eeb 100644 --- a/modules/preloader/dapps.js +++ b/modules/preloader/dapps.js @@ -1,7 +1,7 @@ /** @module preloader dapps */ -require('./consoleLogCapture')('dapps'); +require('./include/common')('dapps'); const electron = require('electron'); const ipc = electron.ipcRenderer; const shell = electron.shell; @@ -13,7 +13,7 @@ require('../getFavicon.js'); require('../getMetaTags.js'); require('../openExternal.js'); -require('./setBasePath')('interface'); +require('./include/setBasePath')('interface'); // register with window manager ipc.send('backendAction_setWindowId'); diff --git a/modules/preloader/include/common.js b/modules/preloader/include/common.js new file mode 100644 index 000000000..8baac896d --- /dev/null +++ b/modules/preloader/include/common.js @@ -0,0 +1,7 @@ +module.exports = function(windowId) { + if (process.env.TEST_MODE) { + window.electronRequire = require; + } + + require('./consoleLogCapture')(windowId); +} diff --git a/modules/preloader/consoleLogCapture.js b/modules/preloader/include/consoleLogCapture.js similarity index 91% rename from modules/preloader/consoleLogCapture.js rename to modules/preloader/include/consoleLogCapture.js index 81d569fa3..f8a252285 100644 --- a/modules/preloader/consoleLogCapture.js +++ b/modules/preloader/include/consoleLogCapture.js @@ -29,7 +29,7 @@ module.exports = function(windowId) { // send console logging to IPC backend ['trace', 'debug', 'info', 'warn', 'error', 'log'].forEach(function(method) { - console['orig_' + method] = console[method]; + console['_' + method] = console[method]; console[method] = (function(origMethod) { return function() { let args = Array.from(arguments); @@ -51,7 +51,7 @@ module.exports = function(windowId) { JSON.stringify(args) ); } catch (err) { - console.orig_error('Unable to stringify arguments to log to backend', err.stack); + console._warn('Unable to stringify arguments to log to backend', err.stack); } }; })(console[method]); diff --git a/modules/preloader/setBasePath.js b/modules/preloader/include/setBasePath.js similarity index 100% rename from modules/preloader/setBasePath.js rename to modules/preloader/include/setBasePath.js diff --git a/modules/preloader/mistUI.js b/modules/preloader/mistUI.js index 7c281e310..517c48e53 100644 --- a/modules/preloader/mistUI.js +++ b/modules/preloader/mistUI.js @@ -2,7 +2,7 @@ @module preloader MistUI */ -require('./consoleLogCapture')('mist'); +require('./include/common')('mist'); const electron = require('electron'); const ipc = electron.ipcRenderer; const syncMinimongo = require('../syncMinimongo.js'); @@ -16,7 +16,7 @@ const Web3 = require('web3'); const ipcProviderWrapper = require('../ipc/ipcProviderWrapper.js'); const web3Admin = require('../web3Admin.js'); -require('./setBasePath')('interface'); +require('./include/setBasePath')('interface'); // register with window manager ipc.send('backendAction_setWindowId'); @@ -38,6 +38,12 @@ window.syncMinimongo = syncMinimongo; window.ipc = ipc; +// remove require and modules, when node-integration is on +delete window.module; +delete window.require; + + + // prevent overwriting the Dapps Web3 delete global.Web3; delete window.Web3; diff --git a/modules/preloader/popupWindows.js b/modules/preloader/popupWindows.js index 6cb01db3e..324b471c0 100644 --- a/modules/preloader/popupWindows.js +++ b/modules/preloader/popupWindows.js @@ -2,7 +2,7 @@ @module preloader PopupWindows */ -require('./consoleLogCapture')('popup'); +require('./include/common')('popup'); const electron = require('electron'); const ipc = electron.ipcRenderer; require('../openExternal.js'); @@ -12,7 +12,7 @@ const BigNumber = require('bignumber.js'); const Web3 = require('web3'); const web3Admin = require('../web3Admin.js'); -require('./setBasePath')('interface'); +require('./include/setBasePath')('interface'); // register with window manager ipc.send('backendAction_setWindowId'); diff --git a/modules/preloader/popupWindowsNoWeb3.js b/modules/preloader/popupWindowsNoWeb3.js index 93a35da88..89fb55dba 100644 --- a/modules/preloader/popupWindowsNoWeb3.js +++ b/modules/preloader/popupWindowsNoWeb3.js @@ -2,13 +2,13 @@ @module preloader PopupWindows */ -require('./consoleLogCapture')('popup-no-web3'); +require('./include/common')('popup-no-web3'); const electron = require('electron'); const mist = require('../mistAPI.js'); const ipc = electron.ipcRenderer; const ipcProviderWrapper = require('../ipc/ipcProviderWrapper.js'); -require('./setBasePath')('interface'); +require('./include/setBasePath')('interface'); // register with window manager ipc.send('backendAction_setWindowId'); diff --git a/modules/preloader/splashScreen.js b/modules/preloader/splashScreen.js index 4f154b852..8c1d0e13f 100644 --- a/modules/preloader/splashScreen.js +++ b/modules/preloader/splashScreen.js @@ -1,4 +1,4 @@ -require('./consoleLogCapture')('splash'); +require('./include/common')('splash'); const mist = require('../mistAPI.js'); const electron = require('electron'); const ipc = electron.ipcRenderer; @@ -6,7 +6,7 @@ const ipcProviderWrapper = require('../ipc/ipcProviderWrapper.js'); const Web3 = require('web3'); require('../openExternal.js'); -require('./setBasePath')('interface'); +require('./include/setBasePath')('interface'); // register with window manager ipc.send('backendAction_setWindowId'); diff --git a/modules/preloader/wallet.js b/modules/preloader/wallet.js index 2fdc04008..790ef0547 100644 --- a/modules/preloader/wallet.js +++ b/modules/preloader/wallet.js @@ -2,7 +2,7 @@ @module preloader wallet */ -require('./consoleLogCapture')('wallet'); +require('./include/common')('wallet'); const electron = require('electron'); const ipc = electron.ipcRenderer; const mist = require('../mistAPI.js'); @@ -12,7 +12,7 @@ const ipcProviderWrapper = require('../ipc/ipcProviderWrapper.js'); const web3Admin = require('../web3Admin.js'); require('../openExternal.js'); -require('./setBasePath')('interface/wallet'); +require('./include/setBasePath')('interface/wallet'); // register with window manager ipc.send('backendAction_setWindowId'); diff --git a/modules/settings.js b/modules/settings.js index 4b0072115..edd765524 100644 --- a/modules/settings.js +++ b/modules/settings.js @@ -14,6 +14,8 @@ try { + + const argv = require('yargs') .usage('Usage: $0 [Mist options] -- [Node options]') .option({ @@ -27,6 +29,24 @@ const argv = require('yargs') type: 'string', group: 'Mist options:', }, + node: { + demand: false, + default: null, + describe: 'Node to use: geth, eth', + requiresArg: true, + nargs: 1, + type: 'string', + group: 'Mist options:', + }, + network: { + demand: false, + default: null, + describe: 'Network to connect to: main, test', + requiresArg: true, + nargs: 1, + type: 'string', + group: 'Mist options:', + }, ipcpath: { demand: false, describe: 'Path to node IPC socket file (this will automatically get passed as an option to Geth).', @@ -103,11 +123,13 @@ const argv = require('yargs') .parse(process.argv.slice(1)); + argv.nodeOptions = []; -for (let optIdx in argv._) { - if ('-' === argv._[optIdx].charAt(0)) { - argv.nodeOptions = argv._.slice(optIdx); +for (let optIdx in argv) { + if (0 === optIdx.indexOf('node-')) { + argv.nodeOptions.push('--' + optIdx.substr(5)); + argv.nodeOptions.push(argv[optIdx]); break; } @@ -115,7 +137,7 @@ for (let optIdx in argv._) { // some options are shared if (argv.ipcpath) { - argv.nodeOptions.push('--ipcpcath', argv.ipcpath); + argv.nodeOptions.push('--ipcpath', argv.ipcpath); } @@ -150,6 +172,10 @@ class Settings { return defaultConfig.production; } + get inTestMode () { + return !!process.env.TEST_MODE; + } + get gethPath () { return argv.gethpath; } @@ -162,6 +188,14 @@ class Settings { return argv.ipcpath; } + get nodeType () { + return argv.node; + } + + get network () { + return argv.network; + } + get nodeOptions () { return argv.nodeOptions; } diff --git a/modules/sockets.js b/modules/sockets.js index 4d14010bd..895948adf 100644 --- a/modules/sockets.js +++ b/modules/sockets.js @@ -10,6 +10,9 @@ const dechunker = require('./ipc/dechunker.js'); +const CONNECT_INTERVAL_MS = 1000; +const CONNECT_TIMEOUT_MS = 3000; + /** * Socket connecting to Ethereum Node. @@ -41,51 +44,66 @@ class Socket extends EventEmitter { * Connect to host. * @param {Object} connectConfig * @param {Object} [options] - * @param {Number} [options.timeout] Milliseconds to wait before timeout. + * @param {Number} [options.timeout] Milliseconds to wait before timeout (default is 5000). * @return {Promise} */ connect (connectConfig, options) { this._log.info(`Connect to ${JSON.stringify(connectConfig)}`); - options = options || {}; + options = _.extend({ + timeout: CONNECT_TIMEOUT_MS, + }, options); return this._resetSocket() .then(() => { + let connectTimerId = null; + let timeoutTimerId = null; + this._log.debug('Connecting...'); + this._log.debug(`Will wait ${options.timeout}ms for connection to happen.`); + this._state = STATE.CONNECTING; return new Q((resolve, reject) => { this._socket.once('connect', () => { - this._log.info('Connected!'); + if (STATE.CONNECTING === this._state) { + this._log.info('Connected!'); - this._state = STATE.CONNECTED; + this._state = STATE.CONNECTED; - this.emit('connect'); + clearTimeout(connectTimerId); + clearTimeout(timeoutTimerId); - resolve(); + this.emit('connect'); + + resolve(); + } }); - this._socket.once('error', (err) => { + this._socket.on('error', (err) => { if (STATE.CONNECTING === this._state) { - this._log.error('Connection error', err); - - this._state = STATE.ERROR; + this._log.warn(`Connection failed, retrying after ${CONNECT_INTERVAL_MS}ms...`); - return reject(new Error(`Unable to connect to socket: ${err.message}`)); + connectTimerId = setTimeout(() => { + this._socket.connect(connectConfig); + }, CONNECT_INTERVAL_MS); } }); - if (options.timeout) { - this._log.debug(`Will wait ${options.timeout}ms for connection to happen.`); + timeoutTimerId = setTimeout(() => { + if (STATE.CONNECTING === this._state) { + this._log.error(`Connection failed (${options.timeout}ms elapsed)`); - setTimeout(() => { - if (STATE.CONNECTING === this._state) { - this._socket.emit('error', `Connection timeout (took longer than ${options.timeout} ms)`); - } - }, options.timeout); - } + this._state = STATE.CONNECTION_TIMEOUT; + + clearTimeout(connectTimerId); + + return reject(new Error(`Unable to connect to socket: timeout`)); + } + }, options.timeout); + // initial kick-off this._socket.connect(connectConfig); }); }); @@ -388,6 +406,7 @@ const STATE = Socket.STATE = { DISCONNECTED: 4, ERROR: -1, DISCONNECTION_TIMEOUT: -2, + CONNECTION_TIMEOUT: -3, }; diff --git a/modules/updateChecker.js b/modules/updateChecker.js index 07385ff7b..261a6d7d4 100644 --- a/modules/updateChecker.js +++ b/modules/updateChecker.js @@ -73,6 +73,8 @@ function showWindow(options) { width: 420, height: 230 , alwaysOnTop: true, + resizable: false, + maximizable: false, }, }, options)); } diff --git a/modules/windows.js b/modules/windows.js index 3adf9fdb8..7caa82297 100644 --- a/modules/windows.js +++ b/modules/windows.js @@ -177,11 +177,12 @@ class Windows { alwaysOnTop: true, resizable: false, width: 100, - height: 50, + height: 80, center: true, frame: false, useContentSize: true, titleBarStyle: 'hidden', //hidden-inset: more space + skipTaskbar: true }, }); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json new file mode 100644 index 000000000..cf8549def --- /dev/null +++ b/npm-shrinkwrap.json @@ -0,0 +1,2004 @@ +{ + "name": "Mist", + "version": "0.7.6", + "dependencies": { + "abbrev": { + "version": "1.0.9", + "from": "abbrev@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" + }, + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + }, + "ansi-styles": { + "version": "2.2.1", + "from": "ansi-styles@>=2.2.1 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + }, + "archive-type": { + "version": "3.2.0", + "from": "archive-type@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz" + }, + "archy": { + "version": "1.0.0", + "from": "archy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" + }, + "array-differ": { + "version": "1.0.0", + "from": "array-differ@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz" + }, + "array-find-index": { + "version": "1.0.1", + "from": "array-find-index@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.1.tgz" + }, + "array-union": { + "version": "1.0.2", + "from": "array-union@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz" + }, + "array-uniq": { + "version": "1.0.3", + "from": "array-uniq@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" + }, + "asar": { + "version": "0.11.0", + "from": "asar@>=0.11.0 <0.12.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-0.11.0.tgz", + "dependencies": { + "glob": { + "version": "6.0.4", + "from": "glob@>=6.0.4 <7.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz" + } + } + }, + "asn1": { + "version": "0.1.11", + "from": "asn1@0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" + }, + "assert-plus": { + "version": "0.1.5", + "from": "assert-plus@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" + }, + "async": { + "version": "1.5.2", + "from": "async@>=0.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + }, + "aws-sign2": { + "version": "0.5.0", + "from": "aws-sign2@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" + }, + "aws4": { + "version": "1.4.1", + "from": "aws4@>=1.2.1 <2.0.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz" + }, + "balanced-match": { + "version": "0.4.1", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz" + }, + "base64-js": { + "version": "0.0.8", + "from": "base64-js@0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz" + }, + "beeper": { + "version": "1.1.0", + "from": "beeper@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.0.tgz" + }, + "bignumber.js": { + "version": "2.3.0", + "from": "bignumber.js@>=2.1.4 <3.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.3.0.tgz" + }, + "binary": { + "version": "0.3.0", + "from": "binary@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz" + }, + "binaryextensions": { + "version": "1.0.1", + "from": "binaryextensions@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-1.0.1.tgz" + }, + "bl": { + "version": "0.9.5", + "from": "bl@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz" + }, + "bluebird": { + "version": "3.4.1", + "from": "bluebird@>=3.3.5 <4.0.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz" + }, + "boom": { + "version": "2.10.1", + "from": "boom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + }, + "brace-expansion": { + "version": "1.1.5", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz" + }, + "buffer": { + "version": "3.6.0", + "from": "buffer@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + } + } + }, + "buffer-crc32": { + "version": "0.2.5", + "from": "buffer-crc32@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.5.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "buffers": { + "version": "0.1.1", + "from": "buffers@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" + }, + "builtin-modules": { + "version": "1.1.1", + "from": "builtin-modules@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" + }, + "camelcase": { + "version": "3.0.0", + "from": "camelcase@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + }, + "camelcase-keys": { + "version": "2.1.0", + "from": "camelcase-keys@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "dependencies": { + "camelcase": { + "version": "2.1.1", + "from": "camelcase@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz" + } + } + }, + "capture-stack-trace": { + "version": "1.0.0", + "from": "capture-stack-trace@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz" + }, + "caseless": { + "version": "0.9.0", + "from": "caseless@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.9.0.tgz" + }, + "chainsaw": { + "version": "0.1.0", + "from": "chainsaw@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz" + }, + "chalk": { + "version": "1.1.3", + "from": "chalk@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + }, + "chromium-pickle-js": { + "version": "0.1.0", + "from": "chromium-pickle-js@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.1.0.tgz" + }, + "cliui": { + "version": "3.2.0", + "from": "cliui@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz" + }, + "clone": { + "version": "1.0.2", + "from": "clone@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz" + }, + "clone-stats": { + "version": "0.0.1", + "from": "clone-stats@>=0.0.1 <0.0.2", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + }, + "code-point-at": { + "version": "1.0.0", + "from": "code-point-at@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz" + }, + "combined-stream": { + "version": "0.0.7", + "from": "combined-stream@>=0.0.5 <0.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz" + }, + "commander": { + "version": "2.9.0", + "from": "commander@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + }, + "concat-stream": { + "version": "1.5.0", + "from": "concat-stream@1.5.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz", + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" + } + } + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "create-error-class": { + "version": "3.0.2", + "from": "create-error-class@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz" + }, + "cryptiles": { + "version": "2.0.5", + "from": "cryptiles@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + }, + "crypto-js": { + "version": "3.1.6", + "from": "crypto-js@>=3.1.4 <4.0.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.6.tgz" + }, + "ctype": { + "version": "0.5.3", + "from": "ctype@0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" + }, + "cuint": { + "version": "0.2.1", + "from": "cuint@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.1.tgz" + }, + "currently-unhandled": { + "version": "0.4.1", + "from": "currently-unhandled@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz" + }, + "dashdash": { + "version": "1.14.0", + "from": "dashdash@>=1.12.0 <2.0.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "dateformat": { + "version": "1.0.12", + "from": "dateformat@>=1.0.11 <2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz" + }, + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "decamelize": { + "version": "1.2.0", + "from": "decamelize@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + }, + "decompress": { + "version": "4.0.0", + "from": "decompress@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.0.0.tgz" + }, + "decompress-tar": { + "version": "4.1.0", + "from": "decompress-tar@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.0.tgz" + }, + "decompress-tarbz2": { + "version": "4.1.0", + "from": "decompress-tarbz2@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.0.tgz" + }, + "decompress-targz": { + "version": "4.0.0", + "from": "decompress-targz@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.0.0.tgz" + }, + "decompress-unzip": { + "version": "4.0.1", + "from": "decompress-unzip@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "dependencies": { + "get-stream": { + "version": "2.3.0", + "from": "get-stream@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.0.tgz" + }, + "yauzl": { + "version": "2.6.0", + "from": "yauzl@>=2.4.2 <3.0.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.6.0.tgz" + } + } + }, + "decompress-zip": { + "version": "0.3.0", + "from": "decompress-zip@0.3.0", + "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.0.tgz", + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "from": "readable-stream@>=1.1.8 <2.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + } + } + }, + "deep-extend": { + "version": "0.4.1", + "from": "deep-extend@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz" + }, + "defaults": { + "version": "1.0.3", + "from": "defaults@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz" + }, + "delayed-stream": { + "version": "0.0.5", + "from": "delayed-stream@0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + }, + "deprecated": { + "version": "0.0.1", + "from": "deprecated@>=0.0.1 <0.0.2", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz" + }, + "duplexer": { + "version": "0.1.1", + "from": "duplexer@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" + }, + "duplexer2": { + "version": "0.0.2", + "from": "duplexer2@0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "from": "readable-stream@>=1.1.9 <1.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + } + } + }, + "duplexer3": { + "version": "0.1.4", + "from": "duplexer3@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + }, + "each-async": { + "version": "1.1.1", + "from": "each-async@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz" + }, + "ecc-jsbn": { + "version": "0.1.1", + "from": "ecc-jsbn@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + }, + "electron-download": { + "version": "2.1.2", + "from": "electron-download@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-2.1.2.tgz", + "dependencies": { + "path-exists": { + "version": "1.0.0", + "from": "path-exists@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz" + } + } + }, + "electron-osx-sign": { + "version": "0.3.1", + "from": "electron-osx-sign@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.3.1.tgz" + }, + "end-of-stream": { + "version": "0.1.5", + "from": "end-of-stream@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz" + }, + "error-ex": { + "version": "1.3.0", + "from": "error-ex@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz" + }, + "escape-string-regexp": { + "version": "1.0.5", + "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + }, + "event-stream": { + "version": "3.1.7", + "from": "event-stream@>=3.1.0 <3.2.0", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz" + }, + "extend": { + "version": "3.0.0", + "from": "extend@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "extract-zip": { + "version": "1.5.0", + "from": "extract-zip@>=1.0.3 <2.0.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.5.0.tgz", + "dependencies": { + "debug": { + "version": "0.7.4", + "from": "debug@0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" + }, + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + }, + "mkdirp": { + "version": "0.5.0", + "from": "mkdirp@0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz" + } + } + }, + "extsprintf": { + "version": "1.0.2", + "from": "extsprintf@1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + }, + "fancy-log": { + "version": "1.2.0", + "from": "fancy-log@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.2.0.tgz" + }, + "fd-slicer": { + "version": "1.0.1", + "from": "fd-slicer@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz" + }, + "file-type": { + "version": "3.8.0", + "from": "file-type@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.8.0.tgz" + }, + "find-index": { + "version": "0.1.1", + "from": "find-index@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" + }, + "find-up": { + "version": "1.1.2", + "from": "find-up@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" + }, + "findup-sync": { + "version": "0.3.0", + "from": "findup-sync@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz" + }, + "first-chunk-stream": { + "version": "1.0.0", + "from": "first-chunk-stream@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz" + }, + "flagged-respawn": { + "version": "0.3.2", + "from": "flagged-respawn@>=0.3.2 <0.4.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz" + }, + "forever-agent": { + "version": "0.6.1", + "from": "forever-agent@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + }, + "form-data": { + "version": "0.2.0", + "from": "form-data@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "dependencies": { + "async": { + "version": "0.9.2", + "from": "async@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz" + } + } + }, + "from": { + "version": "0.1.3", + "from": "from@>=0.0.0 <1.0.0", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz" + }, + "fs-extra": { + "version": "0.28.0", + "from": "fs-extra@>=0.28.0 <0.29.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.28.0.tgz" + }, + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "gaze": { + "version": "0.5.2", + "from": "gaze@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz" + }, + "generate-function": { + "version": "2.0.0", + "from": "generate-function@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + }, + "generate-object-property": { + "version": "1.2.0", + "from": "generate-object-property@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + }, + "get-package-info": { + "version": "0.0.2", + "from": "get-package-info@0.0.2", + "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-0.0.2.tgz" + }, + "get-stdin": { + "version": "4.0.1", + "from": "get-stdin@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" + }, + "get-stream": { + "version": "1.1.0", + "from": "get-stream@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-1.1.0.tgz" + }, + "getpass": { + "version": "0.1.6", + "from": "getpass@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "glob": { + "version": "5.0.15", + "from": "glob@>=5.0.3 <6.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" + }, + "glob-stream": { + "version": "3.1.18", + "from": "glob-stream@>=3.1.5 <4.0.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "dependencies": { + "glob": { + "version": "4.5.3", + "from": "glob@>=4.3.1 <5.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz" + }, + "minimatch": { + "version": "2.0.10", + "from": "minimatch@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz" + }, + "through2": { + "version": "0.6.5", + "from": "through2@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz" + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "from": "glob-watcher@>=0.0.6 <0.0.7", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz" + }, + "glob2base": { + "version": "0.0.12", + "from": "glob2base@>=0.0.12 <0.0.13", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz" + }, + "globby": { + "version": "2.1.0", + "from": "globby@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "dependencies": { + "object-assign": { + "version": "3.0.0", + "from": "object-assign@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz" + } + } + }, + "globule": { + "version": "0.1.0", + "from": "globule@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "dependencies": { + "glob": { + "version": "3.1.21", + "from": "glob@>=3.1.21 <3.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz" + }, + "graceful-fs": { + "version": "1.2.3", + "from": "graceful-fs@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" + }, + "inherits": { + "version": "1.0.2", + "from": "inherits@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz" + }, + "lodash": { + "version": "1.0.2", + "from": "lodash@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz" + }, + "minimatch": { + "version": "0.2.14", + "from": "minimatch@>=0.2.11 <0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + } + } + }, + "glogg": { + "version": "1.0.0", + "from": "glogg@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz" + }, + "got": { + "version": "6.3.0", + "from": "got@>=6.3.0 <7.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-6.3.0.tgz" + }, + "graceful-fs": { + "version": "4.1.4", + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz" + }, + "graceful-readlink": { + "version": "1.0.1", + "from": "graceful-readlink@>=1.0.0", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + }, + "gulp-util": { + "version": "3.0.7", + "from": "gulp-util@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "object-assign": { + "version": "3.0.0", + "from": "object-assign@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz" + }, + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" + }, + "through2": { + "version": "2.0.1", + "from": "through2@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz" + } + } + }, + "gulplog": { + "version": "1.0.0", + "from": "gulplog@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz" + }, + "har-validator": { + "version": "1.8.0", + "from": "har-validator@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", + "dependencies": { + "bluebird": { + "version": "2.10.2", + "from": "bluebird@>=2.9.30 <3.0.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz" + } + } + }, + "has-ansi": { + "version": "2.0.0", + "from": "has-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" + }, + "has-gulplog": { + "version": "0.1.0", + "from": "has-gulplog@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz" + }, + "hawk": { + "version": "2.3.1", + "from": "hawk@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz" + }, + "hoek": { + "version": "2.16.3", + "from": "hoek@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + }, + "home-path": { + "version": "1.0.3", + "from": "home-path@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.3.tgz" + }, + "hosted-git-info": { + "version": "2.1.5", + "from": "hosted-git-info@>=2.1.4 <3.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz" + }, + "http-signature": { + "version": "0.10.1", + "from": "http-signature@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz" + }, + "i18next": { + "version": "2.5.1", + "from": "i18next@>=2.3.4 <3.0.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-2.5.1.tgz" + }, + "ieee754": { + "version": "1.1.6", + "from": "ieee754@>=1.1.4 <2.0.0", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.6.tgz" + }, + "indent-string": { + "version": "2.1.0", + "from": "indent-string@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz" + }, + "inflight": { + "version": "1.0.5", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz" + }, + "inherits": { + "version": "2.0.1", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "ini": { + "version": "1.3.4", + "from": "ini@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz" + }, + "interpret": { + "version": "1.0.1", + "from": "interpret@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz" + }, + "invert-kv": { + "version": "1.0.0", + "from": "invert-kv@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" + }, + "is-absolute": { + "version": "0.1.7", + "from": "is-absolute@>=0.1.5 <0.2.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz" + }, + "is-arrayish": { + "version": "0.2.1", + "from": "is-arrayish@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + }, + "is-builtin-module": { + "version": "1.0.0", + "from": "is-builtin-module@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz" + }, + "is-finite": { + "version": "1.0.1", + "from": "is-finite@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + }, + "is-my-json-valid": { + "version": "2.13.1", + "from": "is-my-json-valid@>=2.12.0 <3.0.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz" + }, + "is-natural-number": { + "version": "2.1.1", + "from": "is-natural-number@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz" + }, + "is-path-cwd": { + "version": "1.0.0", + "from": "is-path-cwd@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz" + }, + "is-path-in-cwd": { + "version": "1.0.0", + "from": "is-path-in-cwd@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz" + }, + "is-path-inside": { + "version": "1.0.0", + "from": "is-path-inside@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz" + }, + "is-plain-obj": { + "version": "1.1.0", + "from": "is-plain-obj@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + }, + "is-property": { + "version": "1.0.2", + "from": "is-property@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + }, + "is-redirect": { + "version": "1.0.0", + "from": "is-redirect@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz" + }, + "is-relative": { + "version": "0.1.3", + "from": "is-relative@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz" + }, + "is-retry-allowed": { + "version": "1.0.0", + "from": "is-retry-allowed@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.0.0.tgz" + }, + "is-stream": { + "version": "1.1.0", + "from": "is-stream@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" + }, + "is-typedarray": { + "version": "1.0.0", + "from": "is-typedarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + }, + "is-utf8": { + "version": "0.2.1", + "from": "is-utf8@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "isstream": { + "version": "0.1.2", + "from": "isstream@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + }, + "istextorbinary": { + "version": "1.0.2", + "from": "istextorbinary@1.0.2", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-1.0.2.tgz" + }, + "jodid25519": { + "version": "1.0.2", + "from": "jodid25519@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + }, + "jsbn": { + "version": "0.1.0", + "from": "jsbn@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" + }, + "json-schema": { + "version": "0.2.2", + "from": "json-schema@0.2.2", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz" + }, + "json-stringify-safe": { + "version": "5.0.1", + "from": "json-stringify-safe@>=5.0.0 <5.1.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + }, + "jsonfile": { + "version": "2.3.1", + "from": "jsonfile@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.3.1.tgz" + }, + "jsonpointer": { + "version": "2.0.0", + "from": "jsonpointer@2.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" + }, + "jsprim": { + "version": "1.3.0", + "from": "jsprim@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz" + }, + "klaw": { + "version": "1.3.0", + "from": "klaw@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.0.tgz" + }, + "lcid": { + "version": "1.0.0", + "from": "lcid@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" + }, + "liftoff": { + "version": "2.2.4", + "from": "liftoff@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.2.4.tgz" + }, + "load-json-file": { + "version": "1.1.0", + "from": "load-json-file@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz" + }, + "lodash": { + "version": "3.10.1", + "from": "lodash@>=3.5.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz" + }, + "lodash._basecopy": { + "version": "3.0.1", + "from": "lodash._basecopy@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz" + }, + "lodash._basetostring": { + "version": "4.12.0", + "from": "lodash._basetostring@>=4.12.0 <4.13.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "lodash._basevalues": { + "version": "3.0.0", + "from": "lodash._basevalues@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz" + }, + "lodash._getnative": { + "version": "3.9.1", + "from": "lodash._getnative@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "from": "lodash._isiterateecall@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" + }, + "lodash._reescape": { + "version": "3.0.0", + "from": "lodash._reescape@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz" + }, + "lodash._reevaluate": { + "version": "3.0.0", + "from": "lodash._reevaluate@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "from": "lodash._reinterpolate@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz" + }, + "lodash._root": { + "version": "3.0.1", + "from": "lodash._root@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz" + }, + "lodash._stringtopath": { + "version": "4.8.0", + "from": "lodash._stringtopath@>=4.8.0 <4.9.0", + "resolved": "https://registry.npmjs.org/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz" + }, + "lodash.assign": { + "version": "4.0.9", + "from": "lodash.assign@>=4.0.3 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.0.9.tgz" + }, + "lodash.escape": { + "version": "3.2.0", + "from": "lodash.escape@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz" + }, + "lodash.get": { + "version": "4.3.0", + "from": "lodash.get@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.3.0.tgz" + }, + "lodash.isarguments": { + "version": "3.0.8", + "from": "lodash.isarguments@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.8.tgz" + }, + "lodash.isarray": { + "version": "3.0.4", + "from": "lodash.isarray@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" + }, + "lodash.keys": { + "version": "4.0.7", + "from": "lodash.keys@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.0.7.tgz" + }, + "lodash.rest": { + "version": "4.0.3", + "from": "lodash.rest@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.3.tgz" + }, + "lodash.restparam": { + "version": "3.6.1", + "from": "lodash.restparam@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz" + }, + "lodash.template": { + "version": "3.6.2", + "from": "lodash.template@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "dependencies": { + "lodash._basetostring": { + "version": "3.0.1", + "from": "lodash._basetostring@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz" + }, + "lodash.keys": { + "version": "3.1.2", + "from": "lodash.keys@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + } + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "from": "lodash.templatesettings@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz" + }, + "log-rotate": { + "version": "0.2.7", + "from": "log-rotate@>=0.2.7 <0.3.0", + "resolved": "https://registry.npmjs.org/log-rotate/-/log-rotate-0.2.7.tgz" + }, + "log4js": { + "version": "0.6.37", + "from": "log4js@>=0.6.35 <0.7.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.37.tgz", + "dependencies": { + "semver": { + "version": "4.3.6", + "from": "semver@>=4.3.3 <4.4.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz" + } + } + }, + "loud-rejection": { + "version": "1.5.0", + "from": "loud-rejection@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.5.0.tgz" + }, + "lowercase-keys": { + "version": "1.0.0", + "from": "lowercase-keys@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz" + }, + "lru-cache": { + "version": "2.7.3", + "from": "lru-cache@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz" + }, + "map-obj": { + "version": "1.0.1", + "from": "map-obj@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" + }, + "map-stream": { + "version": "0.1.0", + "from": "map-stream@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz" + }, + "memorystream": { + "version": "0.3.1", + "from": "memorystream@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz" + }, + "meow": { + "version": "3.7.0", + "from": "meow@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz" + }, + "mime-db": { + "version": "1.12.0", + "from": "mime-db@>=1.12.0 <1.13.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz" + }, + "mime-types": { + "version": "2.0.14", + "from": "mime-types@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz" + }, + "minimatch": { + "version": "3.0.2", + "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz" + }, + "minimist": { + "version": "1.2.0", + "from": "minimist@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + }, + "minimongo-standalone": { + "version": "0.0.9", + "from": "minimongo-standalone@0.0.9", + "resolved": "https://registry.npmjs.org/minimongo-standalone/-/minimongo-standalone-0.0.9.tgz" + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "mkpath": { + "version": "0.1.0", + "from": "mkpath@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz" + }, + "mksnapshot": { + "version": "0.3.0", + "from": "mksnapshot@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.0.tgz", + "dependencies": { + "fs-extra": { + "version": "0.26.7", + "from": "fs-extra@0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz" + } + } + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "multipipe": { + "version": "0.1.2", + "from": "multipipe@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz" + }, + "mv": { + "version": "2.1.1", + "from": "mv@>=2.0.3 <3.0.0", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "dependencies": { + "glob": { + "version": "6.0.4", + "from": "glob@>=6.0.1 <7.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz" + }, + "rimraf": { + "version": "2.4.5", + "from": "rimraf@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz" + } + } + }, + "ncp": { + "version": "2.0.0", + "from": "ncp@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz" + }, + "node-status-codes": { + "version": "2.0.0", + "from": "node-status-codes@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-2.0.0.tgz" + }, + "node-uuid": { + "version": "1.4.7", + "from": "node-uuid@>=1.4.0 <1.5.0", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" + }, + "nopt": { + "version": "3.0.6", + "from": "nopt@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + }, + "normalize-package-data": { + "version": "2.3.5", + "from": "normalize-package-data@>=2.3.2 <3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz" + }, + "nugget": { + "version": "1.6.2", + "from": "nugget@>=1.5.1 <2.0.0", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz" + }, + "number-is-nan": { + "version": "1.0.0", + "from": "number-is-nan@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz" + }, + "numeral": { + "version": "1.5.3", + "from": "numeral@>=1.5.3 <2.0.0", + "resolved": "https://registry.npmjs.org/numeral/-/numeral-1.5.3.tgz" + }, + "oauth-sign": { + "version": "0.6.0", + "from": "oauth-sign@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.6.0.tgz" + }, + "object-assign": { + "version": "4.1.0", + "from": "object-assign@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz" + }, + "object-keys": { + "version": "0.4.0", + "from": "object-keys@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" + }, + "once": { + "version": "1.3.3", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" + }, + "onetime": { + "version": "1.1.0", + "from": "onetime@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz" + }, + "orchestrator": { + "version": "0.3.7", + "from": "orchestrator@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz" + }, + "ordered-read-streams": { + "version": "0.1.0", + "from": "ordered-read-streams@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz" + }, + "os-homedir": { + "version": "1.0.1", + "from": "os-homedir@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz" + }, + "os-locale": { + "version": "1.4.0", + "from": "os-locale@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz" + }, + "os-timesync": { + "version": "1.0.6", + "from": "os-timesync@>=1.0.6 <2.0.0", + "resolved": "https://registry.npmjs.org/os-timesync/-/os-timesync-1.0.6.tgz" + }, + "parse-json": { + "version": "2.2.0", + "from": "parse-json@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz" + }, + "path-exists": { + "version": "2.1.0", + "from": "path-exists@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz" + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + }, + "path-is-inside": { + "version": "1.0.1", + "from": "path-is-inside@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz" + }, + "path-type": { + "version": "1.1.0", + "from": "path-type@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" + }, + "pause-stream": { + "version": "0.0.11", + "from": "pause-stream@0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz" + }, + "pend": { + "version": "1.2.0", + "from": "pend@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" + }, + "pify": { + "version": "2.3.0", + "from": "pify@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + }, + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "pkg-conf": { + "version": "1.1.3", + "from": "pkg-conf@>=1.1.2 <2.0.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz" + }, + "plist": { + "version": "1.2.0", + "from": "plist@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz" + }, + "prepend-http": { + "version": "1.0.4", + "from": "prepend-http@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz" + }, + "pretty-bytes": { + "version": "1.0.4", + "from": "pretty-bytes@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz" + }, + "pretty-hrtime": { + "version": "1.0.2", + "from": "pretty-hrtime@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "progress-stream": { + "version": "1.2.0", + "from": "progress-stream@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz" + }, + "q": { + "version": "1.4.1", + "from": "q@>=1.1.2 <2.0.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz" + }, + "qs": { + "version": "2.4.2", + "from": "qs@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz" + }, + "rc": { + "version": "1.1.6", + "from": "rc@>=1.1.2 <2.0.0", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz" + }, + "read-pkg": { + "version": "1.1.0", + "from": "read-pkg@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" + }, + "read-pkg-up": { + "version": "1.0.1", + "from": "read-pkg-up@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" + }, + "readable-stream": { + "version": "1.0.34", + "from": "readable-stream@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" + }, + "rechoir": { + "version": "0.6.2", + "from": "rechoir@>=0.6.2 <0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + }, + "redent": { + "version": "1.0.0", + "from": "redent@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz" + }, + "repeating": { + "version": "2.0.1", + "from": "repeating@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" + }, + "replace-ext": { + "version": "0.0.1", + "from": "replace-ext@0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + }, + "replacestream": { + "version": "4.0.0", + "from": "replacestream@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.0.tgz", + "dependencies": { + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "object-assign": { + "version": "3.0.0", + "from": "object-assign@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz" + }, + "readable-stream": { + "version": "2.1.4", + "from": "readable-stream@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz" + } + } + }, + "request": { + "version": "2.55.0", + "from": "request@2.55.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.55.0.tgz" + }, + "request-progress": { + "version": "2.0.1", + "from": "request-progress@latest", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "dependencies": { + "throttleit": { + "version": "1.0.0", + "from": "throttleit@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz" + } + } + }, + "require-from-string": { + "version": "1.2.0", + "from": "require-from-string@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.0.tgz" + }, + "require-main-filename": { + "version": "1.0.1", + "from": "require-main-filename@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" + }, + "resolve": { + "version": "1.1.7", + "from": "resolve@>=1.1.6 <2.0.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" + }, + "rimraf": { + "version": "2.5.2", + "from": "rimraf@>=2.2.8 <3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz", + "dependencies": { + "glob": { + "version": "7.0.5", + "from": "glob@>=7.0.0 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz" + } + } + }, + "run-series": { + "version": "1.1.4", + "from": "run-series@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.4.tgz" + }, + "seek-bzip": { + "version": "1.0.5", + "from": "seek-bzip@>=1.0.5 <2.0.0", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "dependencies": { + "commander": { + "version": "2.8.1", + "from": "commander@>=2.8.1 <2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz" + } + } + }, + "semver": { + "version": "5.1.1", + "from": "semver@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.1.tgz" + }, + "sequencify": { + "version": "0.0.7", + "from": "sequencify@>=0.0.7 <0.1.0", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz" + }, + "set-blocking": { + "version": "1.0.0", + "from": "set-blocking@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-1.0.0.tgz" + }, + "set-immediate-shim": { + "version": "1.0.1", + "from": "set-immediate-shim@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" + }, + "sigmund": { + "version": "1.0.1", + "from": "sigmund@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + }, + "signal-exit": { + "version": "3.0.0", + "from": "signal-exit@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz" + }, + "single-line-log": { + "version": "0.4.1", + "from": "single-line-log@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz" + }, + "sntp": { + "version": "1.0.9", + "from": "sntp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + }, + "solc": { + "version": "0.3.5", + "from": "solc@>=0.3.1-1 <0.4.0", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.3.5.tgz" + }, + "sparkles": { + "version": "1.0.0", + "from": "sparkles@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" + }, + "spdx-correct": { + "version": "1.0.2", + "from": "spdx-correct@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz" + }, + "spdx-exceptions": { + "version": "1.0.4", + "from": "spdx-exceptions@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz" + }, + "spdx-expression-parse": { + "version": "1.0.2", + "from": "spdx-expression-parse@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz" + }, + "spdx-license-ids": { + "version": "1.2.1", + "from": "spdx-license-ids@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.1.tgz" + }, + "speedometer": { + "version": "0.1.4", + "from": "speedometer@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz" + }, + "split": { + "version": "0.2.10", + "from": "split@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz" + }, + "sshpk": { + "version": "1.8.3", + "from": "sshpk@>=1.7.0 <2.0.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz", + "dependencies": { + "asn1": { + "version": "0.2.3", + "from": "asn1@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + }, + "assert-plus": { + "version": "1.0.0", + "from": "assert-plus@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + } + } + }, + "stream-combiner": { + "version": "0.0.4", + "from": "stream-combiner@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" + }, + "stream-consume": { + "version": "0.1.0", + "from": "stream-consume@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "string-width": { + "version": "1.0.1", + "from": "string-width@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz" + }, + "stringstream": { + "version": "0.0.5", + "from": "stringstream@>=0.0.4 <0.1.0", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + }, + "strip-bom": { + "version": "2.0.0", + "from": "strip-bom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + }, + "strip-dirs": { + "version": "1.1.1", + "from": "strip-dirs@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz" + }, + "strip-indent": { + "version": "1.0.1", + "from": "strip-indent@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" + }, + "strip-json-comments": { + "version": "1.0.4", + "from": "strip-json-comments@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" + }, + "sum-up": { + "version": "1.0.3", + "from": "sum-up@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz" + }, + "supports-color": { + "version": "2.0.0", + "from": "supports-color@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + }, + "symbol": { + "version": "0.2.3", + "from": "symbol@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz" + }, + "tar-stream": { + "version": "1.5.2", + "from": "tar-stream@>=1.5.2 <2.0.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz", + "dependencies": { + "bl": { + "version": "1.1.2", + "from": "bl@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.5 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" + } + } + }, + "end-of-stream": { + "version": "1.1.0", + "from": "end-of-stream@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "readable-stream": { + "version": "2.1.4", + "from": "readable-stream@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz" + } + } + }, + "textextensions": { + "version": "1.0.2", + "from": "textextensions@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-1.0.2.tgz" + }, + "throttleit": { + "version": "0.0.2", + "from": "throttleit@0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz" + }, + "through": { + "version": "2.3.8", + "from": "through@>=2.3.6 <3.0.0", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + }, + "through2": { + "version": "0.2.3", + "from": "through2@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "from": "readable-stream@>=1.1.9 <1.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + }, + "xtend": { + "version": "2.1.2", + "from": "xtend@>=2.1.1 <2.2.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" + } + } + }, + "tildify": { + "version": "1.2.0", + "from": "tildify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz" + }, + "time-stamp": { + "version": "1.0.1", + "from": "time-stamp@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.0.1.tgz" + }, + "timed-out": { + "version": "2.0.0", + "from": "timed-out@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz" + }, + "touch": { + "version": "0.0.3", + "from": "touch@0.0.3", + "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", + "dependencies": { + "nopt": { + "version": "1.0.10", + "from": "nopt@>=1.0.10 <1.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz" + } + } + }, + "tough-cookie": { + "version": "2.2.2", + "from": "tough-cookie@>=0.12.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz" + }, + "traverse": { + "version": "0.3.9", + "from": "traverse@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" + }, + "trim-newlines": { + "version": "1.0.0", + "from": "trim-newlines@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" + }, + "tunnel-agent": { + "version": "0.4.3", + "from": "tunnel-agent@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" + }, + "tweetnacl": { + "version": "0.13.3", + "from": "tweetnacl@>=0.13.0 <0.14.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz" + }, + "typedarray": { + "version": "0.0.6", + "from": "typedarray@>=0.0.5 <0.1.0", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + }, + "unbzip2-stream": { + "version": "1.0.9", + "from": "unbzip2-stream@>=1.0.9 <2.0.0", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.0.9.tgz" + }, + "underscore": { + "version": "1.8.3", + "from": "underscore@>=1.8.3 <2.0.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" + }, + "unique-stream": { + "version": "1.0.0", + "from": "unique-stream@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" + }, + "unzip-response": { + "version": "1.0.0", + "from": "unzip-response@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.0.tgz" + }, + "url-parse-lax": { + "version": "1.0.0", + "from": "url-parse-lax@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz" + }, + "user-home": { + "version": "1.1.1", + "from": "user-home@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" + }, + "utf8": { + "version": "2.1.1", + "from": "utf8@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "uuid": { + "version": "2.0.2", + "from": "uuid@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz" + }, + "v8flags": { + "version": "2.0.11", + "from": "v8flags@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.11.tgz" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "from": "validate-npm-package-license@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz" + }, + "verror": { + "version": "1.3.6", + "from": "verror@1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + }, + "vinyl": { + "version": "0.5.3", + "from": "vinyl@>=0.5.0 <0.6.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz" + }, + "vinyl-fs": { + "version": "0.3.14", + "from": "vinyl-fs@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "dependencies": { + "clone": { + "version": "0.2.0", + "from": "clone@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz" + }, + "graceful-fs": { + "version": "3.0.8", + "from": "graceful-fs@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz" + }, + "strip-bom": { + "version": "1.0.0", + "from": "strip-bom@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz" + }, + "through2": { + "version": "0.6.5", + "from": "through2@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz" + }, + "vinyl": { + "version": "0.4.6", + "from": "vinyl@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" + } + } + }, + "web3": { + "version": "0.17.0-alpha", + "from": "web3@>=0.17.0-alpha <0.18.0", + "resolved": "https://registry.npmjs.org/web3/-/web3-0.17.0-alpha.tgz", + "dependencies": { + "bignumber.js": { + "version": "2.0.7", + "from": "git+https://github.com/debris/bignumber.js.git#master", + "resolved": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + } + } + }, + "window-size": { + "version": "0.2.0", + "from": "window-size@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz" + }, + "wrap-ansi": { + "version": "2.0.0", + "from": "wrap-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.0.0.tgz" + }, + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + }, + "xmlbuilder": { + "version": "4.0.0", + "from": "xmlbuilder@4.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.0.0.tgz" + }, + "xmldom": { + "version": "0.1.22", + "from": "xmldom@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.22.tgz" + }, + "xmlhttprequest": { + "version": "1.8.0", + "from": "xmlhttprequest@*", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz" + }, + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + }, + "y18n": { + "version": "3.2.1", + "from": "y18n@>=3.2.1 <4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz" + }, + "yargs": { + "version": "4.7.1", + "from": "yargs@>=4.3.1 <5.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.7.1.tgz" + }, + "yargs-parser": { + "version": "2.4.0", + "from": "yargs-parser@>=2.4.0 <3.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.0.tgz", + "dependencies": { + "camelcase": { + "version": "2.1.1", + "from": "camelcase@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz" + } + } + }, + "yauzl": { + "version": "2.4.1", + "from": "yauzl@2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz" + } + } +} diff --git a/package.json b/package.json index bff8a5722..b9ebf34a2 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "Mist", - "version": "0.7.6", + "version": "0.8.0", "license": "GPL-3.0", "repository": { "type": "git", "url": "https://github.com/ethereum/mist.git" }, "scripts": { - "test": "gulp", + "ci": "gulp --platform=linux", "postinstall": "gulp update-nodes" }, "main": "main.js", @@ -21,7 +21,7 @@ "log4js": "^0.6.35", "minimongo-standalone": "0.0.9", "numeral": "^1.5.3", - "os-timesync": "^1.0.3", + "os-timesync": "^1.0.6", "semver": "^5.1.0", "solc": "^0.3.1-1", "underscore": "^1.8.3", @@ -30,17 +30,27 @@ "yargs": "^4.3.1" }, "devDependencies": { + "chai": "^3.5.0", + "co-mocha": "^1.1.2", "del": "^1.2.1", + "easy-zip": "0.0.4", "electron-packager": "^7.0.4", + "genomatic": "^1.0.0", + "geth-private": "^1.3.0", "gulp": "^3.9.0", "gulp-decompress": "^2.0.0", - "gulp-download": "0.0.1", + "gulp-download-stream": "0.0.13", "gulp-rename": "^1.2.2", "gulp-replace": "^0.5.4", + "gulp-spawn-mocha": "^2.2.2", "gulp-tap": "^0.1.3", + "gulp-zip": "^3.2.0", "merge-stream": "^1.0.0", "minimist": "^1.1.3", - "rcedit": "^0.3.0" + "rcedit": "^0.3.0", + "run-sequence": "^1.2.1", + "shelljs": "^0.7.0", + "spectron": "^3.2.2" }, "engines": { "node": ">4.3.0", diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 000000000..40664721f --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,2 @@ +mist.log +mist.png \ No newline at end of file diff --git a/test/_base.js b/test/_base.js new file mode 100644 index 000000000..afaee3e62 --- /dev/null +++ b/test/_base.js @@ -0,0 +1,261 @@ +"use strict"; + +require('co-mocha'); + +const _ = require('underscore'); +const genomatic = require('genomatic'); +const Q = require('bluebird'); +const fs = require('fs'); +const Web3 = require('web3'); +const shell = require('shelljs'); +const path = require('path'); +const packageJson = require('../package.json'); +const gethPrivate = require('geth-private'); +const Application = require('spectron').Application; + +const chai = require('chai'); +chai.should(); + +process.env.TEST_MODE = 'true'; + + +exports.mocha = function(_module, options) { + const tests = {}; + + options = _.extend({ + app: 'mist' + }, options); + + _module.exports[options.name || path.basename(_module.filename)] = { + before: function*() { + this.timeout(10000000); + + this.assert = chai.assert; + this.expect = chai.expect; + + const logFilePath = path.join(__dirname, 'mist.log'); + shell.rm('-rf', logFilePath); + + const appFileName = ('wallet' === options.app) ? 'Ethereum-Wallet' : 'Mist', + appVers = packageJson.version.replace(/\./ig, '-'), + platformArch = `${process.platform}-${process.arch}`; + + let appPath, gethPath; + + switch (platformArch) { + case 'darwin-x64': + appPath = path.join( + process.cwd(), + `dist_${options.app}`, + `${appFileName}-macosx-${appVers}`, + `${appFileName}.app`, + 'Contents', + 'MacOS', + appFileName + ); + break; + case 'linux-x64': + appPath = path.join( + process.cwd(), + `dist_${options.app}`, + `${appFileName}-linux64-${appVers}`, + appFileName + ); + break; + default: + throw new Error(`Cannot run tests on ${platformArch}, please run on: darwin-x64, linux-x64`) + } + + // check that appPath exists + if (!shell.test('-f', appPath)) { + throw new Error('Cannot find binary: ' + appPath); + } + + this.geth = gethPrivate({ + gethPath: path.join(process.cwd(), 'nodes', 'geth', platformArch, 'geth'), + balance: 5, + genesisBlock: { + difficulty: '0x1', + extraData: '0x1', + }, + gethOptions: { + port: 58546, + rpcport: 58545, + }, + }); + + yield this.geth.start(); + + this.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:58545")); + + + this.app = new Application({ + requireName: 'electronRequire', + startTimeout: 5000, + waitTimeout: 5000, + quitTimeout: 10000, + path: appPath, + args: [ + '--mode', options.app, + '--loglevel', 'debug', + '--logfile', logFilePath, + '--node-datadir', this.geth.dataDir, + '--ipcpath', path.join(this.geth.dataDir, 'geth.ipc') + ], + }); + + yield this.app.start(); + + this.client = this.app.client; + + yield this.client.waitUntilWindowLoaded(); + + // wait a small amount of time to ensure main app window is ready with data + yield Q.delay(8000); + + // console.log(this.app.chromeDriver.logLines); + + /* + Utility methods + */ + for (let key in Utils) { + this[key] = genomatic.bind(Utils[key], this); + } + + this.mainWindowHandle = (yield this.client.windowHandle()).value; + }, + + after: function*() { + if (this.app && this.app.isRunning()) { + yield this.app.stop(); + } + + if (this.geth && this.geth.isRunning) { + yield this.geth.stop(); + } + }, + + tests: tests, + }; + + return tests; +}; + + + +const Utils = { + waitUntil: function*(msg, promiseFn) { + yield this.client.waitUntil(promiseFn, + 10000, + msg, + 500); + }, + getUiElements: function*(selector) { + const elems = yield this.client.elements(selector); + + return elems.value; + }, + getUiElement: function*(selector) { + const elem = yield this.client.element(selector); + + return elem.value; + }, + openAndFocusNewWindow: function*(fnPromise) { + const client = this.client; + + const existingHandles = (yield client.windowHandles()).value; + + yield fnPromise(); + + yield this.waitUntil('new window visible', function checkForAddWindow() { + return client.windowHandles().then((handles) => { + return handles.value.length === existingHandles.length + 1; + }); + }); + + const newHandles = (yield client.windowHandles()).value; + + // focus on new window + yield client.window(newHandles.pop()); + }, + execElemsMethod: function*(clientElementIdMethod, selector) { + const elems = yield this.client.elements(selector); + + const values = yield elems.value.map( + (e) => this.client[clientElementIdMethod](e.ELEMENT) + ); + + return values.map(r => r.value); + }, + execElemMethod: function*(clientElementIdMethod, selector) { + const e = yield this.client.element(selector); + + console.log(e); + + const value = yield this.client[clientElementIdMethod](e.ELEMENT); + + return value.value; + }, + capturePage: function*() { + let pageImage = yield this.app.browserWindow.capturePage(); + + if (!pageImage) { + throw new Error('Page capture failed'); + } + + fs.writeFileSync(path.join(__dirname, 'mist.png'), pageImage); + }, + getRealAccountBalances: function*() { + let accounts = this.web3.eth.accounts; + + let balances = accounts.map((acc) => + this.web3.fromWei(this.web3.eth.getBalance(acc), 'ether') + '' + ); + + accounts = accounts.map(a => a.toLowerCase()); + balances = balances.map(b => parseInt(b)); + + return _.object(accounts, balances); + }, + getUiAccountBalances: function*() { + // check balances on the pgetUiAccountsBalancesage + let _accounts = yield this.execElemsMethod('elementIdText', '.wallet-box .account-id'); + let _balances = yield this.execElemsMethod('elementIdText', '.wallet-box .account-balance'); + + _accounts = _accounts.map(a => a.toLowerCase()); + _balances = _balances.map(b => parseInt(b)); + + return _.object(_accounts, _balances); + }, + openAccountInUi: function*(accId) { + let _accounts = yield this.execElemsMethod('elementIdText', '.wallet-box .account-id'); + + let idx = -1; + + accId = accId.toLowerCase(); + + for (let i in _accounts) { + if (_accounts[i].toLowerCase() === accId) { + idx = i; + } + } + + if (0 > idx) { + throw new Error('Unable to find account in UI'); + } + + const accLinks = yield this.client.elements('.wallet-box'); + + yield this.client.elementIdClick(accLinks.value[idx].ELEMENT); + + yield Q.delay(1000); + }, + startMining: function*() { + yield this.geth.consoleExec('miner.start();'); + }, + stopMining: function*() { + yield this.geth.consoleExec('miner.stop();'); + }, +} + + diff --git a/test/wallet/basic.test.js b/test/wallet/basic.test.js new file mode 100644 index 000000000..37e9e3a6e --- /dev/null +++ b/test/wallet/basic.test.js @@ -0,0 +1,125 @@ +"use strict"; + +const _ = require('underscore'); + +const Q = require('bluebird'), + fs = require('fs'), + path = require('path'); + + +const test = require('../_base').mocha(module, { + app: 'wallet' +}); + + + + +test['title'] = function*() { + yield this.client.window(this.mainWindowHandle); + + (yield this.client.getTitle()).should.eql('Ethereum Wallet'); +}; + + + +test['account balances'] = function*() { + const web3 = this.web3; + const client = this.client; + + const realBalances = this.getRealAccountBalances(); + const appBalances = this.getUiAccountBalances(); + + appBalances.should.eql(realBalances); +}; + + +// test['create account'] = function*() { +// const web3 = this.web3; +// const client = this.client; + +// const originalBalances = yield this.getRealAccountBalances(); + +// yield _createNewAccount.call(this); + +// const realBalances = yield this.getRealAccountBalances(); +// const appBalances = yield this.getUiAccountBalances(); + +// _.keys(realBalances).length.should.eql(_.keys(originalBalances).length + 1); +// appBalances.should.eql(realBalances); +// }; + + + +test['deposit into account'] = function*() { + const web3 = this.web3; + const client = this.client; + + let accounts = web3.eth.accounts; + + yield _createNewAccount.call(this); + + let newAccount = _.difference(web3.eth.accounts, accounts)[0]; + + yield this.openAccountInUi(newAccount); + + // links + const accLinks = yield this.getUiElements('.dapp-actionbar li'); + yield client.elementIdClick(accLinks[0].ELEMENT); + + // fill in send form and submit + yield _completeSendForm.call(this, 1); + + // do some mining + yield this.startMining(); + yield Q.delay(10000); + yield this.stopMining(); + + // check balances + let realBalances = yield this.getRealAccountBalances(); + + realBalances[newAccount].should.eql(1); +}; + + + + +const _createNewAccount = function*() { + const client = this.client; + + // open password window + yield this.openAndFocusNewWindow(() => { + return client.click('button.create.account'); + }); + + // enter password + yield client.setValue('form .password', '1234'); + yield client.click('form button.ok'); + + // re-enter password + yield client.setValue('form .password-repeat', '1234'); + yield client.click('form button.ok'); + + yield Q.delay(10000); + + yield client.window(this.mainWindowHandle); +}; + + + +const _completeSendForm = function*(amt) { + const client = this.client; + + // enter password + yield client.setValue('form input[name=amount]', '' + amt); + + // open password window + yield this.openAndFocusNewWindow(() => { + return client.click('form button[type=submit]'); + }); + + // fill in password and submit + yield client.setValue('form input[type=password]', '1234'); + yield client.click('form button.ok'); + + yield Q.delay(5000); +};