Skip to content
Snippets Groups Projects
Commit e35c8ef6 authored by inso's avatar inso
Browse files

Refactored money transfers to add lifecycle

parent 36422500
No related branches found
No related tags found
No related merge requests found
......@@ -178,38 +178,13 @@ class Account(object):
sources.append(s)
return sources
def transactions_received(self, community):
received = []
for w in self.wallets:
for tx in w.transactions_received(community):
# Lets remove transactions from our own wallets
pubkeys = [wallet.pubkey for wallet in self.wallets]
if tx[1].issuers[0] not in pubkeys:
received.append(tx)
return received
def transactions_sent(self, community):
def transfers(self, community):
sent = []
for w in self.wallets:
for tx in w.transactions_sent(community):
# Lets remove transactions to our own wallets
pubkeys = [wallet.pubkey for wallet in self.wallets]
outputs = [o for o in tx[1].outputs if o.pubkey not in pubkeys]
if len(outputs) > 0:
sent.append(tx)
for transfer in w.transfers(community):
sent.append(transfer)
return sent
def transactions_awaiting(self, community):
awaiting = []
for w in self.wallets:
for tx in w.transactions_awaiting(community):
# Lets remove transactions to our own wallets
pubkeys = [wallet.pubkey for wallet in self.wallets]
outputs = [o for o in tx[1].outputs if o.pubkey not in pubkeys]
if len(outputs) > 0:
awaiting.append(tx)
return awaiting
def member_of(self, community):
pubkeys = community.members_pubkeys()
if self.pubkey not in pubkeys:
......
'''
Created on 31 janv. 2015
@author: inso
'''
from ucoinpy.api import bma
from ucoinpy.documents.transaction import Transaction
class Transfer(object):
'''
A transaction
'''
TO_SEND = 0
AWAITING = 1
VALIDATED = 2
REFUSED = 3
SENT = 4
DROPPED = 5
def __init__(self, txdoc, state, metadata):
'''
Constructor
'''
self.txdoc = txdoc
self.state = state
self.metadata = metadata
@classmethod
def initiate(cls, txdoc, block, amount):
return cls(txdoc, Transfer.TO_SEND, {'block': block,
'amount': amount,
'issuer': txdoc.issuers[0]})
@classmethod
def create_validated(cls, txdoc, metadata):
return cls(txdoc, Transfer.VALIDATED, metadata)
@classmethod
def load(cls, data):
txdoc = Transaction.from_signed_raw(data['txdoc'])
return cls(txdoc, data['state'], data['metadata'])
def jsonify(self):
return {'txdoc': self.txdoc.signed_raw(),
'state': self.state,
'metadata': self.metadata}
def send(self, community):
try:
community.broadcast(bma.tx.Process,
post_args={'transaction': self.txdoc.signed_raw()})
self.state = Transfer.AWAITING
except ValueError as e:
if '400' in e:
self.state = Transfer.REFUSED
raise
finally:
self.metadata['block'] = community.current_blockid['number']
self.metadata['time'] = community.get_block().time
def check_registered(self, tx, metadata):
if tx.signed_raw() == self.txdoc.signed_raw():
self.state = Transfer.VALIDATED
self.metadata = metadata
if metadata['block'] > self.metadata['block'] + 15:
self.state = Transfer.REFUSED
class Received(Transfer):
def __init__(self, txdoc, metadata):
'''
Constructor
'''
super().__init__(txdoc, Transfer.VALIDATED, metadata)
@classmethod
def load(cls, data):
txdoc = Transaction.from_signed_raw(data['txdoc'])
return cls(txdoc, data['metadata'])
......@@ -10,6 +10,7 @@ from ucoinpy.documents.block import Block
from ucoinpy.documents.transaction import InputSource, OutputSource, Transaction
from ucoinpy.key import SigningKey
from ..tools.exceptions import NotEnoughMoneyError, NoPeerAvailable
from cutecoin.core.transfer import Transfer, Received
import logging
......@@ -18,49 +19,29 @@ class Cache():
self.latest_block = 0
self.wallet = wallet
self.tx_sent = []
self.tx_awaiting = []
self.tx_received = []
self.tx_to_send = []
self._transfers = []
self.available_sources = []
def load_from_json(self, data):
self.tx_received = []
self.tx_sent = []
self.tx_awaiting = []
self._transfers = []
logging.debug(data)
data_received = data['received']
for r in data_received:
self.tx_received.append((r['block'], Transaction.from_signed_raw(r['raw'])))
data_sent = data['sent']
data_sent = data['transfers']
for s in data_sent:
self.tx_sent.append((r['block'], Transaction.from_signed_raw(s['raw'])))
data_awaiting = data['awaiting']
for s in data_awaiting:
self.tx_awaiting.append((r['block'], Transaction.from_signed_raw(s['raw'])))
if s['metadata']['issuer'] == self.wallet.pubkey:
self._transfers.append(Transfer.load(s))
else:
self._transfers.append(Received.load(s))
if 'sources' in data:
data_sources = data['sources']
for s in data_sources:
self.available_sources.append(InputSource.from_inline(s['inline']))
for s in data['sources']:
self.available_sources.append(InputSource.from_inline(s['inline']))
self.latest_block = data['latest_block']
def jsonify(self):
data_received = []
for r in self.tx_received:
data_received.append({'block': r[0], 'raw': r[1].signed_raw()})
data_sent = []
for s in self.tx_sent:
data_sent.append({'block': r[0], 'raw': s[1].signed_raw()})
data_awaiting = []
for s in self.tx_awaiting:
data_awaiting.append({'block': r[0], 'raw': s[1].signed_raw()})
data_transfer = []
for s in self._transfers:
data_transfer.append(s.jsonify())
data_sources = []
for s in self.available_sources:
......@@ -68,19 +49,12 @@ class Cache():
data_sources.append({'inline': "{0}\n".format(s.inline())})
return {'latest_block': self.latest_block,
'received': data_received,
'sent': data_sent,
'awaiting': data_awaiting,
'transfers': data_transfer,
'sources': data_sources}
def latest_sent(self, community):
return self.tx_sent
def awaiting(self, community):
return self.tx_awaiting
def latest_received(self, community):
return self.tx_received
@property
def transfers(self):
return self._transfers
def refresh(self, community):
current_block = 0
......@@ -106,21 +80,44 @@ class Cache():
for block_number in parsed_blocks:
block = community.request(bma.blockchain.Block,
req_args={'number': block_number})
signed_raw = "{0}{1}\n".format(block['raw'], block['signature'])
signed_raw = "{0}{1}\n".format(block['raw'],
block['signature'])
block_doc = Block.from_signed_raw(signed_raw)
metadata = {'block': block_number,
'time': block_doc.time}
for tx in block_doc.transactions:
in_outputs = [o for o in tx.outputs
if o.pubkey == self.wallet.pubkey]
if len(in_outputs) > 0:
self.tx_received.append((block_number, tx))
in_inputs = [i for i in tx.issuers if i == self.wallet.pubkey]
if len(in_inputs) > 0:
# remove from waiting transactions list the one which were
# validated in the blockchain
self.tx_awaiting = [awaiting[1] for awaiting in self.tx_awaiting
if awaiting[1].compact() != tx.compact()]
self.tx_sent.append((block_number, tx))
metadata['issuer'] = tx.issuers[0]
receivers = [o.pubkey for o in tx.outputs
if o.pubkey != metadata['issuer']]
metadata['receiver'] = receivers[0]
in_issuers = len([i for i in tx.issuers
if i == self.wallet.pubkey]) > 0
if in_issuers:
outputs = [o for o in tx.outputs
if o.pubkey != self.wallet.pubkey]
amount = 0
for o in outputs:
amount += o.amount
metadata['amount'] = amount
awaiting = [t for t in self._transfers
if t.state == Transfer.AWAITING]
awaiting_docs = [t.txdoc for t in awaiting]
if tx not in awaiting_docs:
transfer = Transfer.create_validated(tx, metadata)
self._transfers.append(transfer)
for transfer in awaiting:
transfer.check_registered(tx, metadata)
else:
outputs = [o for o in tx.outputs
if o.pubkey == self.wallet.pubkey]
if len(outputs) > 0:
amount = 0
for o in outputs:
amount += o.amount
metadata['amount'] = amount
self._transfers.append(Received(tx, metadata))
if current_block > self.latest_block:
self.available_sources = self.wallet.sources(community)
......@@ -259,13 +256,12 @@ class Wallet(object):
tx.sign([key])
logging.debug("Transaction : {0}".format(tx.signed_raw()))
try:
community.broadcast(bma.tx.Process,
post_args={'transaction': tx.signed_raw()})
block_number = community.current_blockid()['number']
self.caches[community.currency].tx_awaiting.append((block_number, tx))
except:
raise
block_number = community.current_blockid()['number']
transfer = Transfer.initiate(tx, block_number, amount)
transfer.send()
self.caches[community.currency]._transfers.append(transfer)
def sources(self, community):
data = community.request(bma.tx.Sources,
......@@ -275,20 +271,8 @@ class Wallet(object):
tx.append(InputSource.from_bma(s))
return tx
def transactions_awaiting(self, community):
return self.caches[community.currency].awaiting(community)
def transactions_sent(self, community):
return self.caches[community.currency].latest_sent(community)
def transactions_received(self, community):
return self.caches[community.currency].latest_received(community)
def get_text(self, community):
return "%s : \n \
%d %s \n \
%.2f UD" % (self.name, self.value(community), community.currency,
self.relative_value(community))
def transfers(self, community):
return self.caches[community.currency].transfers
def jsonify(self):
return {'walletid': self.walletid,
......
......@@ -5,9 +5,11 @@ Created on 5 févr. 2014
'''
import logging
from ..core.transfer import Transfer, Received
from ..core.person import Person
from ..tools.exceptions import PersonNotFoundError
from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant, QSortFilterProxyModel, QDateTime
from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant, QSortFilterProxyModel, \
QDateTime, QModelIndex
from PyQt5.QtGui import QFont
......@@ -27,12 +29,13 @@ class TxFilterProxyModel(QSortFilterProxyModel):
self.ts_to = ts_to
def filterAcceptsRow(self, sourceRow, sourceParent):
def in_period(tx):
block = self.community.get_block(tx[0])
return (block.mediantime in range(self.ts_from, self.ts_to))
def in_period(date):
return (QDateTime(date).toTime_t() in range(self.ts_from, self.ts_to))
tx = self.sourceModel().transactions[sourceRow]
return in_period(tx)
date_col = self.sourceModel().columns.index('Date')
source_index = self.sourceModel().index(sourceRow, date_col)
date = self.sourceModel().data(source_index, Qt.DisplayRole)
return in_period(date)
def lessThan(self, left, right):
"""
......@@ -70,12 +73,10 @@ class HistoryTableModel(QAbstractTableModel):
self.account = account
self.community = community
self.columns = ('Date', 'UID/Public key', 'Payment', 'Deposit', 'Comment')
self.transactions = self.account.transactions_sent(self.community) + \
self.account.transactions_awaiting(self.community) + \
self.account.transactions_received(self.community)
self.transfers = self.account.transfers(community)
def rowCount(self, parent):
return len(self.transactions)
return len(self.transfers)
def columnCount(self, parent):
return len(self.columns)
......@@ -84,16 +85,10 @@ class HistoryTableModel(QAbstractTableModel):
if role == Qt.DisplayRole:
return self.columns[section]
def data_received(self, tx):
outputs = []
amount = 0
for o in tx[1].outputs:
pubkeys = [w.pubkey for w in self.account.wallets]
if o.pubkey in pubkeys:
outputs.append(o)
amount += o.amount
comment = tx[1].comment
pubkey = tx[1].issuers[0]
def data_received(self, transfer):
amount = transfer.metadata['amount']
comment = transfer.txdoc.comment
pubkey = transfer.metadata['issuer']
try:
#sender = Person.lookup(pubkey, self.community).name
sender = Person.lookup(pubkey, self.community)
......@@ -101,7 +96,7 @@ class HistoryTableModel(QAbstractTableModel):
#sender = "pub:{0}".format(pubkey[:5])
sender = pubkey
date_ts = self.community.get_block(tx[0]).time
date_ts = transfer.metadata['time']
date = QDateTime.fromTime_t(date_ts)
amount_ref = self.account.units_to_ref(amount, self.community)
......@@ -110,17 +105,11 @@ class HistoryTableModel(QAbstractTableModel):
return (date.date(), sender, "", "{0:.2f} {1}".format(amount_ref, ref_name),
comment)
def data_sent(self, tx):
amount = 0
outputs = []
for o in tx[1].outputs:
pubkeys = [w.pubkey for w in self.account.wallets]
if o.pubkey not in pubkeys:
outputs.append(o)
amount += o.amount
comment = tx[1].comment
pubkey = outputs[0].pubkey
def data_sent(self, transfer):
amount = transfer.metadata['amount']
comment = transfer.txdoc.comment
pubkey = transfer.metadata['receiver']
try:
#receiver = Person.lookup(pubkey, self.community).name
receiver = Person.lookup(pubkey, self.community)
......@@ -128,7 +117,7 @@ class HistoryTableModel(QAbstractTableModel):
#receiver = "pub:{0}".format(pubkey[:5])
receiver = pubkey
date_ts = self.community.get_block(tx[0]).time
date_ts = transfer.metadata['time']
date = QDateTime.fromTime_t(date_ts)
amount_ref = self.account.units_to_ref(-amount, self.community)
......@@ -144,17 +133,16 @@ class HistoryTableModel(QAbstractTableModel):
if not index.isValid():
return QVariant()
transfer = self.transfers[row]
if role == Qt.DisplayRole:
if self.transactions[row] in self.account.transactions_sent(self.community) \
or self.transactions[row] in self.account.transactions_awaiting(self.community):
return self.data_sent(self.transactions[row])[col]
if self.transactions[row] in self.account.transactions_received(self.community):
return self.data_received(self.transactions[row])[col]
if type(transfer) is Received:
return self.data_received(transfer)[col]
else:
return self.data_sent(transfer)[col]
if role == Qt.FontRole:
font = QFont()
if self.transactions[row] in self.account.transactions_awaiting(self.community):
if transfer.state == Transfer.AWAITING:
font.setItalic(True)
else:
font.setItalic(False)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment