Git Product home page Git Product logo

node-stratum's Introduction

Build Status Coverage Status Dependency Status

NPM

Node.js Stratum Server / Client / RPC Daemon

Exposes a server to enable Stratum mining protocol (server and client) usage on Node.js and subscribe for events using EventEmitter, and accept stratum-notify from *coind daemons

This is not a ready-to-use miner pool, you may use this server to implement your favorite altcoins, all the pool logic is up to you (shares, passwords, sessions, etc).

Highlights

  • Simple but powerful API for managing both server and client
  • Build-in support for spawn coins daemons (bitcoind, litecoind, etc) process and accept RPC calls
  • Easy for you to add your own procedures do the RPC server (using expose)
  • No need to worry about .conf files for the daemons, everything is passed through command line the best way possible (but you may override arguments)
  • All classes based on EventEmitter by default (through the Base class)
  • The client part make it easy, along with an RPC server, to setup your own farming pool for coins
  • You can create a proxy from it using the Client interface, mix up Stratum with your own RPC definition and commands

Install

npm install stratum

Notice that you may install this globally using -g, stratum-notify will be available system wide

Stratum notify

if you want to call it manually for testing purposes
node node_modules/.bin/stratum-notify --host localhost --port 1337 --password willbebase64encoded --type block --data "jsondata"

This command is called automatically if you set the coind options, they are forked when the server is started.

Usage

var Server = require('stratum').Server;

// these settings can be changed using Server.defaults as well, for every new server up
var server = new Server({
  /**
   * RPC to listen interface for this server
   */
  rpc     : {
    /**
     * Bind to address
     *
     * @type {String}
     */
    host: 'localhost',
    /**
     * RPC port
     *
     * @type {Number}
     */
    port: 1337,
    /**
     * RPC password, this needs to be a SHA256 hash, defaults to 'password'
     * To create a hash out of your password, launch node.js and write
     *
     * require('crypto').createHash('sha256').update('password').digest('hex');
     *
     * @type {String}
     */
    password: '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8',
    /**
     * Mode to listen. By default listen only on TCP, but you may use 'http' or 'both' (deal
     * with HTTP and TCP at same time)
     */
    mode: 'tcp'
  },
  /**
   * The server settings itself
   */
  settings: {
    /**
     * Address to set the X-Stratum header if someone connects using HTTP
     * @type {String}
     */
    hostname: 'localhost',
    /**
     * Max server lag before considering the server "too busy" and drop new connections
     * @type {Number}
     */
    toobusy : 70,
    /**
     * Bind to address, use 0.0.0.0 for external access
     * @type {string}
     */
    host    : 'localhost',
    /**
     * Port for the stratum TCP server to listen on
     * @type {Number}
     */
    port    : 3333
  }
});

server.on('mining', function(req, deferred){
    switch (req.method){
        case 'subscribe':
            // req.params[0] -> if filled, it's the User Agent, like CGMiner/CPUMiner sends
            // Just resolve the deferred, the promise will be resolved and the data sent to the connected client
            deferred.resolve([subscription, extranonce1, extranonce2_size]);
            break;
    }
});

server.listen();

You can connect to Stratum servers as well:

var Client = require('stratum').Client;

client = new Client();

client.connect({
    host: 'localhost',
    port: 3333
}).then(function(){
    return ...;
}).then(function(value){
    if (value){
        //etc
    }
});

Examples

Check the examples folder, each part (client and server) is completely explained, and how to proceed on each possible case.

Documentation

The following documentation expects that:

var stratum = require('stratum');

Base

Available through stratum.Base

All the classes inherit from the base class, that inherits from EventEmitter3, and got an additional method:

debug(msg)

Show debug messages for the class only if DEBUG=stratum environment variable is set

stratum.Base.debug('oops');

Server

Available through stratum.Server

You can write your own defaults that applies to all new server instances through stratum.Server.defaults

stratum.Server.defaults.settings.toobusy = 50;

You can also include your own stratum method calls through stratum.Server.commands object, the server will lookup them automatically and provide it in the event emitted callback. The 'mining.' prefix is expected, so if you put 'hashes', it expects the command to be mining.hashes

stratum.Server.commands.hashes = function(id, any, params, you, want, to, pass, to, the, client){
    // this function is actually the "resolved" function, that sends data back to the client
    // it's reached by using deferred.resolve([...params...]); in the emitted callback

    // "this" is the current socket
    // "id" is the current RPC call id and is non-optional, must be always the first parameter

    // you should always return something like this:
    return this.stratumSend({
        error: null,
        result: [any, params, you, want], // your result
        id: id
    });
};

// the event `mining.hashes` will be fired on the callback

server.on('mining', function(req, deferred) {
    if (req.method === 'hashes'){
        deferred.resolve([any, params, you, want, to, pass, to, the, client]);
        // or reject
        deferred.reject([any, params, you, want, to, pass, to, the, client]);
    }
});

// mining.error event is emitted when something is wrong, mining related

server.on('mining.error', function(){

});

// the stratum.Server also holds defaults for coins daemons
console.log(stratum.Server.daemons); // a list of pre-configured daemons in stratum.Server.daemons

// You can inject them into the server later on, using stratum.Daemon

//instantiates a bitcoin stratum.Daemon and places inside the server
server.addDaemon(stratum.Server.daemons.bitcoin);

// you can instantiate using your own instance as well
server.addDaemon(stratum.Daemon.create({
    'name': 'MyExampleCoin',
    /*...*/
}));

RPCServer

Available through stratum.RPCServer.

Enables you to communicate from outside the Stratum module through an JSON RPC 2.0 interface. It's optional, and you don't need to enable it, you may communicate from inside out only.

It's mainly useful to receive notifications (wallet, block and alert), like the stratum-notify bin to receive json data from the outside, but you may extend the interface to accept any other commands that you deem necessary for your app.

It's advised to bind the RPCServer instance to either localhost or an internal IP range, and/or access through trusted proxies.

const rpc = new stratum.RPCServer({
    'mode': 'tcp', // can be 'tcp', 'http', 'both' (can handle TCP and HTTP/Websockets on one port)
    'port': 9999,
    'host': 'localhost', // bind to localhost
    'password': 'a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3' // SHA256 hash of the password, no plain text!
});

rpc.listen(); // listens on port 9999, binding to localhost

rpc.expose('mymethod', function(args, connection, callback){
    // if you want to pass an error, use the first callback parameter
    callback(error);
    // otherwise, pass the result through the second parameter
    callback(null, result);
});

// RPC calls like {"method":"mymethod","params":[1,"2"],"id":1}, the args parameter will receive only the [1,"2"]

Client

Available through stratum.Client

The client can connect to a stratum server and send and receive commands like if it was a miner.

The main reason for this part of the module is that you can setup a stratum proxy using it, to forward raw data (or even a command line call) to a stratum server.

You may also test your pool sending arbitrary test data to see if it's responding properly.

If your URL starts with 'stratum+tcp://', remove it!

var client = new stratum.Client();

client.on('mining.error', function(message){
});

client.on('mining', function(req, deferred){
    // this
});

client.connect(8080, 'localhost').then(function(socket){
    socket.stratumSubscribe('NodeMiner');
    socket.stratumAuthorize('user','pass');
    socket.stratumSubmit('worker', 'job_id', 'extranonce2', 'ntime', 'nonce');
    socket.stratumSend(data, true); //send a stratum command other than the previous ones
    socket.send(data); // send raw data through the socket
});

Daemon

Available through stratum.Daemon

Include or change the global configuration for daemons using the stratum.Server.daemons member. It's not set per instance, but rather globally.

The options path, args, notifyPath, notify are optional

stratum.Server.daemons['sillycoin'] = {
    'path': '/usr/bin/sillycoind', // optional
    'args': ['debug'], // optional
    'rpcserver': { // this whole block is optional, this is the stratum server RPC (not the daemon one))
        'port': 8888,
        'host': 'localhost',
        'password': 'rpcpassword',
        'notifyPath': './node_modules/.bin/stratum-notify', // optional
        'notify': ['block', 'wallet', 'alert'], // optional, will build walletnotify, blocknotify and alertnotify parameters
    }
    'name': 'SillyCoin',
    'user': 'rpcuser',
    'password': 'rpcpassword',
    'port': 0xDEAD,
    'host': 'localhost'
};

You can start issuing commands to the daemon BEFORE calling start(), usually when you already have it running. start() will attempt to spawn the process.

var daemon = new stratum.Daemon({
    'path': '/usr/bin/sillycoind',
    'name': 'SillyCoin',
    'user': 'rpcuser',
    'password': 'rpcpassword',
    'port': 0xDEAD,
    'host': 'localhost',
    'args': ['debug']
});

async function start() {
    daemon.start();

    try {
        const result = await daemon.call('getinfo', []);
        // daemon returned a result
        console.log(result.balance);
    } catch (result) {
        // daemon returned an error
        console.log(result); // usually "Command timed out" or "Unauthorized access"
    }
}

start();

Debugging

Export/set the environment variable DEBUG=stratum on your command line before executing your code, that you'll be able to see everything behind the hood inside this module on the command line.

You can additionally set DEBUG=stratum,jsonrpc to also see the RPC part in-depth (for stratum.Daemon and stratum.RPCServer)

Development

  • BTC: 16QDbqa6UMFtMCdDcJJ5N2bqryH4Q56BVU
  • BCH: 1E6gKfkyxsjr2rSbcHbnfsQumKxkGKwRYc
  • ETH: 0xfF9087E7112d3b7D7B5bDD6C9ffb0970ACC162E7
  • MIOTA: NNIH9VGEQFZAJIITBO9FEDSYUDYXHMAINGSKWIU9ADUHYYNTIYGJADZITOCVMWEFTKJGCNCJN9ZRFUZKCPSUOMDAKD
  • NXT: NXT-7TJT-8NS2-8QBS-5Y89X
  • BTG: GY2RWXUKYDmYDaroMmucgUdF7dLqaHDKWu
  • XEM: NBC772-Q3SL4X-AGVNMP-JAWGJE-U6BCSB-Q7WNAX-YU5V
  • DASH: XaqxcT3BDmSLGB4M6ozrET1qJPBA4RJpng
  • XRB: xrb_3fi16pk4gyz331r4531m7jywrfsgp3h31yoyfusac77esuamh65r5kwjz7dm

node-stratum's People

Contributors

envman avatar pocesar avatar thehobbit85 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-stratum's Issues

Contact request

Hello Paulo,

I took a look at your GitHub repos and it looks like you're trying to achieve the same thing as I do, building a node.js mining pool software :)
I'm somewhat nearly done with assembling/disassembling block hashes(yes, it works! but needs more work...).
So I was wondering if we can cooperate...
Ping me at [email protected] or at Skype 'erundook' account when you have time.

Thanks!

Unhandled rejection Error: -24,Unauthorized worker,

Unhandled rejection Error: -24,Unauthorized worker,
how do i fix it
im using everything default copy and pasted
except for this

client.connect(3333, 'localhost').then(function(socket){
    socket.stratumSubscribe('NodeMiner');
    socket.stratumAuthorize('user','password');
    socket.stratumSubmit('user', 'job_id', 'extranonce2', 'ntime', 'nonce');
    //socket.stratumSend(data, true); //send a stratum command other than the previous ones
    //socket.send(data); // send raw data through the socket
});

Stratum client - object constructor has no method 'on'

Hello,

I used this in my code

var stratum = require('stratum');
var Client = stratum.Client;
var client = Client.create();
client.on('mining.error', function(msg, socket) {
console.log(msg);
});

and when i launch i throw this error.

Any idea ?

Support WebSockets

Hello,
this is just an idea, as HTTP and TCP are both already supported in this project.
Afaik a WebSocket connection starts out as HTTP, a handshake occurs and the protocol is changed to TCP. One could probably use a library such as ws for that.

Enhancement: stratum.Client should support client.* calls to client from server

example from server to stratum.Client:

{"id": 1289739, "method": "client.get_version", "params": null}.

Currently the library just throws an exception here:

throw new Error("No suitable command was issued from the server");

see:
https://en.bitcoin.it/wiki/Stratum_mining_protocol#Methods_.28server_to_client.29

Would be nice to be able to handle and respond to various client.* requests from the server...

quick question

Can I use this to connect to https://minexmr.com/ or any other pool? Or am I restricted to only connect to the server from this repo? I think not but to make sure I ask here

Proxy ?

Hi, I wondered if you could add an example to show how to setup a proxy between a client like cgminer and any stratum server. Thanks.

question

can i set up an asic miner with this server???

Example?

The examples dont exactle show how to do anything. can you redo the examples?

Vardiff doesn't work due to a simple mistake

There is a simple mistake in pool.js that causes the varDiff options to not be passed to the varDiff constructor. The fix is to replace options.ports[port] by options.ports[port].varDiff:

function SetupVarDiff(){
  Object.keys(options.ports).forEach(function(port) {
    _this.setVarDiff(port, new varDiff(port, options.ports[port].varDiff));
  });
}

Example client code is repeatedly asking for authorization

I wanted to give the client a test with my slushpool account. Everything is connecting fine, but there seems to be some kind of loop in which I'm repeatedly asking for authorization. I've included the output below. Is this intended? I didn't find anything mentioned about this behavior in the documentation so I want to verify its not something I'm doing wrong.

localhost:node-stratum davea$ ts-node examples/client.ts
Connected! lets ask for subscribe
Sent!
Mining data: result = { error: null,
id: 1,
result: [ [ [Array], [Array] ], '0765080016f43c', 4 ] }
Asking for authorization
Mining data: broadcast = { params: [ 8192 ], id: null, method: 'set_difficulty' }
Mining data: broadcast = { params:
[ '7a5e',
'244089fad599c594d34cbf2113f8f85738a3f477002cced20000000000000000',
'01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff440340d107fabe6d6d018a23a9d3938f68282ee4266d7f2b47369eda8eba57e1d5ac46241c3c78277b0100000000000000',
'5e7a2f736c7573682f0000000003c75eff4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3af71dadaea776bcbe81814b88154015a7d4fa8c62846b23445be1be0204004b740000000000000000266a24aa21a9ed89d0281c8c7080c56a09cabe990d70343de7961cbfb7b53dbf260749f86ec47900000000',
[ 'b942a59aaee78830473bb3e59de854cf01d6192f5ddcf144f3993fe294af986b',
'60bea12566a1202e31072e59d8505270604e7e6d765c525d498fc40a9d40d7c6',
'98f0e59c54bf5f3ec4098ee90e603a0cf954d80e4c27d1c42145b72885fe61ce',
'086e0121b5011cf0827a63758c27cca51e642a9d71179560828ec754606f7d86',
'8ea37b32a351349870bb5a7eac64b4565bd2a0d1cf85799968d8ac9eb160e60b',
'bbd5d0aa9a80ebdc57be4f819f8706c060df6479698dff30076fcaf7f44d0883',
'179ff592ed9b2f8ae44c9342407a295654ec83f653d873b79a04a2e65250e142',
'1d3247127cd95b71f85e20491c2bad15a28269fd6202ad95fc8e956675db1d68',
'ed6b2fe074e7187de8d61fe75c42b943deade685a1e4bd63515b3be4e5e78610' ],
'20000000',
'175589a3',
'5a9f05bc',
true ],
id: null,
method: 'notify' }
Mining data: result = { error: null,
id: 1,
result: [ [ [Array], [Array] ], '0765080016f43c', 4 ] }
Asking for authorization
Mining data: broadcast = { params: [ 8192 ], id: null, method: 'set_difficulty' }
Mining data: broadcast = { params:
[ '7a5e',
'244089fad599c594d34cbf2113f8f85738a3f477002cced20000000000000000',
'01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff440340d107fabe6d6d018a23a9d3938f68282ee4266d7f2b47369eda8eba57e1d5ac46241c3c78277b0100000000000000',
'5e7a2f736c7573682f0000000003c75eff4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3af71dadaea776bcbe81814b88154015a7d4fa8c62846b23445be1be0204004b740000000000000000266a24aa21a9ed89d0281c8c7080c56a09cabe990d70343de7961cbfb7b53dbf260749f86ec47900000000',
[ 'b942a59aaee78830473bb3e59de854cf01d6192f5ddcf144f3993fe294af986b',
'60bea12566a1202e31072e59d8505270604e7e6d765c525d498fc40a9d40d7c6',
'98f0e59c54bf5f3ec4098ee90e603a0cf954d80e4c27d1c42145b72885fe61ce',
'086e0121b5011cf0827a63758c27cca51e642a9d71179560828ec754606f7d86',
'8ea37b32a351349870bb5a7eac64b4565bd2a0d1cf85799968d8ac9eb160e60b',
'bbd5d0aa9a80ebdc57be4f819f8706c060df6479698dff30076fcaf7f44d0883',
'179ff592ed9b2f8ae44c9342407a295654ec83f653d873b79a04a2e65250e142',
'1d3247127cd95b71f85e20491c2bad15a28269fd6202ad95fc8e956675db1d68',
'ed6b2fe074e7187de8d61fe75c42b943deade685a1e4bd63515b3be4e5e78610' ],
'20000000',
'175589a3',
'5a9f05bc',
true ],
id: null,
method: 'notify' }
Mining data: result = { error: null,
id: 1,
result: [ [ [Array], [Array] ], '0765080016f43c', 4 ] }
Asking for authorization
Mining data: broadcast = { params: [ 8192 ], id: null, method: 'set_difficulty' }
Mining data: broadcast = { params:
[ '7a5e',
'244089fad599c594d34cbf2113f8f85738a3f477002cced20000000000000000',
'01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff440340d107fabe6d6d018a23a9d3938f68282ee4266d7f2b47369eda8eba57e1d5ac46241c3c78277b0100000000000000',
'5e7a2f736c7573682f0000000003c75eff4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac00000000000000002c6a4c2952534b424c4f434b3af71dadaea776bcbe81814b88154015a7d4fa8c62846b23445be1be0204004b740000000000000000266a24aa21a9ed89d0281c8c7080c56a09cabe990d70343de7961cbfb7b53dbf260749f86ec47900000000',
...

upload new version to npm

can you please publish the new version to npm.
I want to go back and set the dependency to npm and not git ;)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.