Merge branch 'mempool'

This commit is contained in:
Michał Sałaban 2018-01-25 07:56:53 +01:00
commit a59a8f737a
7 changed files with 94 additions and 33 deletions

View File

@ -30,11 +30,13 @@ class Account(object):
def get_payments(self, payment_id=None): def get_payments(self, payment_id=None):
return self._backend.get_payments(account=self.index, payment_id=payment_id) return self._backend.get_payments(account=self.index, payment_id=payment_id)
def get_transactions_in(self): def get_transactions_in(self, confirmed=True, unconfirmed=False):
return self._backend.get_transactions_in(account=self.index) return self._backend.get_transactions_in(
account=self.index, confirmed=confirmed, unconfirmed=unconfirmed)
def get_transactions_out(self): def get_transactions_out(self, confirmed=True, unconfirmed=True):
return self._backend.get_transactions_out(account=self.index) return self._backend.get_transactions_out(
account=self.index, confirmed=confirmed, unconfirmed=unconfirmed)
def transfer(self, address, amount, def transfer(self, address, amount,
priority=prio.NORMAL, ringsize=5, payment_id=None, unlock_time=0, priority=prio.NORMAL, ringsize=5, payment_id=None, unlock_time=0,

View File

@ -37,6 +37,16 @@ class JSONRPCDaemon(object):
"{status}: {reason}".format(**res), "{status}: {reason}".format(**res),
details=res) details=res)
def get_mempool(self):
res = self.raw_request('/get_transaction_pool', {})
txs = []
for tx in res.get('transactions', []):
txs.append(Transaction(
hash=tx['id_hash'],
fee=from_atomic(tx['fee']),
timestamp=datetime.fromtimestamp(tx['receive_time'])))
return txs
def raw_request(self, path, data): def raw_request(self, path, data):
hdr = {'Content-Type': 'application/json'} hdr = {'Content-Type': 'application/json'}
_log.debug(u"Request: {path}\nData: {data}".format( _log.debug(u"Request: {path}\nData: {data}".format(
@ -103,6 +113,9 @@ class JSONRPCWallet(object):
_log.debug("JSONRPC wallet backend auth: '{user}'/'{stars}'".format( _log.debug("JSONRPC wallet backend auth: '{user}'/'{stars}'".format(
user=user, stars=('*' * len(password)) if password else '')) user=user, stars=('*' * len(password)) if password else ''))
def get_height(self):
return self.raw_request('getheight')['height']
def get_view_key(self): def get_view_key(self):
return self.raw_request('query_key', {'key_type': 'view_key'})['key'] return self.raw_request('query_key', {'key_type': 'view_key'})['key']
@ -167,17 +180,31 @@ class JSONRPCWallet(object):
pmts.append(Payment(**data)) pmts.append(Payment(**data))
return pmts return pmts
def get_transactions_in(self, account=0): def get_transactions_in(self, account=0, confirmed=True, unconfirmed=False):
_transfers = self.raw_request('get_transfers', _txns = self.raw_request('get_transfers',
{'account_index': account, 'in': True, 'out': False, 'pool': False}) {'account_index': account, 'in': confirmed, 'out': False, 'pool': unconfirmed})
txns = _txns.get('in', [])
if unconfirmed:
txns.extend(_txns.get('pool', []))
return [Payment(**self._tx2dict(tx)) for tx in return [Payment(**self._tx2dict(tx)) for tx in
sorted(_transfers.get('in', []), key=operator.itemgetter('timestamp'))] sorted(txns, key=operator.itemgetter('timestamp'))]
def get_transactions_out(self, account=0): def get_transactions_out(self, account=0, confirmed=True, unconfirmed=True):
_transfers = self.raw_request('get_transfers', _txns = self.raw_request('get_transfers',
{'account_index': account, 'in': False, 'out': True, 'pool': False}) {'account_index': account, 'in': False, 'out': confirmed, 'pool': unconfirmed})
txns = _txns.get('out', [])
if unconfirmed:
txns.extend(_txns.get('pool', []))
return [Transfer(**self._tx2dict(tx)) for tx in return [Transfer(**self._tx2dict(tx)) for tx in
sorted(_transfers.get('out', []), key=operator.itemgetter('timestamp'))] sorted(txns, key=operator.itemgetter('timestamp'))]
def get_transaction(self, txhash):
_tx = self.raw_request('get_transfer_by_txid', {'txid': str(txhash)})['transfer']
try:
_class = {'in': Payment, 'out': Transfer}[_tx['type']]
except KeyError:
_class = Transaction
return _class(**self._tx2dict(_tx))
def _tx2dict(self, tx): def _tx2dict(self, tx):
pid = tx.get('payment_id', None) pid = tx.get('payment_id', None)
@ -186,7 +213,7 @@ class JSONRPCWallet(object):
'timestamp': datetime.fromtimestamp(tx['timestamp']) if 'timestamp' in tx else None, 'timestamp': datetime.fromtimestamp(tx['timestamp']) if 'timestamp' in tx else None,
'amount': from_atomic(tx['amount']), 'amount': from_atomic(tx['amount']),
'fee': from_atomic(tx['fee']) if 'fee' in tx else None, 'fee': from_atomic(tx['fee']) if 'fee' in tx else None,
'height': tx.get('height', tx.get('block_height')), 'height': tx.get('height', tx.get('block_height')) or None,
'payment_id': None if pid is None else PaymentID(pid), 'payment_id': None if pid is None else PaymentID(pid),
'note': tx.get('note'), 'note': tx.get('note'),
# NOTE: address will be resolved only after PR#3010 has been merged to Monero # NOTE: address will be resolved only after PR#3010 has been merged to Monero
@ -268,6 +295,7 @@ _err2exc = {
-2: exceptions.WrongAddress, -2: exceptions.WrongAddress,
-4: exceptions.NotEnoughUnlockedMoney, -4: exceptions.NotEnoughUnlockedMoney,
-5: exceptions.WrongPaymentId, -5: exceptions.WrongPaymentId,
-8: exceptions.TransactionNotFound,
-16: exceptions.TransactionNotPossible, -16: exceptions.TransactionNotPossible,
-17: exceptions.NotEnoughMoney, -17: exceptions.NotEnoughMoney,
-20: exceptions.AmountIsZero, -20: exceptions.AmountIsZero,

View File

@ -5,5 +5,11 @@ class Daemon(object):
def get_info(self): def get_info(self):
return self._backend.get_info() return self._backend.get_info()
def get_height(self):
return self._backend.get_info()['height']
def send_transaction(self, blob): def send_transaction(self, blob):
return self._backend.send_transaction(blob) return self._backend.send_transaction(blob)
def get_mempool(self):
return self._backend.get_mempool()

View File

@ -30,3 +30,5 @@ class TransactionBroadcastError(BackendException):
self.details = details self.details = details
super(TransactionBroadcastError, self).__init__(message) super(TransactionBroadcastError, self).__init__(message)
class TransactionNotFound(AccountException):
pass

View File

@ -2,37 +2,44 @@ class Transaction(object):
hash = None hash = None
height = None height = None
timestamp = None timestamp = None
payment_id = '0000000000000000'
amount = None
fee = None fee = None
local_address = None blob = None
def __init__(self, hash=None, **kwargs): def __init__(self, hash=None, **kwargs):
self.hash = hash self.hash = hash
self.height = kwargs.get('height', self.height) self.height = kwargs.get('height', self.height)
self.timestamp = kwargs.get('timestamp', self.timestamp) self.timestamp = kwargs.get('timestamp', self.timestamp)
self.payment_id = kwargs.get('payment_id', self.payment_id)
self.amount = kwargs.get('amount', self.amount)
self.fee = kwargs.get('fee', self.fee) self.fee = kwargs.get('fee', self.fee)
self.local_address = kwargs.get('local_address', self.local_address) self.blob = kwargs.get('blob', self.blob)
def __repr__(self): def __repr__(self):
return self.hash return self.hash
class Payment(Transaction): class LocalTransaction(Transaction):
"""A transaction that concerns local wallet, either incoming or outgoing."""
payment_id = None
amount = None
local_address = None
def __init__(self, **kwargs):
super(LocalTransaction, self).__init__(**kwargs)
self.payment_id = kwargs.get('payment_id', self.payment_id)
self.amount = kwargs.get('amount', self.amount)
self.local_address = kwargs.get('local_address', self.local_address)
class Payment(LocalTransaction):
"""Incoming Transaction""" """Incoming Transaction"""
pass pass
class Transfer(Transaction): class Transfer(LocalTransaction):
"""Outgoing Transaction""" """Outgoing Transaction"""
key = None key = None
blob = None
note = '' note = ''
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(Transfer, self).__init__(**kwargs) super(Transfer, self).__init__(**kwargs)
self.key = kwargs.get('key', self.key) self.key = kwargs.get('key', self.key)
self.note = kwargs.get('note', self.note) self.note = kwargs.get('note', self.note)
self.blob = kwargs.get('blob', self.blob)

View File

@ -1,6 +1,7 @@
from . import address from . import address
from . import prio from . import prio
from . import account from . import account
from . import transaction
class Wallet(object): class Wallet(object):
accounts = None accounts = None
@ -21,6 +22,12 @@ class Wallet(object):
self.accounts.append(_acc) self.accounts.append(_acc)
idx += 1 idx += 1
def get_height(self):
"""
Returns the height of the wallet.
"""
return self._backend.get_height()
def get_view_key(self): def get_view_key(self):
""" """
Returns private view key. Returns private view key.
@ -39,6 +46,15 @@ class Wallet(object):
self.accounts.append(acc) self.accounts.append(acc)
return acc return acc
def get_transaction(self, hash):
return self._backend.get_transaction(hash)
def confirmations(self, txn):
txn = self._backend.get_transaction(txn)
if txn.height is None:
return 0
return max(0, self.get_height() - txn.height)
# Following methods operate on default account (index=0) # Following methods operate on default account (index=0)
def get_balances(self): def get_balances(self):
return self.accounts[0].get_balances() return self.accounts[0].get_balances()
@ -58,11 +74,11 @@ class Wallet(object):
def get_payments(self, payment_id=None): def get_payments(self, payment_id=None):
return self.accounts[0].get_payments(payment_id=payment_id) return self.accounts[0].get_payments(payment_id=payment_id)
def get_transactions_in(self): def get_transactions_in(self, confirmed=True, unconfirmed=False):
return self.accounts[0].get_transactions_in() return self.accounts[0].get_transactions_in(cofirmed=confirmed, unconfirmed=unconfirmed)
def get_transactions_out(self): def get_transactions_out(self, confirmed=True, unconfirmed=True):
return self.accounts[0].get_transactions_out() return self.accounts[0].get_transactions_out(confirmed=confirmed, unconfirmed=unconfirmed)
def transfer(self, address, amount, def transfer(self, address, amount,
priority=prio.NORMAL, ringsize=5, payment_id=None, unlock_time=0, priority=prio.NORMAL, ringsize=5, payment_id=None, unlock_time=0,

View File

@ -36,9 +36,9 @@ _TXHDR = "timestamp height id/hash
" amount fee {dir:95s} payment_id" " amount fee {dir:95s} payment_id"
def tx2str(tx): def tx2str(tx):
return "{time} {height} {hash} {amount:17.12f} {fee:13.12f} {addr} {payment_id}".format( return "{time} {height:7d} {hash} {amount:17.12f} {fee:13.12f} {addr} {payment_id}".format(
time=tx.timestamp.strftime("%d-%m-%y %H:%M:%S") if getattr(tx, 'timestamp', None) else None, time=tx.timestamp.strftime("%d-%m-%y %H:%M:%S") if getattr(tx, 'timestamp', None) else None,
height=tx.height, height=tx.height or 0,
hash=tx.hash, hash=tx.hash,
amount=tx.amount, amount=tx.amount,
fee=tx.fee or 0, fee=tx.fee or 0,
@ -80,26 +80,26 @@ if len(w.accounts) > 1:
addresses = acc.get_addresses() addresses = acc.get_addresses()
print("{num:2d} address(es):".format(num=len(addresses))) print("{num:2d} address(es):".format(num=len(addresses)))
print("\n".join(map(a2str, addresses))) print("\n".join(map(a2str, addresses)))
ins = acc.get_transactions_in() ins = acc.get_transactions_in(unconfirmed=True)
if ins: if ins:
print("\nIncoming transactions:") print("\nIncoming transactions:")
print(_TXHDR.format(dir='received by')) print(_TXHDR.format(dir='received by'))
for tx in ins: for tx in ins:
print(tx2str(tx)) print(tx2str(tx))
outs = acc.get_transactions_out() outs = acc.get_transactions_out(unconfirmed=True)
if outs: if outs:
print("\nOutgoing transactions:") print("\nOutgoing transactions:")
print(_TXHDR.format(dir='sent from')) print(_TXHDR.format(dir='sent from'))
for tx in outs: for tx in outs:
print(tx2str(tx)) print(tx2str(tx))
else: else:
ins = w.get_transactions_in() ins = w.get_transactions_in(unconfirmed=True)
if ins: if ins:
print("\nIncoming transactions:") print("\nIncoming transactions:")
print(_TXHDR.format(dir='received by')) print(_TXHDR.format(dir='received by'))
for tx in ins: for tx in ins:
print(tx2str(tx)) print(tx2str(tx))
outs = w.get_transactions_out() outs = w.get_transactions_out(unconfirmed=True)
if outs: if outs:
print("\nOutgoing transactions:") print("\nOutgoing transactions:")
print(_TXHDR.format(dir='sent from')) print(_TXHDR.format(dir='sent from'))