2020-08-21 08:39:59 +01:00
|
|
|
import json
|
|
|
|
import requests
|
2020-08-30 20:27:35 +01:00
|
|
|
from six import integer_types
|
|
|
|
from decimal import Decimal
|
2020-08-21 08:39:59 +01:00
|
|
|
from wowstash import config
|
|
|
|
|
2020-08-27 06:50:08 +01:00
|
|
|
|
2020-08-30 20:27:35 +01:00
|
|
|
PICOWOW = Decimal('0.00000000001')
|
|
|
|
|
2020-08-21 08:39:59 +01:00
|
|
|
class JSONRPC(object):
|
|
|
|
def __init__(self, proto, host, port, username='', password=''):
|
|
|
|
self.endpoint = '{}://{}:{}/'.format(
|
|
|
|
proto, host, port
|
|
|
|
)
|
|
|
|
self.auth = requests.auth.HTTPDigestAuth(
|
|
|
|
username, password
|
|
|
|
)
|
|
|
|
|
|
|
|
def make_rpc(self, method, params={}, json_rpc=True):
|
|
|
|
if json_rpc:
|
|
|
|
endpoint = self.endpoint + "json_rpc"
|
|
|
|
else:
|
|
|
|
endpoint = self.endpoint + method
|
|
|
|
|
|
|
|
try:
|
|
|
|
r = requests.get(
|
|
|
|
endpoint,
|
|
|
|
data=json.dumps({'method': method, 'params': params}),
|
|
|
|
auth=self.auth
|
|
|
|
)
|
|
|
|
if 'result' in r.json():
|
|
|
|
return r.json()['result']
|
|
|
|
elif 'error' in r.json():
|
|
|
|
return r.json()['error']
|
|
|
|
else:
|
|
|
|
return r.json()
|
|
|
|
except:
|
|
|
|
return {}
|
|
|
|
|
2020-08-27 06:50:08 +01:00
|
|
|
|
2020-08-21 08:39:59 +01:00
|
|
|
class Wallet(JSONRPC):
|
2020-08-27 06:50:08 +01:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
if 'height' in self.height():
|
|
|
|
self.connected = True
|
|
|
|
else:
|
|
|
|
self.connected = False
|
|
|
|
|
2020-08-21 08:39:59 +01:00
|
|
|
def height(self):
|
|
|
|
return self.make_rpc('get_height', {})
|
|
|
|
|
2020-08-27 06:50:08 +01:00
|
|
|
def new_address(self, account_index=0, label=None):
|
|
|
|
data = {'account_index': account_index, 'label': label}
|
|
|
|
_address = self.make_rpc('create_address', data)
|
|
|
|
return (_address['address_index'], _address['address'])
|
|
|
|
|
|
|
|
def get_address(self, account_index, subaddress_index):
|
|
|
|
data = {'account_index': account_index, 'address_index': [subaddress_index]}
|
2020-08-30 20:27:35 +01:00
|
|
|
subaddress = self.make_rpc('get_address', data)['addresses'][0]['address']
|
|
|
|
return subaddress
|
|
|
|
|
|
|
|
def get_balance(self, account_index, subaddress_index):
|
|
|
|
data = {'account_index': account_index, 'address_indices': [subaddress_index]}
|
|
|
|
_balance = self.make_rpc('get_balance', data)
|
|
|
|
locked = from_atomic(_balance['per_subaddress'][0]['balance'])
|
|
|
|
unlocked = from_atomic(_balance['per_subaddress'][0]['unlocked_balance'])
|
|
|
|
return (float(locked), float(unlocked))
|
|
|
|
|
|
|
|
def get_transfers(self, account_index, subaddress_index):
|
|
|
|
data = {
|
|
|
|
'account_index': account_index,
|
|
|
|
'subaddr_indices': [subaddress_index],
|
|
|
|
'in': True,
|
|
|
|
'out': True,
|
|
|
|
'pending': True,
|
|
|
|
'failed': True,
|
|
|
|
'pool': True
|
|
|
|
}
|
|
|
|
return self.make_rpc('get_transfers', data)
|
2020-08-27 06:50:08 +01:00
|
|
|
|
2020-09-11 21:59:48 +01:00
|
|
|
def transfer(self, account_index, subaddress_index, dest_address, amount):
|
|
|
|
data = {
|
|
|
|
'account_index': account_index,
|
|
|
|
'subaddr_indices': [subaddress_index],
|
|
|
|
'destinations': [{'address': dest_address, 'amount': to_atomic(amount)}],
|
|
|
|
'priority': 0,
|
|
|
|
'unlock_time': 0,
|
|
|
|
'get_tx_key': True,
|
|
|
|
'get_tx_hex': True,
|
|
|
|
'new_algorithm': True,
|
|
|
|
'do_not_relay': False,
|
|
|
|
'ring_size': 22
|
|
|
|
}
|
|
|
|
transfer = self.make_rpc('transfer', data)
|
|
|
|
return transfer
|
|
|
|
|
2020-08-27 06:50:08 +01:00
|
|
|
|
2020-08-21 08:39:59 +01:00
|
|
|
class Daemon(JSONRPC):
|
2020-08-27 06:50:08 +01:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
2020-08-21 08:39:59 +01:00
|
|
|
def info(self):
|
|
|
|
return self.make_rpc('get_info', {}, json_rpc=False)
|
|
|
|
|
|
|
|
def height(self):
|
|
|
|
return self.make_rpc('get_height', {}, json_rpc=False)
|
|
|
|
|
|
|
|
|
2020-08-30 20:27:35 +01:00
|
|
|
def to_atomic(amount):
|
|
|
|
if not isinstance(amount, (Decimal, float) + integer_types):
|
|
|
|
raise ValueError("Amount '{}' doesn't have numeric type. Only Decimal, int, long and "
|
|
|
|
"float (not recommended) are accepted as amounts.")
|
|
|
|
return int(amount * 10**11)
|
|
|
|
|
|
|
|
def from_atomic(amount):
|
|
|
|
return (Decimal(amount) * PICOWOW).quantize(PICOWOW)
|
|
|
|
|
|
|
|
def as_wownero(amount):
|
|
|
|
return Decimal(amount).quantize(PICOWOW)
|
|
|
|
|
|
|
|
|
2020-08-27 06:50:08 +01:00
|
|
|
daemon = Daemon(
|
|
|
|
proto=config.DAEMON_PROTO,
|
|
|
|
host=config.DAEMON_HOST,
|
|
|
|
port=config.DAEMON_PORT,
|
|
|
|
username=config.DAEMON_USER,
|
|
|
|
password=config.DAEMON_PASS
|
|
|
|
)
|
|
|
|
|
|
|
|
wallet = Wallet(
|
|
|
|
proto=config.WALLET_PROTO,
|
|
|
|
host=config.WALLET_HOST,
|
|
|
|
port=config.WALLET_PORT,
|
|
|
|
username=config.WALLET_USER,
|
|
|
|
password=config.WALLET_PASS
|
|
|
|
)
|