4438bd3d6a
- add mining rig and device classes
142 lines
4.6 KiB
Python
142 lines
4.6 KiB
Python
"""
|
|
NiceHash API interface
|
|
|
|
References:
|
|
- https://docs.nicehash.com/main/index.html
|
|
- https://github.com/nicehash/rest-clients-demo/blob/master/python/nicehash.py
|
|
"""
|
|
from datetime import datetime
|
|
from hashlib import sha256
|
|
import hmac
|
|
import json
|
|
import requests_async as requests
|
|
import sys
|
|
from time import mktime
|
|
import uuid
|
|
|
|
from .const import NICEHASH_API_URL
|
|
|
|
|
|
class MiningRigDevice:
|
|
def __init__(self, data):
|
|
self.device_id = data.get("id")
|
|
self.name = data.get("name")
|
|
self.status = data.get("status").get("description")
|
|
self.temperature = int(data.get("temperature"))
|
|
self.load = float(data.get("load"))
|
|
self.rpm = float(data.get("revolutionsPerMinute"))
|
|
self.speeds = data.get("speeds")
|
|
|
|
|
|
class MiningRig:
|
|
def __init__(self, data):
|
|
self.rig_id = data.get("rig_id")
|
|
self.name = data.get("name")
|
|
self.status = data.get("minerStatus")
|
|
self.status_time = data.get("statusTime")
|
|
self.devices = dict()
|
|
self.temperatures = []
|
|
self.profitability = data.get("profitability")
|
|
self.unpaid_amount = data.get("unpaidAmount")
|
|
devices = data.get("devices")
|
|
self.num_devices = len(devices)
|
|
for raw_device in devices:
|
|
device = MiningRigDevice(raw_device)
|
|
self.devices[f"{device.device_id}"] = device
|
|
self.temperatures.append(device.temperature)
|
|
|
|
|
|
class NiceHashPublicClient:
|
|
async def get_exchange_rates(self):
|
|
exchange_data = await self.request("GET", "/main/api/v2/exchangeRate/list")
|
|
return exchange_data["list"]
|
|
|
|
async def request(self, method, path, query=None, body=None):
|
|
url = NICEHASH_API_URL + path
|
|
|
|
if query is not None:
|
|
url += f"?{query}"
|
|
|
|
async with requests.Session() as session:
|
|
if body:
|
|
data = json.dumps(body)
|
|
response = await session.request(method, url, data=data)
|
|
else:
|
|
response = await session.request(method, url)
|
|
|
|
if response.status_code == 200:
|
|
return response.json()
|
|
else:
|
|
err_messages = [str(response.status_code), response.reason]
|
|
if response.content:
|
|
err_messages.append(str(response.content))
|
|
raise Exception(": ".join(err_messages))
|
|
|
|
|
|
class NiceHashPrivateClient:
|
|
def __init__(self, organization_id, key, secret, verbose=False):
|
|
self.organization_id = organization_id
|
|
self.key = key
|
|
self.secret = secret
|
|
self.verbose = verbose
|
|
|
|
async def get_accounts(self):
|
|
return await self.request("GET", "/main/api/v2/accounting/accounts2")
|
|
|
|
async def get_mining_rigs(self):
|
|
return await self.request("GET", "/main/api/v2/mining/rigs2")
|
|
|
|
async def get_mining_rig(self, rig_id):
|
|
return await self.request("GET", f"/main/api/v2/mining/rig2/{rig_id}")
|
|
|
|
async def request(self, method, path, query="", body=None):
|
|
xtime = self.get_epoch_ms_from_now()
|
|
xnonce = str(uuid.uuid4())
|
|
|
|
message = f"{self.key}\00{str(xtime)}\00{xnonce}\00\00{self.organization_id}\00\00{method}\00{path}\00{query}"
|
|
|
|
data = None
|
|
if body:
|
|
data = json.dumps(body)
|
|
message += f"\00{data}"
|
|
|
|
digest = hmac.new(self.secret.encode(), message.encode(), sha256).hexdigest()
|
|
xauth = f"{self.key}:{digest}"
|
|
|
|
headers = {
|
|
"X-Time": str(xtime),
|
|
"X-Nonce": xnonce,
|
|
"X-Auth": xauth,
|
|
"Content-Type": "application/json",
|
|
"X-Organization-Id": self.organization_id,
|
|
"X-Request-Id": str(uuid.uuid4()),
|
|
}
|
|
|
|
async with requests.Session() as session:
|
|
session.headers = headers
|
|
|
|
url = NICEHASH_API_URL + path
|
|
if query:
|
|
url += "?" + query
|
|
|
|
if self.verbose:
|
|
print(method, url)
|
|
|
|
if data:
|
|
response = await session.request(method, url, data=data)
|
|
else:
|
|
response = await session.request(method, url)
|
|
|
|
if response.status_code == 200:
|
|
return response.json()
|
|
else:
|
|
err_messages = [str(response.status_code), response.reason]
|
|
if response.content:
|
|
err_messages.append(str(response.content))
|
|
raise Exception(": ".join(err_messages))
|
|
|
|
def get_epoch_ms_from_now(self):
|
|
now = datetime.now()
|
|
now_ec_since_epoch = mktime(now.timetuple()) + now.microsecond / 1000000.0
|
|
return int(now_ec_since_epoch * 1000)
|