{"id":17458115,"url":"https://github.com/pocesar/node-stratum","last_synced_at":"2025-10-15T21:32:08.486Z","repository":{"id":9578010,"uuid":"11493026","full_name":"pocesar/node-stratum","owner":"pocesar","description":"Stratum protocol server and client for Node.js","archived":false,"fork":false,"pushed_at":"2019-07-08T06:30:55.000Z","size":229,"stargazers_count":164,"open_issues_count":9,"forks_count":68,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-04-02T09:08:21.788Z","etag":null,"topics":["coin","cryptocurrency","daemon","javascript","mining","node-stratum","promise","rpc","rpc-server","stratum","stratum-protocol","stratum-proxy","stratum-server"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pocesar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-18T03:03:02.000Z","updated_at":"2025-03-20T16:02:00.000Z","dependencies_parsed_at":"2022-09-07T07:51:02.095Z","dependency_job_id":null,"html_url":"https://github.com/pocesar/node-stratum","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocesar%2Fnode-stratum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocesar%2Fnode-stratum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocesar%2Fnode-stratum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocesar%2Fnode-stratum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pocesar","download_url":"https://codeload.github.com/pocesar/node-stratum/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247883237,"owners_count":21012233,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coin","cryptocurrency","daemon","javascript","mining","node-stratum","promise","rpc","rpc-server","stratum","stratum-protocol","stratum-proxy","stratum-server"],"created_at":"2024-10-18T03:54:42.191Z","updated_at":"2025-10-15T21:32:08.392Z","avatar_url":"https://github.com/pocesar.png","language":"TypeScript","readme":"[![Build Status](https://travis-ci.org/pocesar/node-stratum.svg?branch=master)](https://travis-ci.org/pocesar/node-stratum)\r\n[![Coverage Status](https://coveralls.io/repos/pocesar/node-stratum/badge.png)](https://coveralls.io/r/pocesar/node-stratum)\r\n[![Dependency Status](https://gemnasium.com/badges/github.com/pocesar/node-stratum.svg)](https://gemnasium.com/github.com/pocesar/node-stratum)\r\n\r\n[![NPM](https://nodei.co/npm/stratum.png?downloads=true)](https://nodei.co/npm/stratum/)\r\n\r\n# Node.js Stratum Server / Client / RPC Daemon\r\n\r\nExposes 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\r\n\r\nThis 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).\r\n\r\n## Highlights\r\n\r\n* Simple but powerful API for managing both server and client\r\n* Build-in support for spawn coins daemons (`bitcoind`, `litecoind`, etc) process and accept RPC calls\r\n* Easy for you to add your own procedures do the RPC server (using `expose`)\r\n* 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)\r\n* All classes based on `EventEmitter` by default (through the `Base` class)\r\n* The client part make it easy, along with an RPC server, to setup your own farming pool for coins\r\n* You can create a proxy from it using the `Client` interface, mix up Stratum with your own RPC definition and commands\r\n\r\n## Install\r\n\r\n```bash\r\nnpm install stratum\r\n```\r\n\r\nNotice that you may install this globally using `-g`, `stratum-notify` will be available system wide\r\n\r\n## Stratum notify\r\n\r\n##### if you want to call it manually for testing purposes\r\n\r\n```bash\r\nnode node_modules/.bin/stratum-notify --host localhost --port 1337 --password willbebase64encoded --type block --data \"jsondata\"\r\n```\r\n\r\nThis command is called automatically if you set the `coind` options, they are forked when the server is started.\r\n\r\n## Usage\r\n\r\n```js\r\nvar Server = require('stratum').Server;\r\n\r\n// these settings can be changed using Server.defaults as well, for every new server up\r\nvar server = new Server({\r\n  /**\r\n   * RPC to listen interface for this server\r\n   */\r\n  rpc     : {\r\n    /**\r\n     * Bind to address\r\n     *\r\n     * @type {String}\r\n     */\r\n    host: 'localhost',\r\n    /**\r\n     * RPC port\r\n     *\r\n     * @type {Number}\r\n     */\r\n    port: 1337,\r\n    /**\r\n     * RPC password, this needs to be a SHA256 hash, defaults to 'password'\r\n     * To create a hash out of your password, launch node.js and write\r\n     *\r\n     * require('crypto').createHash('sha256').update('password').digest('hex');\r\n     *\r\n     * @type {String}\r\n     */\r\n    password: '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8',\r\n    /**\r\n     * Mode to listen. By default listen only on TCP, but you may use 'http' or 'both' (deal\r\n     * with HTTP and TCP at same time)\r\n     */\r\n    mode: 'tcp'\r\n  },\r\n  /**\r\n   * The server settings itself\r\n   */\r\n  settings: {\r\n    /**\r\n     * Address to set the X-Stratum header if someone connects using HTTP\r\n     * @type {String}\r\n     */\r\n    hostname: 'localhost',\r\n    /**\r\n     * Max server lag before considering the server \"too busy\" and drop new connections\r\n     * @type {Number}\r\n     */\r\n    toobusy : 70,\r\n    /**\r\n     * Bind to address, use 0.0.0.0 for external access\r\n     * @type {string}\r\n     */\r\n    host    : 'localhost',\r\n    /**\r\n     * Port for the stratum TCP server to listen on\r\n     * @type {Number}\r\n     */\r\n    port    : 3333\r\n  }\r\n});\r\n\r\nserver.on('mining', function(req, deferred){\r\n    switch (req.method){\r\n        case 'subscribe':\r\n            // req.params[0] -\u003e if filled, it's the User Agent, like CGMiner/CPUMiner sends\r\n            // Just resolve the deferred, the promise will be resolved and the data sent to the connected client\r\n            deferred.resolve([subscription, extranonce1, extranonce2_size]);\r\n            break;\r\n    }\r\n});\r\n\r\nserver.listen();\r\n```\r\n\r\nYou can connect to Stratum servers as well:\r\n\r\n```js\r\nvar Client = require('stratum').Client;\r\n\r\nclient = new Client();\r\n\r\nclient.connect({\r\n    host: 'localhost',\r\n    port: 3333\r\n}).then(function(){\r\n    return ...;\r\n}).then(function(value){\r\n    if (value){\r\n        //etc\r\n    }\r\n});\r\n\r\n```\r\n\r\n## Examples\r\n\r\nCheck the `examples` folder, each part (client and server) is completely explained, and how to proceed on each possible case.\r\n\r\n## Documentation\r\n\r\nThe following documentation expects that:\r\n\r\n```js\r\nvar stratum = require('stratum');\r\n```\r\n\r\n### Base\r\n\r\nAvailable through `stratum.Base`\r\n\r\nAll the classes inherit from the base class, that inherits from `EventEmitter3`, and got an additional method:\r\n\r\n#### debug(msg)\r\n\r\nShow debug messages for the class only if `DEBUG=stratum` environment variable is set\r\n\r\n```js\r\nstratum.Base.debug('oops');\r\n```\r\n\r\n### Server\r\n\r\nAvailable through `stratum.Server`\r\n\r\nYou can write your own defaults that applies to all new server instances through `stratum.Server.defaults`\r\n\r\n```js\r\nstratum.Server.defaults.settings.toobusy = 50;\r\n```\r\n\r\nYou 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.\r\nThe 'mining.' prefix is expected, so if you put 'hashes', it expects the command to be `mining.hashes`\r\n\r\n```js\r\nstratum.Server.commands.hashes = function(id, any, params, you, want, to, pass, to, the, client){\r\n    // this function is actually the \"resolved\" function, that sends data back to the client\r\n    // it's reached by using deferred.resolve([...params...]); in the emitted callback\r\n\r\n    // \"this\" is the current socket\r\n    // \"id\" is the current RPC call id and is non-optional, must be always the first parameter\r\n\r\n    // you should always return something like this:\r\n    return this.stratumSend({\r\n        error: null,\r\n        result: [any, params, you, want], // your result\r\n        id: id\r\n    });\r\n};\r\n\r\n// the event `mining.hashes` will be fired on the callback\r\n\r\nserver.on('mining', function(req, deferred) {\r\n    if (req.method === 'hashes'){\r\n        deferred.resolve([any, params, you, want, to, pass, to, the, client]);\r\n        // or reject\r\n        deferred.reject([any, params, you, want, to, pass, to, the, client]);\r\n    }\r\n});\r\n\r\n// mining.error event is emitted when something is wrong, mining related\r\n\r\nserver.on('mining.error', function(){\r\n\r\n});\r\n\r\n// the stratum.Server also holds defaults for coins daemons\r\nconsole.log(stratum.Server.daemons); // a list of pre-configured daemons in stratum.Server.daemons\r\n\r\n// You can inject them into the server later on, using stratum.Daemon\r\n\r\n//instantiates a bitcoin stratum.Daemon and places inside the server\r\nserver.addDaemon(stratum.Server.daemons.bitcoin);\r\n\r\n// you can instantiate using your own instance as well\r\nserver.addDaemon(stratum.Daemon.create({\r\n    'name': 'MyExampleCoin',\r\n    /*...*/\r\n}));\r\n```\r\n\r\n### RPCServer\r\n\r\nAvailable through `stratum.RPCServer`.\r\n\r\nEnables 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.\r\n\r\nIt'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.\r\n\r\nIt's advised to bind the `RPCServer` instance to either `localhost` or an internal IP range, and/or access through trusted proxies.\r\n\r\n```js\r\nconst rpc = new stratum.RPCServer({\r\n    'mode': 'tcp', // can be 'tcp', 'http', 'both' (can handle TCP and HTTP/Websockets on one port)\r\n    'port': 9999,\r\n    'host': 'localhost', // bind to localhost\r\n    'password': 'a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3' // SHA256 hash of the password, no plain text!\r\n});\r\n\r\nrpc.listen(); // listens on port 9999, binding to localhost\r\n\r\nrpc.expose('mymethod', function(args, connection, callback){\r\n    // if you want to pass an error, use the first callback parameter\r\n    callback(error);\r\n    // otherwise, pass the result through the second parameter\r\n    callback(null, result);\r\n});\r\n\r\n// RPC calls like {\"method\":\"mymethod\",\"params\":[1,\"2\"],\"id\":1}, the args parameter will receive only the [1,\"2\"]\r\n```\r\n\r\n### Client\r\n\r\nAvailable through `stratum.Client`\r\n\r\nThe client can connect to a stratum server and send and receive commands like if it was a miner.\r\n\r\nThe 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.\r\n\r\nYou may also test your pool sending arbitrary test data to see if it's responding properly.\r\n\r\nIf your URL starts with 'stratum+tcp://', remove it!\r\n\r\n```js\r\nvar client = new stratum.Client();\r\n\r\nclient.on('mining.error', function(message){\r\n});\r\n\r\nclient.on('mining', function(req, deferred){\r\n    // this\r\n});\r\n\r\nclient.connect(8080, 'localhost').then(function(socket){\r\n    socket.stratumSubscribe('NodeMiner');\r\n    socket.stratumAuthorize('user','pass');\r\n    socket.stratumSubmit('worker', 'job_id', 'extranonce2', 'ntime', 'nonce');\r\n    socket.stratumSend(data, true); //send a stratum command other than the previous ones\r\n    socket.send(data); // send raw data through the socket\r\n});\r\n```\r\n\r\n### Daemon\r\n\r\nAvailable through `stratum.Daemon`\r\n\r\nInclude or change the global configuration for daemons using the `stratum.Server.daemons` member. It's not set per instance, but rather globally.\r\n\r\nThe options `path`, `args`, `notifyPath`, `notify` are optional\r\n\r\n```js\r\nstratum.Server.daemons['sillycoin'] = {\r\n    'path': '/usr/bin/sillycoind', // optional\r\n    'args': ['debug'], // optional\r\n    'rpcserver': { // this whole block is optional, this is the stratum server RPC (not the daemon one))\r\n        'port': 8888,\r\n        'host': 'localhost',\r\n        'password': 'rpcpassword',\r\n        'notifyPath': './node_modules/.bin/stratum-notify', // optional\r\n        'notify': ['block', 'wallet', 'alert'], // optional, will build walletnotify, blocknotify and alertnotify parameters\r\n    }\r\n    'name': 'SillyCoin',\r\n    'user': 'rpcuser',\r\n    'password': 'rpcpassword',\r\n    'port': 0xDEAD,\r\n    'host': 'localhost'\r\n};\r\n```\r\n\r\nYou can start issuing commands to the daemon BEFORE calling `start()`, usually when you already have it running. `start()` will attempt to spawn the process.\r\n\r\n```js\r\nvar daemon = new stratum.Daemon({\r\n    'path': '/usr/bin/sillycoind',\r\n    'name': 'SillyCoin',\r\n    'user': 'rpcuser',\r\n    'password': 'rpcpassword',\r\n    'port': 0xDEAD,\r\n    'host': 'localhost',\r\n    'args': ['debug']\r\n});\r\n\r\nasync function start() {\r\n    daemon.start();\r\n\r\n    try {\r\n        const result = await daemon.call('getinfo', []);\r\n        // daemon returned a result\r\n        console.log(result.balance);\r\n    } catch (result) {\r\n        // daemon returned an error\r\n        console.log(result); // usually \"Command timed out\" or \"Unauthorized access\"\r\n    }\r\n}\r\n\r\nstart();\r\n```\r\n\r\n## Debugging\r\n\r\nExport/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.\r\n\r\nYou can additionally set `DEBUG=stratum,jsonrpc` to also see the RPC part in-depth (for `stratum.Daemon` and `stratum.RPCServer`)\r\n\r\n# Development\r\n\r\n* BTC: `16QDbqa6UMFtMCdDcJJ5N2bqryH4Q56BVU`\r\n* BCH: `1E6gKfkyxsjr2rSbcHbnfsQumKxkGKwRYc`\r\n* ETH: `0xfF9087E7112d3b7D7B5bDD6C9ffb0970ACC162E7`\r\n* MIOTA: `NNIH9VGEQFZAJIITBO9FEDSYUDYXHMAINGSKWIU9ADUHYYNTIYGJADZITOCVMWEFTKJGCNCJN9ZRFUZKCPSUOMDAKD`\r\n* NXT: `NXT-7TJT-8NS2-8QBS-5Y89X`\r\n* BTG: `GY2RWXUKYDmYDaroMmucgUdF7dLqaHDKWu`\r\n* XEM: `NBC772-Q3SL4X-AGVNMP-JAWGJE-U6BCSB-Q7WNAX-YU5V`\r\n* DASH: `XaqxcT3BDmSLGB4M6ozrET1qJPBA4RJpng`\r\n* XRB: `xrb_3fi16pk4gyz331r4531m7jywrfsgp3h31yoyfusac77esuamh65r5kwjz7dm`\r\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpocesar%2Fnode-stratum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpocesar%2Fnode-stratum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpocesar%2Fnode-stratum/lists"}