├── .gitignore ├── generate_key.gif ├── javascript ├── index.js ├── README.md ├── package.json ├── config.js ├── exchange.js ├── hashpower.js ├── api.js ├── api.ts └── package-lock.json ├── c# └── connect │ ├── connect │ ├── App.config │ ├── packages.config │ ├── Connect.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── connect.csproj │ ├── Exch.cs │ ├── Hpo.cs │ └── Api.cs │ └── connect.sln ├── bash ├── README.md └── run.sh ├── README.md ├── python ├── README.md ├── test_bot.py └── nicehash.py └── java ├── pom.xml └── src └── main └── java ├── Hpo.java └── com └── nicehash └── connect └── Api.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | javascript/node_modules 3 | -------------------------------------------------------------------------------- /generate_key.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nicehash/rest-clients-demo/HEAD/generate_key.gif -------------------------------------------------------------------------------- /javascript/index.js: -------------------------------------------------------------------------------- 1 | require = require("esm")(module/*, options*/); 2 | 3 | // examples 4 | //require("./hashpower"); 5 | //require("./exchange"); 6 | -------------------------------------------------------------------------------- /c#/connect/connect/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /javascript/README.md: -------------------------------------------------------------------------------- 1 | ### NODE API 2 | 3 | - Install dependencies 4 | 5 | npm install 6 | 7 | - Enter your API key settings into config.js 8 | - Uncomment example you want to run in index.js 9 | - Run with 10 | 11 | node index.js 12 | -------------------------------------------------------------------------------- /c#/connect/connect/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /bash/README.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Get python client 4 | 5 | wget https://raw.githubusercontent.com/nicehash/rest-clients-demo/master/python/nicehash.py 6 | 7 | Install dependencies 8 | 9 | pip install requests 10 | 11 | Enter API key/secret/org in to the bash script 12 | 13 | ./run.sh 14 | 15 | For more options see 16 | 17 | python nicehash.py -h 18 | -------------------------------------------------------------------------------- /bash/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Configuration 3 | ORG="---" 4 | KEY="---" 5 | SEC="---" 6 | #API="https://api2.nicehash.com" #prod env 7 | API="https://api-test.nicehash.com" # test env 8 | 9 | # Command 10 | NHCLIENT="python nicehash.py -b $API -o $ORG -k $KEY -s $SEC" 11 | 12 | # Run method 13 | eval "$NHCLIENT -m GET -p '/main/api/v2/accounting/accounts2'"; # -b '{json}' 14 | -------------------------------------------------------------------------------- /javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-app-node", 3 | "version": "0.0.1", 4 | "description": "NiceHash Example App", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "NiceHash", 10 | "license": "ISC", 11 | "dependencies": { 12 | "crypto-js": "^3.1.9-1", 13 | "esm": "^3.2.25", 14 | "qs": "^6.7.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /javascript/config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | apiHost: 'https://api-test.nicehash.com', //use https://api2.nicehash.com for production 3 | apiKey: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', //get it here: https://test.nicehash.com/my/settings/keys or https://www.nicehash.com/my/settings/keys 4 | apiSecret: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 5 | orgId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 6 | } 7 | -------------------------------------------------------------------------------- /c#/connect/connect.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29021.104 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "connect", "connect\connect.csproj", "{25EF6083-E791-4BAD-A0C0-462A1A1220E3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {25EF6083-E791-4BAD-A0C0-462A1A1220E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {25EF6083-E791-4BAD-A0C0-462A1A1220E3}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {25EF6083-E791-4BAD-A0C0-462A1A1220E3}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {25EF6083-E791-4BAD-A0C0-462A1A1220E3}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {A8EDF606-C147-427F-B08D-FECCD44EC071} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /c#/connect/connect/Connect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace connect 5 | { 6 | class Connect 7 | { 8 | static void Main(string[] args) 9 | { 10 | Console.WriteLine("running HashPowerOrder"); 11 | new Hpo(); 12 | Console.WriteLine("\n\nrunning Exchange"); 13 | new Exch(); 14 | Console.ReadLine(); 15 | } 16 | } 17 | 18 | public class ServerTime 19 | { 20 | public string serverTime { get; set; } 21 | } 22 | public class Currencies 23 | { 24 | public List currencies { get; set; } 25 | } 26 | public class Currency 27 | { 28 | public String currency { get; set; } 29 | public double available { get; set; } 30 | } 31 | public class Symbols 32 | { 33 | public List symbols { get; set; } 34 | } 35 | public class Symbol 36 | { 37 | public String baseAsset { get; set; } 38 | } 39 | public class Pool 40 | { 41 | public string id { get; set; } 42 | } 43 | public class Order 44 | { 45 | public string id { get; set; } 46 | } 47 | public class OrderBooks 48 | { 49 | public List sell { get; set; } 50 | public List buy { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rest-clients-demo 2 | 3 | ### Examples by language 4 | 5 | - [python](https://github.com/nicehash/rest-clients-demo/blob/master/python/nicehash.py) 6 | - [bash](https://github.com/nicehash/rest-clients-demo/tree/master/bash) 7 | - [c#](https://github.com/nicehash/rest-clients-demo/blob/master/c%23/connect/connect/Hpo.cs) 8 | - [java](https://github.com/nicehash/rest-clients-demo/blob/master/java/src/main/java/Hpo.java) 9 | - [javascript](https://github.com/nicehash/rest-clients-demo/blob/master/javascript/hashpower.js) 10 | - [php](https://github.com/nicehash/rest-clients-demo/wiki/php-demo) 11 | 12 | ### TEST environment 13 | 14 | Generate Api key and Secret for test platform on: 15 | 16 | https://test.nicehash.com (User / Settings / API Keys) 17 | Organization ID is displayed just above "+ Create new API key" button. 18 | 19 | Use https://api-test.nicehash.com for API domain. 20 | 21 | The entire platform runs on testnet. This means that you don’t have to use your own funds to test the platform. This is the opportunity to familiarize yourself with the new system, place hash-power orders and try trading without spending any real money. 22 | 23 | ![](https://raw.githubusercontent.com/nicehash/rest-clients-demo/master/generate_key.gif) 24 | 25 | ### PRODUCTION environment 26 | 27 | To use production just generate key the same way on https://www.nicehash.com and use https://api2.nicehash.com for API domain. 28 | 29 | ### API docs 30 | Can be found here: https://docs.nicehash.com/ 31 | -------------------------------------------------------------------------------- /c#/connect/connect/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("connect")] 9 | [assembly: AssemblyDescription("NH new platform API demo")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("NiceHash")] 12 | [assembly: AssemblyProduct("connect")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("25ef6083-e791-4bad-a0c0-462a1a1220e3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /javascript/exchange.js: -------------------------------------------------------------------------------- 1 | import config from './config' 2 | import Api from './api' 3 | 4 | var log = function () { 5 | return console.log(...arguments); 6 | } 7 | 8 | var market, orderBook ,order; 9 | 10 | const api = new Api(config); 11 | 12 | // get server time - required 13 | api.getTime() 14 | 15 | .then(() => { 16 | log('server time', api.time) 17 | log('--') 18 | }) 19 | 20 | // get exchange settings 21 | .then(() => api.get('/exchange/api/v2/info/status')) 22 | .then(res => { 23 | market = res.symbols[0]; 24 | log('exchange markets', res); 25 | log('--') 26 | }) 27 | 28 | // get balance 29 | .then(() => api.get('/main/api/v2/accounting/accounts2')) 30 | .then(res => { 31 | log('accounts', res); 32 | log('--') 33 | }) 34 | 35 | // get orderbook 36 | .then(() => api.get('/exchange/api/v2/orderbook?aa=1',{query:{market: market.symbol}})) 37 | .then(res => { 38 | orderBook = res; 39 | log('order book for '+market.symbol, res); 40 | log('--') 41 | }) 42 | 43 | // buy with limit order 44 | .then(() => { 45 | var query = { 46 | market: market.symbol, 47 | side: 'buy', 48 | type: 'limit', 49 | quantity: market.secMinAmount * 10, 50 | price: orderBook.sell[0][0], 51 | }; 52 | 53 | return api.post('/exchange/api/v2/order',{query}) 54 | }) 55 | .then(res => { 56 | order = res; 57 | log('new order', res); 58 | log('--') 59 | }) 60 | 61 | // cancel order 62 | .then(() => api.delete('/exchange/api/v2/order',{query:{market: market.symbol, orderId: order. orderId}})) 63 | .then(res => { 64 | orderBook = res; 65 | log('canceled order', res); 66 | log('--') 67 | }) 68 | 69 | .catch(err => { 70 | if(err && err.response) log(err.response.request.method,err.response.request.uri.href); 71 | log('ERROR', err.error || err); 72 | }) 73 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Nicehash python library and command line rest api 2 | 3 | Dependacy 4 | * requests 5 | 6 | To install dependencies run following line your favorite shell console 7 | 8 | pip install requests 9 | 10 | 11 | ## Required data and where to get it 12 | Following data is needed: 13 | * api base url: 14 | * https://api2.nicehash.com - Production environment 15 | * https://api-test.nicehash.com - Test environment 16 | 17 | The documentation how to get organisation id, api key and api key secret is here: 18 | https://github.com/nicehash/rest-clients-demo 19 | 20 | ## Library usage 21 | Nicehash library is contained in file `nicehash.py`. Api is divided in two part: public and private. 22 | 23 | Code snipplet for public api 24 | 25 | import nicehash 26 | 27 | host = 'https://api2.nicehash.com' 28 | 29 | public_api = nicehash.public_api(host) 30 | 31 | buy_info = public_api.buy_info() 32 | print(buy_info) 33 | 34 | 35 | Code snipplet for private api 36 | 37 | import nicehash 38 | 39 | host = 'https://api2.nicehash.com' 40 | organisation_id = 'Enter your organisation id' 41 | key = 'Enter your api key' 42 | secret = 'Enter your secret for api key' 43 | 44 | private_api = nicehash.private_api(host, organisation_id, key, secret) 45 | 46 | my_accounts = private_api.get_accounts() 47 | print(my_accounts) 48 | 49 | 50 | Usage of other api calls are shown in `test_bot.py` 51 | 52 | 53 | ## Command line usage 54 | `nicehash.py` can be used as commad line tools 55 | 56 | To get help run: 57 | 58 | python nicehash.py -h 59 | 60 | Result: 61 | 62 | Usage: nicehash.py [options] 63 | 64 | Options: 65 | -h, --help show this help message and exit 66 | -b BASE, --base_url=BASE 67 | Api base url 68 | -o ORG, --organization_id=ORG 69 | Organization id 70 | -k KEY, --key=KEY Api key 71 | -s SECRET, --secret=SECRET 72 | Secret for api key 73 | -m METHOD, --method=METHOD 74 | Method for request 75 | -p PATH, --path=PATH Path for request 76 | -q PARAMS, --params=PARAMS 77 | Parameters for request 78 | -d BODY, --body=BODY Body for request 79 | 80 | 81 | Example usage: 82 | 83 | python nicehash.py -b https://api2.nicehash.com -o ca5622bd-bc32-451b-90a4-e9ae1088bade -k 85512ceb-4f37-426e-9fb4-929af9134ed1 -s 11260065-37f9-4875-bbdd-52a59ce7775de2c0596c-5c87-4739-bb60-b3f547612aed -m GET -p /main/api/v2/accounting/accounts/ 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /javascript/hashpower.js: -------------------------------------------------------------------------------- 1 | import config from './config' 2 | import Api from './api' 3 | 4 | var log = function () { 5 | return console.log(...arguments); 6 | } 7 | 8 | var algo, pool, order; 9 | 10 | const api = new Api(config); 11 | 12 | // get server time - required 13 | api.getTime() 14 | .then(() => { 15 | log('server time', api.time) 16 | log('--') 17 | }) 18 | 19 | // get algo settings 20 | .then(() => api.get('/main/api/v2/mining/algorithms')) 21 | .then(res => { 22 | algo = res.miningAlgorithms[0]; // SCRYPT 23 | log('algorithms', res); 24 | log('--') 25 | }) 26 | 27 | // get balance 28 | // .then(() => api.get('/main/api/v2/accounting/accounts2')) 29 | // .then(res => { 30 | // log('accounts', res); 31 | // }) 32 | 33 | //// create new pool 34 | .then(() => { 35 | var body = { 36 | algorithm: 'SCRYPT', 37 | name: 'my pool', 38 | username: 'pool_username', 39 | password: 'x', 40 | stratumHostname: 'pool.host.name', 41 | stratumPort: '3456', 42 | }; 43 | 44 | return api.post('/main/api/v2/pool',{body}) 45 | }) 46 | .then(res => { 47 | pool = res; 48 | log('new pool', res); 49 | log('--') 50 | }) 51 | 52 | // create new order 53 | .then(() => { 54 | var body = { 55 | algorithm: 'SCRYPT', 56 | amount: "0.005", 57 | displayMarketFactor: algo.displayMarketFactor, 58 | limit: algo.minSpeedLimit, 59 | market: 'EU', // or USA 60 | marketFactor: algo.marketFactor, 61 | poolId: pool.id, 62 | price: '0.0010', 63 | type: 'STANDARD', 64 | }; 65 | 66 | return api.post('/main/api/v2/hashpower/order',{body}) 67 | }) 68 | .then(res => { 69 | order = res; 70 | log('new order', res); 71 | log('--') 72 | }) 73 | 74 | // update order price or limit 75 | .then(() => { 76 | var body = { 77 | displayMarketFactor: algo.displayMarketFactor, 78 | marketFactor: algo.marketFactor, 79 | limit: '0.11', 80 | price: '0.00123', 81 | }; 82 | 83 | return api.post(`/main/api/v2/hashpower/order/${order.id}/updatePriceAndLimit`,{body}) 84 | }) 85 | .then(res => { 86 | log('updated order', res); 87 | log('--') 88 | }) 89 | 90 | // cancel order 91 | .then(() => api.delete(`/main/api/v2/hashpower/order/${order.id}`)) 92 | .then(res => { 93 | log('deleted order', res); 94 | log('--') 95 | }) 96 | 97 | // delete pool 98 | .then(() => api.delete(`/main/api/v2/pool/${pool.id}`)) 99 | .then(res => { 100 | log('deleted pool', res); 101 | log('--') 102 | }) 103 | 104 | .catch(err => { 105 | if(err && err.response) log(err.response.request.method,err.response.request.uri.href); 106 | log('ERROR', err.error || err); 107 | }) 108 | -------------------------------------------------------------------------------- /java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.nicehash.connect 8 | connect 9 | 1.0-SNAPSHOT 10 | 11 | connect 12 | 13 | http://www.example.com 14 | 15 | 16 | UTF-8 17 | 1.7 18 | 1.7 19 | 20 | 21 | 22 | 23 | org.apache.httpcomponents 24 | httpclient 25 | 4.5.13 26 | 27 | 28 | com.google.code.gson 29 | gson 30 | 2.8.5 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | maven-clean-plugin 40 | 3.1.0 41 | 42 | 43 | 44 | maven-resources-plugin 45 | 3.0.2 46 | 47 | 48 | maven-compiler-plugin 49 | 3.8.0 50 | 51 | 52 | maven-surefire-plugin 53 | 2.22.1 54 | 55 | 56 | maven-jar-plugin 57 | 3.0.2 58 | 59 | 60 | maven-install-plugin 61 | 2.5.2 62 | 63 | 64 | maven-deploy-plugin 65 | 2.8.2 66 | 67 | 68 | 69 | maven-site-plugin 70 | 3.7.1 71 | 72 | 73 | maven-project-info-reports-plugin 74 | 3.0.0 75 | 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-compiler-plugin 82 | 83 | 8 84 | 8 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /javascript/api.js: -------------------------------------------------------------------------------- 1 | import CryptoJS from "crypto-js"; 2 | import qs from 'qs' 3 | 4 | function createNonce() { 5 | var s = '', length = 32; 6 | do { 7 | s += Math.random().toString(36).substr(2); 8 | } while (s.length < length); 9 | s = s.substr(0, length); 10 | return s; 11 | } 12 | 13 | const getAuthHeader = (apiKey, apiSecret, time, nonce, organizationId = '', request = {}) => { 14 | const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, apiSecret); 15 | 16 | hmac.update(apiKey); 17 | hmac.update("\0"); 18 | hmac.update(time); 19 | hmac.update("\0"); 20 | hmac.update(nonce); 21 | hmac.update("\0"); 22 | hmac.update("\0"); 23 | if (organizationId) hmac.update(organizationId); 24 | hmac.update("\0"); 25 | hmac.update("\0"); 26 | hmac.update(request.method); 27 | hmac.update("\0"); 28 | hmac.update(request.path); 29 | hmac.update("\0"); 30 | if (request.query) hmac.update(typeof request.query == 'object' ? qs.stringify(request.query) : request.query); 31 | if (request.body) { 32 | hmac.update("\0"); 33 | hmac.update(typeof request.body == 'object' ? JSON.stringify(request.body) : request.body); 34 | } 35 | 36 | return apiKey + ':' + hmac.finalize().toString(CryptoJS.enc.Hex); 37 | }; 38 | 39 | 40 | class Api { 41 | 42 | constructor({locale, apiHost, apiKey, apiSecret, orgId}) { 43 | this.locale = locale || 'en'; 44 | this.host = apiHost; 45 | this.key = apiKey; 46 | this.secret = apiSecret; 47 | this.org = orgId; 48 | this.localTimeDiff = null; 49 | } 50 | 51 | getTime() { 52 | return fetch(this.host + '/api/v2/time',{}) 53 | .then(res => res.json()) 54 | .then(res => { 55 | this.localTimeDiff = res.serverTime - (+new Date()); 56 | this.time = res.serverTime; 57 | return res; 58 | }); 59 | } 60 | 61 | apiCall(method, path, {query, body, time} = {}) { 62 | if(this.localTimeDiff === null) { 63 | return Promise.reject(new Error('Get server time first .getTime()')); 64 | } 65 | 66 | // query in path 67 | var [pathOnly,pathQuery] = path.split('?'); 68 | if(pathQuery) query = {...qs.parse(pathQuery), ...query}; 69 | 70 | const nonce = createNonce(); 71 | const timestamp = (time || (+new Date() + this.localTimeDiff)).toString(); 72 | var headers = { 73 | "X-Request-Id": nonce, 74 | "X-User-Agent": "NHNodeClient", 75 | "X-Time": timestamp, 76 | "X-Nonce": nonce, 77 | "X-User-Lang": this.locale, 78 | "X-Organization-Id": this.org, 79 | "X-Auth": getAuthHeader( 80 | this.key, 81 | this.secret, 82 | timestamp, 83 | nonce, 84 | this.org, 85 | { 86 | method, 87 | path: pathOnly, 88 | query, 89 | body, 90 | }, 91 | ), 92 | } 93 | 94 | if(body && typeof body == 'object') headers['Content-Type'] = "application/json"; 95 | 96 | return fetch(`${this.host}${pathOnly}?${qs.stringify(query)}`, { 97 | method, 98 | headers, 99 | body: body ? JSON.stringify(body) : undefined 100 | }) 101 | .then(res => res.json()) 102 | } 103 | 104 | get(path, options) { 105 | return this.apiCall('GET', path, options) 106 | } 107 | 108 | post(path, options) { 109 | return this.apiCall('POST', path, options) 110 | } 111 | 112 | put(path, options) { 113 | return this.apiCall('PUT', path, options) 114 | } 115 | 116 | delete(path, options) { 117 | return this.apiCall('DELETE', path, options) 118 | } 119 | 120 | } 121 | 122 | export default Api 123 | -------------------------------------------------------------------------------- /c#/connect/connect/connect.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {25EF6083-E791-4BAD-A0C0-462A1A1220E3} 8 | Exe 9 | connect 10 | connect 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll 38 | 39 | 40 | ..\packages\NLog.4.6.5\lib\net45\NLog.dll 41 | 42 | 43 | ..\packages\RestSharp.106.6.10\lib\net452\RestSharp.dll 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /c#/connect/connect/Exch.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace connect 10 | { 11 | class Exch 12 | { 13 | private static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); 14 | 15 | private static string URL_ROOT = "https://api-test.nicehash.com"; //use https://api2.nicehash.com for production 16 | private static string ORG_ID = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"; 17 | private static string API_KEY = "ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj"; 18 | private static string API_SECRET = "kkkkkkkk-llll-mmmm-nnnn-oooooooooooooooooooo-pppp-qqqq-rrrr-ssssssssssss"; 19 | 20 | private static string CURRENCY_SELL = "TBTC"; //user BTC for production 21 | private static string CURRENCY_BUY = "TLTC"; //use LTC for production 22 | 23 | public Exch() 24 | { 25 | var config = new NLog.Config.LoggingConfiguration(); 26 | var logconsole = new NLog.Targets.ConsoleTarget("logconsole"); 27 | config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole); 28 | NLog.LogManager.Configuration = config; 29 | 30 | Api api = new Api(URL_ROOT, ORG_ID, API_KEY, API_SECRET); 31 | 32 | //get server time 33 | string timeResponse = api.get("/api/v2/time"); 34 | ServerTime serverTimeObject = Newtonsoft.Json.JsonConvert.DeserializeObject(timeResponse); 35 | string time = serverTimeObject.serverTime; 36 | Logger.Info("server time: {}", time); 37 | 38 | //get algo settings 39 | string exchResponse = api.get("/exchange/api/v2/info/status"); 40 | Symbols symbolsObj = Newtonsoft.Json.JsonConvert.DeserializeObject(exchResponse); 41 | 42 | String mySettings = null; 43 | foreach (Symbol s in symbolsObj.symbols) 44 | { 45 | if (s.baseAsset.Equals(CURRENCY_BUY)) 46 | { 47 | mySettings = s.baseAsset; 48 | } 49 | } 50 | Logger.Info("exchange settings: {}", mySettings); 51 | 52 | //get balance 53 | string accountsResponse = api.get("/main/api/v2/accounting/accounts2", true, time); 54 | Currencies currenciesObj = Newtonsoft.Json.JsonConvert.DeserializeObject(accountsResponse); 55 | double myBalace = 0; 56 | foreach (Currency c in currenciesObj.currencies) 57 | { 58 | if (c.currency.Equals(CURRENCY_SELL)) 59 | { 60 | myBalace = c.available; 61 | } 62 | } 63 | Logger.Info("balance: {} {}", myBalace, CURRENCY_SELL); 64 | 65 | //get order book 66 | string orderBookResponse = api.get("/exchange/api/v2/orderbook?market=" + CURRENCY_BUY + CURRENCY_SELL + "&limit=100", true, time); 67 | OrderBooks orderBooks = Newtonsoft.Json.JsonConvert.DeserializeObject(orderBookResponse); 68 | Logger.Info("cheapest offer price: {} supply: {}", orderBooks.sell[0][0], orderBooks.sell[0][1]); 69 | 70 | double qty = 0.1 * 2; 71 | string sQty = qty.ToString("0.00000000", System.Globalization.CultureInfo.InvariantCulture); 72 | string sPrice = orderBooks.sell[0][0].ToString("0.00000000", System.Globalization.CultureInfo.InvariantCulture); 73 | 74 | //buy with limit order 75 | string url = "/exchange/api/v2/order?market=" + CURRENCY_BUY + CURRENCY_SELL + "&side=buy&type=limit&quantity=" + sQty + "&price=" + sPrice; 76 | Logger.Info("order url: {}", url); 77 | string orderCreateResponse = api.post(url, null, time, true); 78 | Logger.Info("order create: {}", orderCreateResponse); 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /javascript/api.ts: -------------------------------------------------------------------------------- 1 | // contributed by @Maxim-Mazurok 2 | 3 | import CryptoJS from "crypto-js"; 4 | import { parse, stringify } from "qs"; 5 | 6 | function createNonce() { 7 | let s = ""; 8 | const length = 32; 9 | do { 10 | s += Math.random().toString(36).slice(2); 11 | } while (s.length < length); 12 | s = s.slice(0, Math.max(0, length)); 13 | return s; 14 | } 15 | 16 | const getAuthHeader = ( 17 | apiKey: string, 18 | apiSecret: string, 19 | time: string, 20 | nonce: string, 21 | organizationId = "", 22 | request: { 23 | method: string; 24 | path: string; 25 | query: Record | string; 26 | body: any; 27 | }, 28 | ) => { 29 | const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, apiSecret); 30 | 31 | hmac.update(apiKey); 32 | hmac.update("\0"); 33 | hmac.update(time); 34 | hmac.update("\0"); 35 | hmac.update(nonce); 36 | hmac.update("\0"); 37 | hmac.update("\0"); 38 | if (organizationId) hmac.update(organizationId); 39 | hmac.update("\0"); 40 | hmac.update("\0"); 41 | hmac.update(request.method); 42 | hmac.update("\0"); 43 | hmac.update(request.path); 44 | hmac.update("\0"); 45 | if (request.query) 46 | hmac.update( 47 | typeof request.query == "object" 48 | ? stringify(request.query) 49 | : request.query, 50 | ); 51 | if (request.body) { 52 | hmac.update("\0"); 53 | hmac.update( 54 | typeof request.body == "object" 55 | ? JSON.stringify(request.body) 56 | : request.body, 57 | ); 58 | } 59 | 60 | return apiKey + ":" + hmac.finalize().toString(CryptoJS.enc.Hex); 61 | }; 62 | 63 | export default class Api { 64 | private readonly locale: string; 65 | private readonly host: string; 66 | private readonly key: string; 67 | private readonly secret: string; 68 | private readonly org: string; 69 | private localTimeDiff?: number; 70 | 71 | constructor({ 72 | locale, 73 | apiHost, 74 | apiKey, 75 | apiSecret, 76 | orgId, 77 | }: { 78 | locale?: string; 79 | apiHost: string; 80 | apiKey: string; 81 | apiSecret: string; 82 | orgId: string; 83 | }) { 84 | this.locale = locale || "en"; 85 | this.host = apiHost; 86 | this.key = apiKey; 87 | this.secret = apiSecret; 88 | this.org = orgId; 89 | 90 | this.getTime(); 91 | } 92 | 93 | async getTime() { 94 | const response = (await ( 95 | await fetch(this.host + "/api/v2/time") 96 | ).json()) as { serverTime: number }; 97 | this.localTimeDiff = response.serverTime - Date.now(); 98 | return response; 99 | } 100 | 101 | private async apiCall( 102 | method: "GET" | "POST" | "PUT" | "DELETE", 103 | path: string, 104 | options?: { 105 | query: Record; 106 | body?: any; 107 | time?: number; 108 | }, 109 | ) { 110 | let query = {}, 111 | body, 112 | time; 113 | if (options) ({ query, body, time } = options); 114 | 115 | if (this.localTimeDiff === undefined) { 116 | throw new Error("Get server time first .getTime()"); 117 | } 118 | 119 | // query in path 120 | const [pathOnly, pathQuery] = path.split("?"); 121 | if (pathQuery) query = { ...parse(pathQuery), ...query }; 122 | 123 | const nonce = createNonce(); 124 | const timestamp = (time || Date.now() + this.localTimeDiff).toString(); 125 | var headers ={ 126 | "Content-type": "application/json", 127 | "X-Request-Id": nonce, 128 | "X-User-Agent": "NHNodeClient", 129 | "X-Time": timestamp, 130 | "X-Nonce": nonce, 131 | "X-User-Lang": this.locale, 132 | "X-Organization-Id": this.org, 133 | "X-Auth": getAuthHeader( 134 | this.key, 135 | this.secret, 136 | timestamp, 137 | nonce, 138 | this.org, 139 | { 140 | method, 141 | path: pathOnly, 142 | query, 143 | body, 144 | }, 145 | ), 146 | } 147 | 148 | if(body && typeof body == 'object') headers['Content-Type'] = "application/json"; 149 | 150 | return ( 151 | await fetch(`${this.host}${pathOnly}?${stringify(query)}`, { 152 | method, 153 | headers, 154 | body: body ? JSON.stringify(body) : undefined 155 | }) 156 | ).json(); 157 | } 158 | 159 | get( 160 | path: string, 161 | options?: { 162 | query: Record; 163 | body?: any; 164 | time?: number; 165 | }, 166 | ) { 167 | return this.apiCall("GET", path, options); 168 | } 169 | 170 | post( 171 | path: string, 172 | options?: { 173 | query: Record; 174 | body?: any; 175 | time?: number; 176 | }, 177 | ) { 178 | return this.apiCall("POST", path, options); 179 | } 180 | 181 | put( 182 | path: string, 183 | options?: { 184 | query: Record; 185 | body?: any; 186 | time?: number; 187 | }, 188 | ) { 189 | return this.apiCall("PUT", path, options); 190 | } 191 | 192 | delete( 193 | path: string, 194 | options?: { 195 | query: Record; 196 | body?: any; 197 | time?: number; 198 | }, 199 | ) { 200 | return this.apiCall("DELETE", path, options); 201 | } 202 | } 203 | 204 | // Usage 205 | /* 206 | await api.getTime(); // get server time - required 207 | const { totalBalance } = (await api.get( 208 | "/main/api/v2/accounting/account2/BTC", 209 | )) as { totalBalance: number }; // get balance settings 210 | console.log(`NiceHash total balance: ${totalBalance} BTC`); 211 | */ 212 | -------------------------------------------------------------------------------- /python/test_bot.py: -------------------------------------------------------------------------------- 1 | import nicehash 2 | 3 | # For testing purposes use api-test.nicehash.com. Register here: https://test.nicehash.com 4 | 5 | 6 | # When ready, uncomment line bellow, to run your script on production environment 7 | # host = 'https://api2.nicehash.com' 8 | 9 | 10 | # How to create key, secret and where to get organisation id please check: 11 | 12 | 13 | # Production - https://www.nicehash.com 14 | # host = 'https://api2.nicehash.com' 15 | # organisation_id = 'Enter your organisation id' 16 | # key = 'Enter your api key' 17 | # secret = 'Enter your secret for api key' 18 | 19 | 20 | # # Test - https://test.nicehash.com 21 | # host = 'https://api-test.nicehash.com' 22 | # organisation_id = '286fcf65-d44e-4cdf-81f2-4790c0cbed04' 23 | # key = '6b957253-bcb9-4b83-b431-4f28ab783a6f' 24 | # secret = 'ac09da0c-0b41-49ba-be6f-4698f9c184a67c6a834f-5bfe-5389-ba6f-d9ada9a86c03' 25 | 26 | ############################################ 27 | # PUBLIC FUNCTIONS 28 | 29 | # Create public api object 30 | public_api = nicehash.public_api(host, True) 31 | 32 | # Get all algorithms 33 | algorithms = public_api.get_algorithms() 34 | print(algorithms) 35 | 36 | # Get all markets 37 | markets = public_api.get_markets() 38 | print(markets) 39 | 40 | # Get all curencies 41 | currencies = public_api.get_currencies() 42 | print(currencies) 43 | 44 | # Get current global stats 45 | global_stats_current = public_api.get_current_global_stats() 46 | print(global_stats_current) 47 | 48 | # Get global stats for 24h 49 | global_stats_24h = public_api.get_global_stats_24() 50 | print(global_stats_24h) 51 | 52 | # Get orders for certain algorithm 53 | global_active_orders = public_api.get_active_orders() 54 | print(global_active_orders) 55 | 56 | # Buy info 57 | buy_info = public_api.buy_info() 58 | print(buy_info) 59 | 60 | # Get multialgo info 61 | multialgo_info = public_api.get_multialgo_info() 62 | print(multialgo_info) 63 | 64 | 65 | ############################################ 66 | # PRIVATE FUNCTIONS 67 | 68 | # Create private api object 69 | private_api = nicehash.private_api(host, organisation_id, key, secret, True) 70 | 71 | # Get balance for all currencies 72 | my_accounts = private_api.get_accounts() 73 | print(my_accounts) 74 | 75 | # Get balance for BTC address 76 | my_btc_account = private_api.get_accounts_for_currency(currencies['currencies'][0]['symbol']) 77 | print(my_btc_account) 78 | 79 | # Get my active hashpower orders 80 | my_top_active_x16r_eu_orders = private_api.get_my_active_orders('X16R', 'EU', 10) 81 | print(my_top_active_x16r_eu_orders) 82 | 83 | # Create pool 84 | new_pool = private_api.create_pool('My best pool', 'X16R', 'the.best.pool.com', 3333, 'mybestcoinaddress', 'x') 85 | print(new_pool) 86 | 87 | # Get pools 88 | pools_on_fist_page = private_api.get_my_pools(0, 10) 89 | print(pools_on_fist_page) 90 | 91 | # Create hashpower order 92 | new_order = private_api.create_hashpower_order('EU', 'STANDARD', 'X16R', 0.123, 0, 0.005, pools_on_fist_page['list'][0]['id'], algorithms) 93 | print(new_order) 94 | 95 | # Refill hashpower order 96 | refilled_order = private_api.refill_hashpower_order(new_order['id'], 0.005) 97 | print(refilled_order) 98 | 99 | # Order hashpower set price 100 | set_price_order = private_api.set_price_hashpower_order(new_order['id'], 0.234, 'X16R', algorithms) 101 | print(set_price_order) 102 | 103 | # Order hashpower set limit 104 | set_limit_order = private_api.set_limit_hashpower_order(new_order['id'], 2.12, 'X16R', algorithms) 105 | print(set_limit_order) 106 | 107 | # Order hashpower set price and imit 108 | set_limit_order = private_api.set_price_and_limit_hashpower_order(new_order['id'], 0.235, 1.2, 'X16R', algorithms) 109 | print(set_limit_order) 110 | 111 | # Remove hashpower order 112 | delete_hp_order = private_api.cancel_hashpower_order(new_order['id']) 113 | print(delete_hp_order) 114 | 115 | # Delete pool 116 | delete_pool_result = private_api.delete_pool(new_pool['id']) 117 | print(delete_pool_result) 118 | 119 | 120 | ############################################ 121 | # EXCHANGE 122 | 123 | # Get exchange market info 124 | exchange_info = public_api.get_exchange_markets_info() 125 | print(exchange_info) 126 | 127 | # Get trades for first market 128 | trades = public_api.get_exchange_trades(exchange_info['symbols'][0]['symbol']) 129 | print (trades) 130 | 131 | # Get candlesticks 132 | candlesticks = public_api.get_candlesticks(exchange_info['symbols'][0]['symbol'], 1561896404, 1567080464, 60) 133 | print (candlesticks) 134 | 135 | # Get exchange orderbook 136 | exchange_orderbook = public_api.get_exchange_orderbook(exchange_info['symbols'][0]['symbol'], 10) 137 | print (exchange_orderbook) 138 | 139 | # Get my exchange orders 140 | my_exchange_orders = private_api.get_my_exchange_orders(exchange_info['symbols'][0]['symbol']) 141 | print (my_exchange_orders) 142 | 143 | # Get my exchnage trades 144 | my_exchange_trades = private_api.get_my_exchange_trades(exchange_info['symbols'][0]['symbol']) 145 | print (my_exchange_trades) 146 | 147 | # Create buy limit exchange order 148 | new_sell_limit_order = private_api.create_exchange_limit_order(exchange_info['symbols'][0]['symbol'], 'sell', 10, 0.1) 149 | print (new_sell_limit_order) 150 | 151 | # Create sell limit exchange order 152 | new_buy_limit_order = private_api.create_exchange_limit_order(exchange_info['symbols'][0]['symbol'], 'buy', 0.1, 0.1) 153 | print (new_buy_limit_order) 154 | 155 | # Create sell market order 156 | new_sell_market_order = private_api.create_exchange_sell_market_order(exchange_info['symbols'][0]['symbol'], 0.1) 157 | print(new_sell_market_order) 158 | 159 | # Create buy market order 160 | new_buy_market_order = private_api.create_exchange_buy_market_order(exchange_info['symbols'][0]['symbol'], 0.1) 161 | print(new_buy_market_order) 162 | 163 | # Cancel exchange order 164 | cancelled_order = private_api.cancel_exchange_order(exchange_info['symbols'][0]['symbol'], my_exchange_orders[0]['orderId']) 165 | print(cancelled_order) 166 | -------------------------------------------------------------------------------- /c#/connect/connect/Hpo.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace connect 10 | { 11 | class Hpo 12 | { 13 | private static NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); 14 | 15 | private static string URL_ROOT = "https://api-test.nicehash.com"; //use https://api2.nicehash.com for production 16 | private static string ORG_ID = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"; 17 | private static string API_KEY = "ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj"; 18 | private static string API_SECRET = "kkkkkkkk-llll-mmmm-nnnn-oooooooooooooooooooo-pppp-qqqq-rrrr-ssssssssssss"; 19 | 20 | private static string ALGORITHM = "X16R"; //algo of your order 21 | private static string CURRENCY = "TBTC"; //user BTC for production 22 | 23 | public Hpo() 24 | { 25 | var config = new NLog.Config.LoggingConfiguration(); 26 | var logconsole = new NLog.Targets.ConsoleTarget("logconsole"); 27 | config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole); 28 | NLog.LogManager.Configuration = config; 29 | 30 | Api api = new Api(URL_ROOT, ORG_ID, API_KEY, API_SECRET); 31 | 32 | //get server time 33 | string timeResponse = api.get("/api/v2/time"); 34 | ServerTime serverTimeObject = Newtonsoft.Json.JsonConvert.DeserializeObject(timeResponse); 35 | string time = serverTimeObject.serverTime; 36 | Logger.Info("server time: {}", time); 37 | 38 | //get algo settings 39 | string algosResponse = api.get("/main/api/v2/mining/algorithms"); 40 | DataSet algoObject = Newtonsoft.Json.JsonConvert.DeserializeObject(algosResponse); 41 | DataTable algoTable = algoObject.Tables["miningAlgorithms"]; 42 | 43 | DataRow mySettings = null; 44 | foreach (DataRow algo in algoTable.Rows) 45 | { 46 | if (algo["algorithm"].Equals(ALGORITHM)) 47 | { 48 | mySettings = algo; 49 | } 50 | } 51 | Logger.Info("algo settings: {}", mySettings["algorithm"]); 52 | 53 | //get balance 54 | string accountsResponse = api.get("/main/api/v2/accounting/accounts2", true, time); 55 | Currencies currenciesObj = Newtonsoft.Json.JsonConvert.DeserializeObject(accountsResponse); 56 | double myBalace = 0; 57 | foreach (Currency c in currenciesObj.currencies) 58 | { 59 | if (c.currency.Equals(CURRENCY)) 60 | { 61 | myBalace = c.available; 62 | } 63 | } 64 | Logger.Info("balance: {} {}", myBalace, CURRENCY); 65 | 66 | //create pool 67 | Dictionary pool = new Dictionary 68 | { 69 | { "algorithm", ALGORITHM }, 70 | { "name", "my pool " + Guid.NewGuid().ToString() }, 71 | { "username", "pool_username" }, //your pool username 72 | { "password", "x" }, //your pool password 73 | { "stratumHostname", "pool.host.name" }, //pool hostname 74 | { "stratumPort", "3456" } //pool port 75 | }; 76 | 77 | string poolResponse = api.post("/main/api/v2/pool", Newtonsoft.Json.JsonConvert.SerializeObject(pool), time, false); 78 | Pool poolObject = Newtonsoft.Json.JsonConvert.DeserializeObject(poolResponse); 79 | string myPoolId = poolObject.id; 80 | Logger.Info("new pool id: {}", myPoolId); 81 | 82 | //create order 83 | Dictionary order = new Dictionary { 84 | { "algorithm", ALGORITHM }, 85 | { "amount", (string)mySettings["minimalOrderAmount"] }, 86 | { "displayMarketFactor", (string)mySettings["displayMarketFactor"] }, 87 | { "limit", (string)mySettings["minSpeedLimit"] }, // GH [minSpeedLimit-maxSpeedLimit] || 0 - unlimited speed 88 | { "market", "EU" }, 89 | { "marketFactor", (string)mySettings["marketFactor"] }, 90 | { "poolId", myPoolId }, 91 | { "price", "0.0010" }, //per BTC/GH/day 92 | { "type", "STANDARD" } 93 | }; 94 | 95 | string newOrderResponse = api.post("/main/api/v2/hashpower/order", Newtonsoft.Json.JsonConvert.SerializeObject(order), time, true); 96 | Order orderObject = Newtonsoft.Json.JsonConvert.DeserializeObject(newOrderResponse); 97 | string myOrderId = orderObject.id; 98 | Logger.Info("new order id: {}", myOrderId); 99 | 100 | //update price and limit 101 | Dictionary updateOrder = new Dictionary { 102 | { "displayMarketFactor", (string)mySettings["displayMarketFactor"] }, 103 | { "limit", "0.11" }, // GH [minSpeedLimit-maxSpeedLimit] || 0 - unlimited speed 104 | { "marketFactor", (string)mySettings["marketFactor"] }, 105 | { "price", "0.00123" } //per BTC/GH/day 106 | }; 107 | 108 | string updateOrderResponse = api.post("/main/api/v2/hashpower/order/" + myOrderId + "/updatePriceAndLimit", Newtonsoft.Json.JsonConvert.SerializeObject(updateOrder), time, true); 109 | Logger.Info("update order response: {}", updateOrderResponse); 110 | 111 | //delete order 112 | string deleteOrderResponse = api.delete("/main/api/v2/hashpower/order/" + myOrderId, time, true); 113 | Logger.Info("delete order response: {}", deleteOrderResponse); 114 | 115 | //delete pool 116 | string deletePoolResponse = api.delete("/main/api/v2/pool/" + myPoolId, time, true); 117 | Logger.Info("update pool response: {}", deletePoolResponse); 118 | } 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /java/src/main/java/Hpo.java: -------------------------------------------------------------------------------- 1 | import com.google.gson.*; 2 | import com.nicehash.connect.Api; 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.UUID; 8 | 9 | /** 10 | * hash power order example 11 | */ 12 | public class Hpo 13 | { 14 | private Log log = LogFactory.getLog(Hpo.class); 15 | 16 | private static final String URL_ROOT = "https://api-test.nicehash.com/"; //use https://api2.nicehash.com for production 17 | private static final String ORG_ID = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"; //get it here: https://test.nicehash.com/my/settings/keys or https://new.nicehash.com/my/settings/keys 18 | private static final String API_KEY = "ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj"; 19 | private static final String API_SECRET = "kkkkkkkk-llll-mmmm-nnnn-oooooooooooooooooooo-pppp-qqqq-rrrr-ssssssssssss"; 20 | 21 | private static final String ALGORITHM = "X16R"; //algo of your order 22 | private static final String CURRENCY = "TBTC"; //user BTC for production 23 | 24 | public static void main( String[] args ) { 25 | new Hpo(); 26 | } 27 | 28 | private Hpo() { 29 | Api api = new Api(URL_ROOT, ORG_ID, API_KEY, API_SECRET); 30 | 31 | //get server time 32 | String timeResponse = api.get("api/v2/time"); 33 | JsonObject timeObject = new Gson().fromJson(timeResponse, JsonObject.class); 34 | String time = timeObject.get("serverTime").getAsString(); 35 | log.info("server time: " + time); 36 | 37 | //get algo settings 38 | String algosResponse = api.get("main/api/v2/mining/algorithms"); 39 | JsonObject algoObject = new Gson().fromJson(algosResponse, JsonObject.class); 40 | //log.info("algorithms: " + algoObject.toString()); 41 | 42 | final JsonObject[] settings = new JsonObject[1]; 43 | algoObject.get("miningAlgorithms").getAsJsonArray().forEach(acc-> { 44 | JsonObject a = acc.getAsJsonObject(); 45 | if (a.get("algorithm").getAsString().equals(ALGORITHM)) { 46 | settings[0] = a; 47 | } 48 | }); 49 | 50 | JsonObject mySettings = settings[0]; 51 | log.info("algo settings: " + mySettings); 52 | 53 | //get balance 54 | String activityResponse = api.get("main/api/v2/accounting/accounts2", true, time); 55 | JsonObject accountsObject = new Gson().fromJson(activityResponse, JsonObject.class); 56 | //log.info("accounts: " + accountsObject.toString()); 57 | 58 | BigDecimal avaliableBalance = accountsObject.getAsJsonObject("total").getAsJsonPrimitive("available").getAsBigDecimal(); 59 | log.info("balance: " + avaliableBalance + CURRENCY); 60 | 61 | //create new pool 62 | JsonObject pool = new JsonObject(); 63 | pool.addProperty("algorithm", ALGORITHM); 64 | pool.addProperty("name", "my pool "+ UUID.randomUUID().toString()); 65 | pool.addProperty("username", "pool_username"); //your pool username 66 | pool.addProperty("password", "x"); //your pool password 67 | pool.addProperty("stratumHostname", "pool.host.name"); //pool hostname 68 | pool.addProperty("stratumPort", "3456"); //pool port 69 | 70 | //log.info("new pool: " + pool.toString()); 71 | String newPoolResponse = api.post("main/api/v2/pool", pool.toString(), time, false); 72 | //log.info("new pool response: " + newPoolResponse); 73 | JsonObject newPoolResponseObject = new Gson().fromJson(newPoolResponse, JsonObject.class); 74 | //log.info("new pool response object: " + newPoolResponseObject); 75 | 76 | String myPoolId = newPoolResponseObject.get("id").getAsString(); 77 | log.info("new pool id: " + myPoolId); 78 | 79 | //create new order 80 | JsonObject order = new JsonObject(); 81 | order.addProperty("algorithm", ALGORITHM); 82 | order.addProperty("amount", mySettings.get("minimalOrderAmount").getAsString()); 83 | order.addProperty("displayMarketFactor", mySettings.get("displayMarketFactor").getAsString()); 84 | order.addProperty("limit", mySettings.get("minSpeedLimit").getAsString()); // GH [minSpeedLimit-maxSpeedLimit] || 0 - unlimited speed 85 | order.addProperty("market", "EU"); // EU/USA 86 | order.addProperty("marketFactor", mySettings.get("marketFactor").getAsString()); 87 | order.addProperty("poolId", myPoolId); 88 | order.addProperty("price", "0.0010"); //per BTC/GH/day 89 | order.addProperty("type", "STANDARD"); 90 | 91 | //log.info("new order: " + order.toString()); 92 | String newOrderResponse = api.post("main/api/v2/hashpower/order", order.toString(), time, true); 93 | //log.info("new order response: " + newOrderResponse); 94 | JsonObject newOrderResponseObject = new Gson().fromJson(newOrderResponse, JsonObject.class); 95 | //log.info("new order response object: " + newOrderResponseObject); 96 | log.info("new order response object: " + newOrderResponseObject); 97 | 98 | String myOrderId = newOrderResponseObject.get("id").getAsString(); 99 | log.info("new order id: " + myOrderId); 100 | 101 | //update price and limit 102 | JsonObject updateOrder = new JsonObject(); 103 | updateOrder.addProperty("displayMarketFactor", mySettings.get("displayMarketFactor").getAsString()); 104 | updateOrder.addProperty("limit", "0.11"); // GH [minSpeedLimit-maxSpeedLimit] || 0 - unlimited speed 105 | updateOrder.addProperty("marketFactor", mySettings.get("marketFactor").getAsString()); 106 | updateOrder.addProperty("price", "0.00123"); //per BTC/GH/day 107 | 108 | //log.info("update order: " + updateOrder.toString()); 109 | String updateOrderResponse = api.post("main/api/v2/hashpower/order/"+myOrderId+"/updatePriceAndLimit", updateOrder.toString(), time, true); 110 | //log.info("update order response: " + updateOrderResponse); 111 | JsonObject updateOrderResponseObject = new Gson().fromJson(updateOrderResponse, JsonObject.class); 112 | log.info("update order response object: " + updateOrderResponseObject); 113 | 114 | //delete order 115 | String deleteOrderResponse = api.delete("main/api/v2/hashpower/order/"+myOrderId, time, true); 116 | //log.info("delete order response: " + deleteOrderResponse); 117 | JsonObject deleteOrderResponseObject = new Gson().fromJson(deleteOrderResponse, JsonObject.class); 118 | log.info("delete order response object: " + deleteOrderResponseObject); 119 | 120 | //delete pool 121 | String deletePoolResponse = api.delete("main/api/v2/pool/"+myPoolId, time, false); 122 | //log.info("delete pool response: " + deletePoolResponse); 123 | JsonObject deletePoolResponseObject = new Gson().fromJson(deletePoolResponse, JsonObject.class); 124 | log.info("delete pool response object: " + deletePoolResponseObject); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /c#/connect/connect/Api.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace connect 8 | { 9 | class Api 10 | { 11 | private string urlRoot; 12 | private string orgId; 13 | private string apiKey; 14 | private string apiSecret; 15 | 16 | public Api(string urlRoot, string orgId, string apiKey, string apiSecret) 17 | { 18 | this.urlRoot = urlRoot; 19 | this.orgId = orgId; 20 | this.apiKey = apiKey; 21 | this.apiSecret = apiSecret; 22 | } 23 | 24 | private static string HashBySegments(string key, string apiKey, string time, string nonce, string orgId, string method, string encodedPath, string query, string bodyStr) 25 | { 26 | List segments = new List(); 27 | segments.Add(apiKey); 28 | segments.Add(time); 29 | segments.Add(nonce); 30 | segments.Add(null); 31 | segments.Add(orgId); 32 | segments.Add(null); 33 | segments.Add(method); 34 | segments.Add(encodedPath == null ? null : encodedPath); 35 | segments.Add(query == null ? null : query); 36 | 37 | if (bodyStr != null && bodyStr.Length > 0) { 38 | segments.Add(bodyStr); 39 | } 40 | return Api.CalcHMACSHA256Hash(Api.JoinSegments(segments), key); 41 | } 42 | private static string getPath(string url) 43 | { 44 | var arrSplit = url.Split('?'); 45 | return arrSplit[0]; 46 | } 47 | private static string getQuery(string url) { 48 | var arrSplit = url.Split('?'); 49 | 50 | if (arrSplit.Length == 1) 51 | { 52 | return null; 53 | } 54 | else 55 | { 56 | return arrSplit[1]; 57 | } 58 | } 59 | 60 | private static string JoinSegments(List segments) { 61 | var sb = new System.Text.StringBuilder(); 62 | bool first = true; 63 | foreach (var segment in segments) { 64 | if (!first) 65 | { 66 | sb.Append("\x00"); 67 | } 68 | else 69 | { 70 | first = false; 71 | } 72 | 73 | if (segment != null) 74 | { 75 | sb.Append(segment); 76 | } 77 | } 78 | //Console.WriteLine("["+sb.ToString()+"]"); 79 | return sb.ToString(); 80 | } 81 | 82 | private static string CalcHMACSHA256Hash(string plaintext, string salt) 83 | { 84 | string result = ""; 85 | var enc = Encoding.Default; 86 | byte[] 87 | baText2BeHashed = enc.GetBytes(plaintext), 88 | baSalt = enc.GetBytes(salt); 89 | System.Security.Cryptography.HMACSHA256 hasher = new System.Security.Cryptography.HMACSHA256(baSalt); 90 | byte[] baHashedText = hasher.ComputeHash(baText2BeHashed); 91 | result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x2")).ToArray()); 92 | return result; 93 | } 94 | 95 | public string get(string url) 96 | { 97 | return this.get(url, false, null); 98 | } 99 | 100 | public string get(string url, bool auth, string time) 101 | { 102 | var client = new RestSharp.RestClient(this.urlRoot); 103 | var request = new RestSharp.RestRequest(url); 104 | 105 | if (auth) 106 | { 107 | string nonce = Guid.NewGuid().ToString(); 108 | string digest = Api.HashBySegments(this.apiSecret, this.apiKey, time, nonce, this.orgId, "GET", getPath(url), getQuery(url), null); 109 | 110 | request.AddHeader("X-Time", time); 111 | request.AddHeader("X-Nonce", nonce); 112 | request.AddHeader("X-Auth", this.apiKey + ":" + digest); 113 | request.AddHeader("X-Organization-Id", this.orgId); 114 | } 115 | 116 | var response = client.Execute(request, RestSharp.Method.GET); 117 | var content = response.Content; 118 | return content; 119 | } 120 | 121 | public string post(string url, string payload, string time, bool requestId) 122 | { 123 | var client = new RestSharp.RestClient(this.urlRoot); 124 | var request = new RestSharp.RestRequest(url); 125 | request.AddHeader("Accept", "application/json"); 126 | request.AddHeader("Content-type", "application/json"); 127 | 128 | string nonce = Guid.NewGuid().ToString(); 129 | string digest = Api.HashBySegments(this.apiSecret, this.apiKey, time, nonce, this.orgId, "POST", getPath(url), getQuery(url), payload); 130 | 131 | if (payload !=null) 132 | { 133 | request.AddJsonBody(payload); 134 | } 135 | 136 | request.AddHeader("X-Time", time); 137 | request.AddHeader("X-Nonce", nonce); 138 | request.AddHeader("X-Auth", this.apiKey + ":" + digest); 139 | request.AddHeader("X-Organization-Id", this.orgId); 140 | 141 | if (requestId) 142 | { 143 | request.AddHeader("X-Request-Id", Guid.NewGuid().ToString()); 144 | } 145 | 146 | var response = client.Execute(request, RestSharp.Method.POST); 147 | var content = response.Content; 148 | return content; 149 | } 150 | 151 | public string delete(string url, string time, bool requestId) 152 | { 153 | var client = new RestSharp.RestClient(this.urlRoot); 154 | var request = new RestSharp.RestRequest(url); 155 | 156 | string nonce = Guid.NewGuid().ToString(); 157 | string digest = Api.HashBySegments(this.apiSecret, this.apiKey, time, nonce, this.orgId, "DELETE", getPath(url), getQuery(url), null); 158 | 159 | request.AddHeader("X-Time", time); 160 | request.AddHeader("X-Nonce", nonce); 161 | request.AddHeader("X-Auth", this.apiKey + ":" + digest); 162 | request.AddHeader("X-Organization-Id", this.orgId); 163 | 164 | if (requestId) 165 | { 166 | request.AddHeader("X-Request-Id", Guid.NewGuid().ToString()); 167 | } 168 | 169 | var response = client.Execute(request, RestSharp.Method.DELETE); 170 | var content = response.Content; 171 | return content; 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /java/src/main/java/com/nicehash/connect/Api.java: -------------------------------------------------------------------------------- 1 | package com.nicehash.connect; 2 | 3 | import org.apache.commons.codec.binary.Hex; 4 | import org.apache.http.HttpHeaders; 5 | import org.apache.http.HttpResponse; 6 | import org.apache.http.client.HttpClient; 7 | import org.apache.http.client.methods.HttpDelete; 8 | import org.apache.http.client.methods.HttpGet; 9 | import org.apache.http.client.methods.HttpPost; 10 | import org.apache.http.entity.StringEntity; 11 | import org.apache.http.impl.client.CloseableHttpClient; 12 | import org.apache.http.impl.client.HttpClientBuilder; 13 | 14 | import javax.crypto.Mac; 15 | import javax.crypto.spec.SecretKeySpec; 16 | import java.io.*; 17 | import java.nio.charset.Charset; 18 | import java.nio.charset.StandardCharsets; 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.UUID; 23 | 24 | public class Api { 25 | 26 | private static final Charset CHARSET = StandardCharsets.ISO_8859_1; 27 | private static final String HMAC_SHA256 = "HmacSHA256"; 28 | 29 | private String urlRoot; 30 | private String orgId; 31 | private String apiKey; 32 | private String apiSecret; 33 | 34 | public Api(String urlRoot, String orgId, String apiKey, String apiSecret) { 35 | this.urlRoot = urlRoot; 36 | this.orgId = orgId; 37 | this.apiKey = apiKey; 38 | this.apiSecret = apiSecret; 39 | } 40 | 41 | private static String hashBySegments(String key, String apiKey, String time, String nonce, String orgId, String method, String encodedPath, String query, String bodyStr) { 42 | List segments = Arrays.asList( 43 | apiKey.getBytes(CHARSET), 44 | time.getBytes(CHARSET), 45 | nonce.getBytes(CHARSET), 46 | null, // unused field 47 | orgId.getBytes(CHARSET), 48 | null, // unused field 49 | method.getBytes(CHARSET), 50 | encodedPath == null ? null : encodedPath.getBytes(CHARSET), 51 | query == null ? null : query.getBytes(CHARSET)); 52 | 53 | if (bodyStr != null && bodyStr.length() > 0) { 54 | segments = new ArrayList<>(segments); 55 | segments.add(bodyStr.getBytes(StandardCharsets.UTF_8)); 56 | } 57 | return hmacSha256BySegments(key, segments); 58 | } 59 | 60 | private static String hmacSha256BySegments(String key, List segments) { 61 | try { 62 | Mac mac = Mac.getInstance(HMAC_SHA256); 63 | SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA256); 64 | mac.init(secret_key); 65 | boolean first = true; 66 | 67 | for (byte [] segment: segments) { 68 | 69 | if (!first) { 70 | mac.update((byte) 0); 71 | } else { 72 | first = false; 73 | } 74 | 75 | if (segment != null) { 76 | mac.update(segment); 77 | } 78 | } 79 | 80 | return Hex.encodeHexString(mac.doFinal()); 81 | } catch (Exception e) { 82 | throw new RuntimeException("Cannot create HmacSHA256", e); 83 | } 84 | } 85 | 86 | public String get(String url) { 87 | return this.get(url, false, null); 88 | } 89 | 90 | public String get(String url, boolean auth, String time) { 91 | StringBuffer result = new StringBuffer(); 92 | HttpClient client = HttpClientBuilder.create().build(); 93 | HttpGet request = new HttpGet(this.urlRoot+url); 94 | 95 | if (auth) { 96 | String nonce = UUID.randomUUID().toString(); 97 | String digest = Api.hashBySegments(this.apiSecret, this.apiKey, time, nonce, this.orgId, request.getMethod(), request.getURI().getPath(), request.getURI().getQuery(), null); 98 | 99 | request.setHeader("X-Time", time); 100 | request.setHeader("X-Nonce", nonce); 101 | request.setHeader("X-Auth", this.apiKey+":"+digest); 102 | request.setHeader("X-Organization-Id", this.orgId); 103 | } 104 | 105 | try { 106 | HttpResponse response = client.execute(request); 107 | BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 108 | 109 | String line = ""; 110 | while ((line = rd.readLine()) != null) { 111 | result.append(line); 112 | } 113 | } catch (IOException e) { 114 | e.printStackTrace(); 115 | } 116 | return result.toString(); 117 | } 118 | 119 | public String post(String url, String payload, String time, boolean requestId) { 120 | StringBuffer result = new StringBuffer(); 121 | HttpClient client = HttpClientBuilder.create().build(); 122 | HttpPost request = new HttpPost(this.urlRoot+url); 123 | 124 | StringEntity entity = null; 125 | if (payload != null) { 126 | try { 127 | entity = new StringEntity(payload); 128 | } catch (UnsupportedEncodingException e) { 129 | e.printStackTrace(); 130 | } 131 | } 132 | 133 | request.setEntity(entity); 134 | request.setHeader("Accept", "application/json"); 135 | request.setHeader("Content-type", "application/json"); 136 | 137 | String nonce = UUID.randomUUID().toString(); 138 | String digest = Api.hashBySegments(this.apiSecret, this.apiKey, time, nonce, this.orgId, request.getMethod(), request.getURI().getPath(), request.getURI().getQuery(), payload); 139 | 140 | request.setHeader("X-Time", time); 141 | request.setHeader("X-Nonce", nonce); 142 | request.setHeader("X-Auth", this.apiKey+":"+digest); 143 | request.setHeader("X-Organization-Id", this.orgId); 144 | if (requestId) 145 | request.setHeader("X-Request-Id", UUID.randomUUID().toString()); //must be unique request 146 | 147 | try { 148 | HttpResponse response = client.execute(request); 149 | BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 150 | 151 | String line = ""; 152 | while ((line = rd.readLine()) != null) { 153 | result.append(line); 154 | } 155 | } catch (IOException e) { 156 | e.printStackTrace(); 157 | } 158 | return result.toString(); 159 | } 160 | 161 | public String delete(String url, String time, boolean requestId) { 162 | StringBuffer result = new StringBuffer(); 163 | HttpClient client = HttpClientBuilder.create().build(); 164 | HttpDelete request = new HttpDelete(this.urlRoot+url); 165 | 166 | String nonce = UUID.randomUUID().toString(); 167 | String digest = Api.hashBySegments(this.apiSecret, this.apiKey, time, nonce, this.orgId, request.getMethod(), request.getURI().getPath(), request.getURI().getQuery(), null); 168 | 169 | request.setHeader("X-Time", time); 170 | request.setHeader("X-Nonce", nonce); 171 | request.setHeader("X-Auth", this.apiKey+":"+digest); 172 | request.setHeader("X-Organization-Id", this.orgId); 173 | if (requestId) 174 | request.setHeader("X-Request-Id", UUID.randomUUID().toString()); //must be unique request 175 | 176 | try { 177 | HttpResponse response = client.execute(request); 178 | BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 179 | 180 | String line = ""; 181 | while ((line = rd.readLine()) != null) { 182 | result.append(line); 183 | } 184 | } catch (IOException e) { 185 | e.printStackTrace(); 186 | } 187 | return result.toString(); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /javascript/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-app-node", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "example-app-node", 9 | "version": "0.0.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "crypto-js": "^3.1.9-1", 13 | "esm": "^3.2.25", 14 | "qs": "^6.7.0" 15 | } 16 | }, 17 | "node_modules/call-bind": { 18 | "version": "1.0.2", 19 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 20 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 21 | "dependencies": { 22 | "function-bind": "^1.1.1", 23 | "get-intrinsic": "^1.0.2" 24 | }, 25 | "funding": { 26 | "url": "https://github.com/sponsors/ljharb" 27 | } 28 | }, 29 | "node_modules/crypto-js": { 30 | "version": "3.1.9-1", 31 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", 32 | "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" 33 | }, 34 | "node_modules/esm": { 35 | "version": "3.2.25", 36 | "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", 37 | "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", 38 | "engines": { 39 | "node": ">=6" 40 | } 41 | }, 42 | "node_modules/function-bind": { 43 | "version": "1.1.1", 44 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 45 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 46 | }, 47 | "node_modules/get-intrinsic": { 48 | "version": "1.2.0", 49 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 50 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 51 | "dependencies": { 52 | "function-bind": "^1.1.1", 53 | "has": "^1.0.3", 54 | "has-symbols": "^1.0.3" 55 | }, 56 | "funding": { 57 | "url": "https://github.com/sponsors/ljharb" 58 | } 59 | }, 60 | "node_modules/has": { 61 | "version": "1.0.3", 62 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 63 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 64 | "dependencies": { 65 | "function-bind": "^1.1.1" 66 | }, 67 | "engines": { 68 | "node": ">= 0.4.0" 69 | } 70 | }, 71 | "node_modules/has-symbols": { 72 | "version": "1.0.3", 73 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 74 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 75 | "engines": { 76 | "node": ">= 0.4" 77 | }, 78 | "funding": { 79 | "url": "https://github.com/sponsors/ljharb" 80 | } 81 | }, 82 | "node_modules/object-inspect": { 83 | "version": "1.12.3", 84 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 85 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 86 | "funding": { 87 | "url": "https://github.com/sponsors/ljharb" 88 | } 89 | }, 90 | "node_modules/qs": { 91 | "version": "6.11.1", 92 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", 93 | "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", 94 | "dependencies": { 95 | "side-channel": "^1.0.4" 96 | }, 97 | "engines": { 98 | "node": ">=0.6" 99 | }, 100 | "funding": { 101 | "url": "https://github.com/sponsors/ljharb" 102 | } 103 | }, 104 | "node_modules/side-channel": { 105 | "version": "1.0.4", 106 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 107 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 108 | "dependencies": { 109 | "call-bind": "^1.0.0", 110 | "get-intrinsic": "^1.0.2", 111 | "object-inspect": "^1.9.0" 112 | }, 113 | "funding": { 114 | "url": "https://github.com/sponsors/ljharb" 115 | } 116 | } 117 | }, 118 | "dependencies": { 119 | "call-bind": { 120 | "version": "1.0.2", 121 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 122 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 123 | "requires": { 124 | "function-bind": "^1.1.1", 125 | "get-intrinsic": "^1.0.2" 126 | } 127 | }, 128 | "crypto-js": { 129 | "version": "3.1.9-1", 130 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", 131 | "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" 132 | }, 133 | "esm": { 134 | "version": "3.2.25", 135 | "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", 136 | "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" 137 | }, 138 | "function-bind": { 139 | "version": "1.1.1", 140 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 141 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 142 | }, 143 | "get-intrinsic": { 144 | "version": "1.2.0", 145 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 146 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 147 | "requires": { 148 | "function-bind": "^1.1.1", 149 | "has": "^1.0.3", 150 | "has-symbols": "^1.0.3" 151 | } 152 | }, 153 | "has": { 154 | "version": "1.0.3", 155 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 156 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 157 | "requires": { 158 | "function-bind": "^1.1.1" 159 | } 160 | }, 161 | "has-symbols": { 162 | "version": "1.0.3", 163 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 164 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 165 | }, 166 | "object-inspect": { 167 | "version": "1.12.3", 168 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 169 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" 170 | }, 171 | "qs": { 172 | "version": "6.11.1", 173 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", 174 | "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", 175 | "requires": { 176 | "side-channel": "^1.0.4" 177 | } 178 | }, 179 | "side-channel": { 180 | "version": "1.0.4", 181 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 182 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 183 | "requires": { 184 | "call-bind": "^1.0.0", 185 | "get-intrinsic": "^1.0.2", 186 | "object-inspect": "^1.9.0" 187 | } 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /python/nicehash.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from time import mktime 3 | import uuid 4 | import hmac 5 | import requests 6 | import json 7 | from hashlib import sha256 8 | import optparse 9 | import sys 10 | 11 | 12 | class public_api: 13 | 14 | def __init__(self, host, verbose=False): 15 | self.host = host 16 | self.verbose = verbose 17 | 18 | def request(self, method, path, query, body): 19 | url = self.host + path 20 | if query: 21 | url += '?' + query 22 | 23 | if self.verbose: 24 | print(method, url) 25 | 26 | s = requests.Session() 27 | if body: 28 | body_json = json.dumps(body) 29 | response = s.request(method, url, data=body_json) 30 | else: 31 | response = s.request(method, url) 32 | 33 | if response.status_code == 200: 34 | return response.json() 35 | elif response.content: 36 | raise Exception(str(response.status_code) + ": " + response.reason + ": " + str(response.content)) 37 | else: 38 | raise Exception(str(response.status_code) + ": " + response.reason) 39 | 40 | def get_current_global_stats(self): 41 | return self.request('GET', '/main/api/v2/public/stats/global/current/', '', None) 42 | 43 | def get_global_stats_24(self): 44 | return self.request('GET', '/main/api/v2/public/stats/global/24h/', '', None) 45 | 46 | def get_active_orders(self): 47 | return self.request('GET', '/main/api/v2/public/orders/active/', '', None) 48 | 49 | def get_active_orders2(self): 50 | return self.request('GET', '/main/api/v2/public/orders/active2/', '', None) 51 | 52 | def buy_info(self): 53 | return self.request('GET', '/main/api/v2/public/buy/info/', '', None) 54 | 55 | def get_algorithms(self): 56 | return self.request('GET', '/main/api/v2/mining/algorithms/', '', None) 57 | 58 | def get_markets(self): 59 | return self.request('GET', '/main/api/v2/mining/markets/', '', None) 60 | 61 | def get_currencies(self): 62 | return self.request('GET', '/main/api/v2/public/currencies/', '', None) 63 | 64 | def get_multialgo_info(self): 65 | return self.request('GET', '/main/api/v2/public/simplemultialgo/info/', '', None) 66 | 67 | def get_exchange_markets_info(self): 68 | return self.request('GET', '/exchange/api/v2/info/status', '', None) 69 | 70 | def get_exchange_trades(self, market): 71 | return self.request('GET', '/exchange/api/v2/trades', 'market=' + market, None) 72 | 73 | def get_candlesticks(self, market, from_s, to_s, resolution): 74 | return self.request('GET', '/exchange/api/v2/candlesticks', "market={}&from={}&to={}&resolution={}".format(market, from_s, to_s, resolution), None) 75 | 76 | def get_exchange_orderbook(self, market, limit): 77 | return self.request('GET', '/exchange/api/v2/orderbook', "market={}&limit={}".format(market, limit), None) 78 | 79 | class private_api: 80 | 81 | def __init__(self, host, organisation_id, key, secret, verbose=False): 82 | self.key = key 83 | self.secret = secret 84 | self.organisation_id = organisation_id 85 | self.host = host 86 | self.verbose = verbose 87 | 88 | def request(self, method, path, query, body): 89 | 90 | xtime = self.get_epoch_ms_from_now() 91 | xnonce = str(uuid.uuid4()) 92 | 93 | message = bytearray(self.key, 'utf-8') 94 | message += bytearray('\x00', 'utf-8') 95 | message += bytearray(str(xtime), 'utf-8') 96 | message += bytearray('\x00', 'utf-8') 97 | message += bytearray(xnonce, 'utf-8') 98 | message += bytearray('\x00', 'utf-8') 99 | message += bytearray('\x00', 'utf-8') 100 | message += bytearray(self.organisation_id, 'utf-8') 101 | message += bytearray('\x00', 'utf-8') 102 | message += bytearray('\x00', 'utf-8') 103 | message += bytearray(method, 'utf-8') 104 | message += bytearray('\x00', 'utf-8') 105 | message += bytearray(path, 'utf-8') 106 | message += bytearray('\x00', 'utf-8') 107 | message += bytearray(query, 'utf-8') 108 | 109 | if body: 110 | body_json = json.dumps(body) 111 | message += bytearray('\x00', 'utf-8') 112 | message += bytearray(body_json, 'utf-8') 113 | 114 | digest = hmac.new(bytearray(self.secret, 'utf-8'), message, sha256).hexdigest() 115 | xauth = self.key + ":" + digest 116 | 117 | headers = { 118 | 'X-Time': str(xtime), 119 | 'X-Nonce': xnonce, 120 | 'X-Auth': xauth, 121 | 'Content-Type': 'application/json', 122 | 'X-Organization-Id': self.organisation_id, 123 | 'X-Request-Id': str(uuid.uuid4()) 124 | } 125 | 126 | s = requests.Session() 127 | s.headers = headers 128 | 129 | url = self.host + path 130 | if query: 131 | url += '?' + query 132 | 133 | if self.verbose: 134 | print(method, url) 135 | 136 | if body: 137 | response = s.request(method, url, data=body_json) 138 | else: 139 | response = s.request(method, url) 140 | 141 | if response.status_code == 200: 142 | return response.json() 143 | elif response.content: 144 | raise Exception(str(response.status_code) + ": " + response.reason + ": " + str(response.content)) 145 | else: 146 | raise Exception(str(response.status_code) + ": " + response.reason) 147 | 148 | def get_epoch_ms_from_now(self): 149 | now = datetime.now() 150 | now_ec_since_epoch = mktime(now.timetuple()) + now.microsecond / 1000000.0 151 | return int(now_ec_since_epoch * 1000) 152 | 153 | def algo_settings_from_response(self, algorithm, algo_response): 154 | algo_setting = None 155 | for item in algo_response['miningAlgorithms']: 156 | if item['algorithm'] == algorithm: 157 | algo_setting = item 158 | 159 | if algo_setting is None: 160 | raise Exception('Settings for algorithm not found in algo_response parameter') 161 | 162 | return algo_setting 163 | 164 | def get_accounts(self): 165 | return self.request('GET', '/main/api/v2/accounting/accounts2/', '', None) 166 | 167 | def get_accounts_for_currency(self, currency): 168 | return self.request('GET', '/main/api/v2/accounting/account2/' + currency, '', None) 169 | 170 | def get_withdrawal_addresses(self, currency, size, page): 171 | 172 | params = "currency={}&size={}&page={}".format(currency, size, page) 173 | 174 | return self.request('GET', '/main/api/v2/accounting/withdrawalAddresses/', params, None) 175 | 176 | def get_withdrawal_types(self): 177 | return self.request('GET', '/main/api/v2/accounting/withdrawalAddresses/types/', '', None) 178 | 179 | def withdraw_request(self, address_id, amount, currency): 180 | withdraw_data = { 181 | "withdrawalAddressId": address_id, 182 | "amount": amount, 183 | "currency": currency 184 | } 185 | return self.request('POST', '/main/api/v2/accounting/withdrawal/', '', withdraw_data) 186 | 187 | def get_my_active_orders(self, algorithm, market, limit): 188 | 189 | ts = self.get_epoch_ms_from_now() 190 | params = "algorithm={}&market={}&ts={}&limit={}&op=LT".format(algorithm, market, ts, limit) 191 | 192 | return self.request('GET', '/main/api/v2/hashpower/myOrders', params, None) 193 | 194 | def create_pool(self, name, algorithm, pool_host, pool_port, username, password): 195 | pool_data = { 196 | "name": name, 197 | "algorithm": algorithm, 198 | "stratumHostname": pool_host, 199 | "stratumPort": pool_port, 200 | "username": username, 201 | "password": password 202 | } 203 | return self.request('POST', '/main/api/v2/pool/', '', pool_data) 204 | 205 | def delete_pool(self, pool_id): 206 | return self.request('DELETE', '/main/api/v2/pool/' + pool_id, '', None) 207 | 208 | def get_my_pools(self, page, size): 209 | return self.request('GET', '/main/api/v2/pools/', '', None) 210 | 211 | def get_hashpower_orderbook(self, algorithm): 212 | return self.request('GET', '/main/api/v2/hashpower/orderBook/', 'algorithm=' + algorithm, None ) 213 | 214 | def create_hashpower_order(self, market, type, algorithm, price, limit, amount, pool_id, algo_response): 215 | 216 | algo_setting = self.algo_settings_from_response(algorithm, algo_response) 217 | 218 | order_data = { 219 | "market": market, 220 | "algorithm": algorithm, 221 | "amount": amount, 222 | "price": price, 223 | "limit": limit, 224 | "poolId": pool_id, 225 | "type": type, 226 | "marketFactor": algo_setting['marketFactor'], 227 | "displayMarketFactor": algo_setting['displayMarketFactor'] 228 | } 229 | return self.request('POST', '/main/api/v2/hashpower/order/', '', order_data) 230 | 231 | def cancel_hashpower_order(self, order_id): 232 | return self.request('DELETE', '/main/api/v2/hashpower/order/' + order_id, '', None) 233 | 234 | def refill_hashpower_order(self, order_id, amount): 235 | refill_data = { 236 | "amount": amount 237 | } 238 | return self.request('POST', '/main/api/v2/hashpower/order/' + order_id + '/refill/', '', refill_data) 239 | 240 | def set_price_hashpower_order(self, order_id, price, algorithm, algo_response): 241 | 242 | algo_setting = self.algo_settings_from_response(algorithm, algo_response) 243 | 244 | price_data = { 245 | "price": price, 246 | "marketFactor": algo_setting['marketFactor'], 247 | "displayMarketFactor": algo_setting['displayMarketFactor'] 248 | } 249 | return self.request('POST', '/main/api/v2/hashpower/order/' + order_id + '/updatePriceAndLimit/', '', 250 | price_data) 251 | 252 | def set_limit_hashpower_order(self, order_id, limit, algorithm, algo_response): 253 | algo_setting = self.algo_settings_from_response(algorithm, algo_response) 254 | limit_data = { 255 | "limit": limit, 256 | "marketFactor": algo_setting['marketFactor'], 257 | "displayMarketFactor": algo_setting['displayMarketFactor'] 258 | } 259 | return self.request('POST', '/main/api/v2/hashpower/order/' + order_id + '/updatePriceAndLimit/', '', 260 | limit_data) 261 | 262 | def set_price_and_limit_hashpower_order(self, order_id, price, limit, algorithm, algo_response): 263 | algo_setting = self.algo_settings_from_response(algorithm, algo_response) 264 | 265 | price_data = { 266 | "price": price, 267 | "limit": limit, 268 | "marketFactor": algo_setting['marketFactor'], 269 | "displayMarketFactor": algo_setting['displayMarketFactor'] 270 | } 271 | return self.request('POST', '/main/api/v2/hashpower/order/' + order_id + '/updatePriceAndLimit/', '', 272 | price_data) 273 | 274 | def get_my_exchange_orders(self, market): 275 | return self.request('GET', '/exchange/api/v2/myOrders', 'market=' + market, None) 276 | 277 | def get_my_exchange_trades(self, market): 278 | return self.request('GET','/exchange/api/v2/myTrades', 'market=' + market, None) 279 | 280 | def create_exchange_limit_order(self, market, side, quantity, price): 281 | query = "market={}&side={}&type=limit&quantity={}&price={}".format(market, side, quantity, price) 282 | return self.request('POST', '/exchange/api/v2/order', query, None) 283 | 284 | def create_exchange_buy_market_order(self, market, quantity): 285 | query = "market={}&side=buy&type=market&secQuantity={}".format(market, quantity) 286 | return self.request('POST', '/exchange/api/v2/order', query, None) 287 | 288 | def create_exchange_sell_market_order(self, market, quantity): 289 | query = "market={}&side=sell&type=market&quantity={}".format(market, quantity) 290 | return self.request('POST', '/exchange/api/v2/order', query, None) 291 | 292 | def cancel_exchange_order(self, market, order_id): 293 | query = "market={}&orderId={}".format(market, order_id) 294 | return self.request('DELETE', '/exchange/api/v2/order', query, None) 295 | 296 | 297 | if __name__ == "__main__": 298 | parser = optparse.OptionParser() 299 | 300 | parser.add_option('-b', '--base_url', dest="base", help="Api base url", default="https://api2.nicehash.com") 301 | parser.add_option('-o', '--organization_id', dest="org", help="Organization id") 302 | parser.add_option('-k', '--key', dest="key", help="Api key") 303 | parser.add_option('-s', '--secret', dest="secret", help="Secret for api key") 304 | parser.add_option('-m', '--method', dest="method", help="Method for request", default="GET") 305 | parser.add_option('-p', '--path', dest="path", help="Path for request", default="/") 306 | parser.add_option('-q', '--params', dest="params", help="Parameters for request") 307 | parser.add_option('-d', '--body', dest="body", help="Body for request") 308 | 309 | options, args = parser.parse_args() 310 | 311 | private_api = private_api(options.base, options.org, options.key, options.secret) 312 | 313 | params = '' 314 | if options.params is not None: 315 | params = options.params 316 | 317 | try: 318 | response = private_api.request(options.method, options.path, params, options.body) 319 | except Exception as ex: 320 | print("Unexpected error:", ex) 321 | exit(1) 322 | 323 | print(response) 324 | exit(0) 325 | --------------------------------------------------------------------------------