forked from bbedward/betsy-middleware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdpow_wsclient.py
73 lines (66 loc) · 2.88 KB
/
dpow_wsclient.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
73
import asyncio
import os
import json
from aiohttp import log, ClientSession, WSMsgType, WSMessage, web
class ConnectionClosed(Exception):
pass
class DPOWClient():
NANO_DIFFICULTY_CONST = 'ffffffc000000000'
def __init__(self, dpow_url : str, user : str, key : str, app : web.Application, work_futures: dict, force_nano_difficulty: bool = False, bpow: bool = False):
self.dpow_url = dpow_url
self.user = user
self.key = key
self.id = 0
self.app = app
self.ws = None # None when socket is closed
self.difficulty = DPOWClient.NANO_DIFFICULTY_CONST if force_nano_difficulty else None
self.bpow = bpow
self.work_futures = work_futures
async def open_connection(self):
"""Create the websocket connection to dPOW service"""
async with ClientSession() as session:
async with session.ws_connect(self.dpow_url) as ws:
self.ws = ws
async for msg in ws:
if msg.type == WSMsgType.TEXT:
if msg.data == 'close':
await ws.close()
else:
# Handle Reply
log.server_logger.debug(f'WS Message Received {msg.data}')
msg_json = json.loads(msg.data)
try:
result = self.work_futures[f'{"b" if self.bpow else "d"}{msg_json["id"]}']
if not result.done():
result.set_result(json.loads(msg.data))
except KeyError:
pass
elif msg.type == WSMsgType.CLOSE:
log.server_logger.info('WS Connection closed normally')
break
elif msg.type == WSMsgType.ERROR:
log.server_logger.info('WS Connection closed with error %s', ws.exception())
break
async def get_id(self) -> int:
"""Get ID that should be used for this request"""
self.id += 1
return self.id
async def request_work(self, hash: str, id: int, difficulty: str = None, reward: bool = True):
"""Request work, return ID of the request"""
try:
if self.ws is None or self.ws.closed:
raise ConnectionClosed()
req = {
"user": self.user,
"api_key": self.key,
"hash": hash,
"id": id,
"reward": reward
}
if difficulty is not None:
req['difficulty'] = difficulty
elif self.difficulty is not None:
req['difficulty'] = self.difficulty
await self.ws.send_str(json.dumps(req))
except Exception:
raise ConnectionClosed()