├── .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 | 
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 |
--------------------------------------------------------------------------------