From d34cf6defbf77dcf289bc069a795661f687e8b08 Mon Sep 17 00:00:00 2001 From: Juan Cazala Date: Sat, 16 Sep 2017 17:14:52 -0300 Subject: [PATCH] added rpc --- LICENSE | 19 ++ README.md | 61 ++++++- bin/coin-hive | 13 +- package-lock.json | 453 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 +- src/index.js | 47 +++-- src/puppeteer.js | 101 +++++++---- test/spec.js | 26 ++- 8 files changed, 658 insertions(+), 68 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d13cc4b --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 334f054..8c0660f 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ var CoinHive = require('coin-hive'); // Listen on events miner.on('found', () => console.log('Found!')) miner.on('accepted', () => console.log('Accepted!')) - miner.on('update', (data) => console.log(` -Hashes per second: ${data.hashesPerSecond} -Total hashes: ${data.totalHashes} -Accepted hashes: ${data.acceptedHashes} + miner.on('update', data => console.log(` + Hashes per second: ${data.hashesPerSecond} + Total hashes: ${data.totalHashes} + Accepted hashes: ${data.acceptedHashes} `)); // Stop miner @@ -40,7 +40,60 @@ Accepted hashes: ${data.acceptedHashes} coin-hive ``` +## API + +- `CoinHive(siteKey)`: Returns a promise of a `Miner` instance. + +- `miner.start()`: Connect to the pool and start mining. Returns a promise that will resolve once the miner is started. + +- `miner.stop()`: Stop mining and disconnect from the pool. Returns a promise that will resolve once the miner is stopped. + +- `miner.on(event, callback)`: Specify a callback for an event. The event types are: + + - `open`: The connection to our mining pool was opened. Usually happens shortly after miner.start() was called. + + - `authed`: The miner successfully authed with the mining pool and the siteKey was verified. Usually happens right after open. + + - `close`: The connection to the pool was closed. Usually happens when miner.stop() was called. + + - `error`: An error occured. In case of a connection error, the miner will automatically try to reconnect to the pool. + + - `job`: A new mining job was received from the pool. + + - `found`: A hash meeting the pool's difficulty (currently 256) was found and will be send to the pool. + + - `accepted`: A hash that was sent to the pool was accepted. + +- `miner.rpc(methodName, argsArray)`: This method allows to interact with the Coin-Hive miner instance. It returns a Promise that resolves the the value of the remote method that was called. The miner intance API can be [found here](https://coin-hive.com/documentation/miner#miner-is-running). Here's an example: + +```js +var miner = await CoinHive('SITE_KEY'); +await miner.rpc('isRunning'); // false +await miner.start(); +await miner.rpc('isRunning'); // true +await miner.rpc('getThrottle'); // 0 +await miner.rpc('setThrottle', [0.5]); +await miner.rpc('getThrottle'); // 0.5 +``` + +## ENVIRONMENT VARIABLES + +All the following environment variables can be used to configure the miner from the outside: + +- `SITE_KEY`: Coin-Hive's Site Key + +- `INTERVAL`: The interval on which the miner reports an update + +- `PORT`: The port that will be used to launch the server, and where puppeteer will point to + +- `HOST`: The host that will be used to launch the server, and where puppeteer will point to + +- `PUPPETEER_URL`: In case you don't want to point puppeteer to the local server, you can use this to make it point somewhere else where the miner is served (ie: `PUPPETEER_URL=http://coin-hive.herokuapp.com`) + ## Requisites + Node v8+ +## Disclaimer + +I have nothing to do with `coin-hive.com` \ No newline at end of file diff --git a/bin/coin-hive b/bin/coin-hive index 50b991e..fcd97de 100755 --- a/bin/coin-hive +++ b/bin/coin-hive @@ -1,11 +1,16 @@ #!/usr/bin/env node 'use strict'; const CoinHive = require('../src'); +const defaults = require('../config/defaults'); console.log('Initializing...'); (async () => { const siteKey = process.argv[2]; + const interval = process.argv[3] || defaults.INTERVAL; + const port = process.argv[4] || defaults.PORT; + const host = process.argv[5] || defaults.HOST; + const help = `Usage: 'coin-hive [, , , ]' - : You CoinHive Site Key @@ -21,10 +26,14 @@ console.log('Initializing...'); break; default: { - var miner = await CoinHive(siteKey); + var miner = await CoinHive(siteKey, interval, port, host); await miner.start(); - console.log('Initialized!'); + console.log('Initialized!\n'); + console.log('Site Key:', siteKey); + console.log('Interval:', interval); + console.log('Port:', port); + console.log('Host:', host, '\n'); miner.on('found', () => console.log('Found!')) miner.on('accepted', () => console.log('Accepted!')) diff --git a/package-lock.json b/package-lock.json index 329c9e5..bb346ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,11 +21,47 @@ "es6-promisify": "5.0.0" } }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -40,12 +76,66 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", "dev": true }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "commander": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", @@ -158,6 +248,38 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expect": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-21.1.0.tgz", + "integrity": "sha512-gBmUVy+A4+brj/MnuiwLe+MIMfSffWUmZMNjKHrMkB0cpkAjnFdwHAxs6MvYeh4+14ocp+SfKp4ebNEhkbV3YQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "jest-diff": "21.1.0", + "jest-get-type": "21.0.2", + "jest-matcher-utils": "21.1.0", + "jest-message-util": "21.1.0", + "jest-regex-util": "21.1.0" + } + }, "express": { "version": "4.15.4", "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", @@ -193,6 +315,15 @@ "vary": "1.1.1" } }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, "extract-zip": { "version": "1.6.5", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.5.tgz", @@ -227,6 +358,25 @@ "pend": "1.2.0" } }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, "finalhandler": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", @@ -241,6 +391,21 @@ "unpipe": "1.0.0" } }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -269,6 +434,25 @@ "path-is-absolute": "1.0.1" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, "graceful-readlink": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", @@ -332,17 +516,144 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=" }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "jest-diff": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-21.1.0.tgz", + "integrity": "sha512-mGJinKrAB6hj1cpO1FOuDCfgILozGvYi4Zpk8GrxmNgdd9/9llIA2Xzu5879Fa4ayh7lb9ej2NdvuNLMCjbrMg==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "diff": "3.2.0", + "jest-get-type": "21.0.2", + "pretty-format": "21.1.0" + } + }, + "jest-get-type": { + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.0.2.tgz", + "integrity": "sha512-4KvNzzXMXeapGaMWd+SL5e47zcMn8KTWjom6Fl3avxVXnbKS7abD1p4xWe4ToAZfgNoYNsQ9Av/mnWMnZK/Z4A==", + "dev": true + }, + "jest-matcher-utils": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-21.1.0.tgz", + "integrity": "sha512-V/Xindf+VY5UM+oz9Nhsv0Ql93lRcKS7tHtVoXtlXkZXoXpydHwuezkLLCpZkH/Uew5y2OyDZpnlxPvEalJZng==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "jest-get-type": "21.0.2", + "pretty-format": "21.1.0" + } + }, + "jest-message-util": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-21.1.0.tgz", + "integrity": "sha512-BwKrjR4HvGoodYw3PFh95IU4qDk3nVOf3LqOKRaaR6486bJM8IZIlxWR8yfxhAN7nDGBDco/TR+U50WcPgzvgA==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "micromatch": "2.3.11", + "slash": "1.0.0" + } + }, + "jest-regex-util": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-21.1.0.tgz", + "integrity": "sha512-1QiJa6nvdzVgDhY1FTG3fl+2eYrCQGQoIeGaVPjt9+VmxsQ/BwZD6aglH0z6ZK/uEXZPAaj1XaemKM9tC6VVlQ==", + "dev": true + }, "json3": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", "dev": true }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, "lodash._baseassign": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", @@ -426,6 +737,27 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, "mime": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.0.tgz", @@ -520,6 +852,25 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -536,6 +887,18 @@ "wrappy": "1.0.2" } }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", @@ -556,6 +919,22 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-format": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.1.0.tgz", + "integrity": "sha512-041BVxr2pp7uGG8slfw43ysRXSaBIVqo5Li03BwI3K1/9oENlhkEEYWPkHpDzj7NlJ3GZte+Tv/DId5g2PLduA==", + "dev": true, + "requires": { + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.0" + } + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -600,6 +979,47 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==" }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -619,6 +1039,33 @@ "util-deprecate": "1.0.2" } }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -675,6 +1122,12 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", diff --git a/package.json b/package.json index 9d71b37..196bb76 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,8 @@ "description": "", "main": "src/index.js", "scripts": { - "test": "mocha test --timeout 60000" + "test": "mocha test --timeout 600000" }, - "author": "", "license": "MIT", "dependencies": { "express": "^4.15.4", @@ -16,10 +15,11 @@ "coin-hive": "./bin/coin-hive" }, "devDependencies": { + "expect": "^21.1.0", "mocha": "^3.5.3" }, "repository": { "type": "git", "url": "git+https://github.com/cazala/coin-hive.git" } -} +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index df6fde8..c25aec2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,25 +1,32 @@ -var server = require('./server'); -var puppeteer = require('./puppeteer'); -var defaults = require('../config/defaults'); +const server = require('./server'); +const puppeteer = require('./puppeteer'); +const defaults = require('../config/defaults'); -module.exports = async function getRunner(siteKey = defaults.SITE_KEY) { - - var port = process.env.PORT || defaults.PORT; - var host = process.env.HOST || defaults.HOST; - - var miner = await new Promise((resolve, reject) => { - server().listen(port, host, async (err) => { - if (err) { - return reject(err); +module.exports = async function getRunner( + siteKey = defaults.SITE_KEY, + interval = defaults.INTERVAL, + port = defaults.PORT, + host = defaults.HOST +) { + const miner = await new Promise((resolve, reject) => { + var minerServer = server().listen( + process.env.SERVER_PORT || process.env.PORT || port, + process.env.SERVER_HOST || process.env.HOST || host, + async (err) => { + if (err) { + return reject(err); + } + return resolve( + puppeteer({ + siteKey, + interval, + port, + host, + server: minerServer + }) + ); } - return resolve( - puppeteer({ - siteKey, - port, - host, - interval: defaults.INTERVAL - })); - }); + ); }); await miner.init(); return miner; diff --git a/src/puppeteer.js b/src/puppeteer.js index 80d39fa..f19eea1 100644 --- a/src/puppeteer.js +++ b/src/puppeteer.js @@ -1,70 +1,101 @@ -var EventEmitter = require('events'); -var puppeteer = require('puppeteer'); -var defaults = require('../config/defaults'); - -// Browser -var browser = null; -var getBrowser = async () => { - if (browser) { - return browser; - } - browser = await puppeteer.launch({ args: ['--no-sandbox'] }); - return browser; -} - -// Page -var page = null; -var getPage = async () => { - if (page) { - return page; - } - page = (await getBrowser()).newPage(); - return page; -} +const EventEmitter = require('events'); +const puppeteer = require('puppeteer'); +const defaults = require('../config/defaults'); class Puppeteer extends EventEmitter { - constructor(siteKey, interval, port, host) { + constructor(siteKey, interval, port, host, server) { super(); + this.inited = false; + this.dead = false; this.siteKey = siteKey; this.interval = interval; this.host = host; this.port = port; + this.server = server; + this.browser = null; + this.page = null; } - async init() { + async getBrowser() { + if (this.browser) { + return this.browser; + } + this.browser = await puppeteer.launch({ args: ['--no-sandbox'] }); + return this.browser; + } + + async getPage() { if (this.page) { return this.page; } + this.page = await (await this.getBrowser()).newPage(); + return this.page; + } + + async init() { + + if (this.dead) { + throw new Error('This miner has been killed'); + } + + if (this.inited) { + return this.page; + } - const page = await getPage(); - await page.goto(`http://${this.host}:${this.port}`); + const page = await this.getPage(); + const url = process.env.PUPPETEER_URL || `http://${this.host}:${this.port}`; + await page.goto(url); await page.exposeFunction('found', () => this.emit('found')); await page.exposeFunction('accepted', () => this.emit('accepted')); await page.exposeFunction('update', (data, interval) => this.emit('update', data, interval)); await page.evaluate((siteKey, interval) => window.init(siteKey, interval), this.siteKey, this.interval); - this.page = page; + this.inited = true; + return this.page; } async start() { await this.init(); - this.page.evaluate(() => window.start()); + return this.page.evaluate(() => window.start()); } async stop() { await this.init(); - this.page.evaluate(() => window.stop()); + return this.page.evaluate(() => window.stop()); + } + + async kill() { + try { + await this.stop(); + } catch (e) { console.log('Error stopping miner', e) } + try { + const browser = await this.getBrowser(); + await browser.close(); + } catch (e) { console.log('Error closing browser', e) } + try { + if (this.server) { + this.server.close(); + console.log('server closed') + } + } catch (e) { console.log('Error closing server', e) } + this.dead = true; + } + + async rpc(method, args) { + await this.init(); + return this.page.evaluate((method, args) => window.miner[method].apply(window.miner, args), method, args) } } module.exports = function getPuppeteer(options = {}) { - var siteKey = options.siteKey || defaults.SITE_KEY; - var interval = options.interval || defaults.INTERVAL; - var port = options.port || defaults.PORT; - var host = options.host || defaults.HOST; + const siteKey = process.env.SITE_KEY || options.siteKey || defaults.SITE_KEY; + const interval = process.env.INTERVAL || options.interval || defaults.INTERVAL; + const port = process.env.PUPPETEER_PORT || process.env.PORT || options.port || defaults.PORT; + const host = process.env.PUPPETEER_HOST || process.env.HOST || options.host || defaults.HOST; + const server = options.server || null; - return new Puppeteer(siteKey, interval, port, host); + return new Puppeteer(siteKey, interval, port, host, server); } \ No newline at end of file diff --git a/test/spec.js b/test/spec.js index af061ba..f0505ab 100644 --- a/test/spec.js +++ b/test/spec.js @@ -1,15 +1,33 @@ +const expect = require('expect'); const CoinHive = require('../src'); -describe('Coin-Hive', () => { + +describe('Coin-Hive', async () => { + it('should mine', async () => { var miner = await CoinHive(); await miner.start(); return new Promise(resolve => { - miner.on('update', (data) => { + miner.on('update', async (data) => { if (data.acceptedHashes > 0) { - miner.stop(); + await miner.kill(); resolve(); } }) }); - }) + }); + + it('should do RPC', async () => { + var miner = await CoinHive(); + let isRunning = await miner.rpc('isRunning'); + expect(isRunning).toBe(false); + await miner.start(); + isRunning = await miner.rpc('isRunning'); + expect(isRunning).toBe(true); + let threads = await miner.rpc('getNumThreads'); + expect(typeof threads).toBe('number'); + await miner.rpc('setNumThreads', [2]); + threads = await miner.rpc('getNumThreads'); + expect(threads).toBe(2); + await miner.kill(); + }); }); \ No newline at end of file