From faa1909843c50ff7fc0ad67094827b7f9ad76b18 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 19 Oct 2018 23:42:24 +0200 Subject: [PATCH] Switching to label based accounts --- funding/bin/daemon.py | 131 +++++++++++++++++++++++++++-------- funding/orm/orm.py | 44 +++++------- funding/routes.py | 14 ++-- funding/static/css/wow.css | 2 +- funding/templates/about.html | 3 + 5 files changed, 131 insertions(+), 63 deletions(-) diff --git a/funding/bin/daemon.py b/funding/bin/daemon.py index e185ef4..f21ffee 100644 --- a/funding/bin/daemon.py +++ b/funding/bin/daemon.py @@ -2,6 +2,9 @@ import settings import requests from requests.auth import HTTPDigestAuth +from funding.orm.orm import User + + class Daemon: def __init__(self): self.url = settings.RPC_LOCATION @@ -9,28 +12,24 @@ class Daemon: self.password = settings.RPC_PASSWORD self.headers = {"User-Agent": "Mozilla"} - def create_address(self, label_name): + def create_address(self, account_index, label_name): data = { 'method': 'create_address', - 'params': {'account_index': 0, 'label': label_name}, + 'params': {'account_index': account_index, 'label': 'p_%s' % label_name}, 'jsonrpc': '2.0', 'id': '0' } - return self._make_request(data) + + try: + result = self._make_request(data) + return result['result'] + except: + return def create_account(self, pid): data = { 'method': 'create_account', - 'params': {'label': '%s' % pid}, - 'jsonrpc': '2.0', - 'id': '0' - } - return self._make_request(data) - - def get_address(self, index, proposal_id): - data = { - 'method': 'getaddress', - 'params': {'account_index': proposal_id, 'address_index': '[0]'}, + 'params': {'label': 'p_%s' % pid}, 'jsonrpc': '2.0', 'id': '0' } @@ -40,36 +39,114 @@ class Daemon: except: return - def get_transfers_in(self, index, proposal_id): + def get_accounts(self, proposal_id:int = None): data = { - "method":"get_transfers", - "params": {"pool": True, "in": True, "account_index": proposal_id}, + 'method': 'get_accounts', + 'jsonrpc': '2.0', + 'id': '0' + } + try: + result = self._make_request(data) + result = result['result'] + + if isinstance(proposal_id, int): + account_user = [acc for acc in result.get('subaddress_accounts', []) if acc['label'] == 'p_%d' % proposal_id] + if account_user: + return account_user[0] + else: + return + + return result + except Exception as ex: + return + + def get_address(self, account_index: int, proposal_id: int = None): + data = { + 'method': 'getaddress', + 'params': {'account_index': account_index}, + 'jsonrpc': '2.0', + 'id': '0' + } + try: + result = self._make_request(data) + addresses = result['result']['addresses'] + + if isinstance(proposal_id, int): + address = [addy for addy in addresses if addy['label'] == 'p_%d' % proposal_id] + if address: + return address[0] + else: + return + return addresses + except: + return + + def get_transfers_in(self, proposal): + daemon = Daemon() + + account = daemon.get_accounts(proposal.id) + if not account: + raise Exception('wallet error; pid not found found') + index = account['account_index'] + + address = daemon.get_address(index, proposal_id=proposal.id) + if not address: + print('Could not fetch transfers_in for proposal id %d' % proposal.id) + return {'sum': [], 'txs': []} + + data = { + "method": "get_transfers", + "params": {"pool": True, "in": True, "account_index": index}, "jsonrpc": "2.0", "id": "0", } + data = self._make_request(data) data = data['result'].get('in', []) - for d in data: - d['amount_human'] = float(d['amount'])/1e12 + + # filter by current proposal + txs = [tx for tx in data if tx.get('address') == address['address']] + + for d in txs: + d['amount_human'] = float(d['amount'])/1e11 + return { - 'sum': sum([float(z['amount'])/1e12 for z in data]), - 'txs': data + 'sum': sum([float(z['amount'])/1e11 for z in txs]), + 'txs': txs } - def get_transfers_out(self, index, proposal_id): + def get_transfers_out(self, proposal): + daemon = Daemon() + + account = daemon.get_accounts(proposal.id) + if not account: + raise Exception('wallet error; pid not found found') + index = account['account_index'] + + address = daemon.get_address(index, proposal_id=proposal.id) + if not address: + print('Could not fetch transfers_in for proposal id %d' % proposal.id) + return {'sum': [], 'txs': []} + data = { - "method":"get_transfers", - "params": {"pool": True, "out": True, "account_index": proposal_id}, + "method": "get_transfers", + "params": {"pool": True, "out": True, "account_index": index}, "jsonrpc": "2.0", "id": "0", } + data = self._make_request(data) data = data['result'].get('out', []) - for d in data: - d['amount_human'] = float(d['amount'])/1e12 + + # filter by current proposal + txs = [tx for tx in data if tx.get('address') == address['address']] + + for d in txs: + d['amount_human'] = float(d['amount'])/1e11 + return { - 'sum': sum([float(z['amount'])/1e12 for z in data]), - 'txs': data + 'sum': sum([float(z['amount'])/1e11 for z in txs]), + 'txs': txs } def _make_request(self, data): diff --git a/funding/orm/orm.py b/funding/orm/orm.py index 5c02895..f3c48ce 100644 --- a/funding/orm/orm.py +++ b/funding/orm/orm.py @@ -139,9 +139,9 @@ class Proposal(base): return # check if we have a valid addr_donation generated. if not, make one. - if not result.addr_donation and result.status >= 2: + if not result.addr_donation and result.status == 2: + from funding.bin.daemon import Daemon Proposal.generate_donation_addr(result) - return result @property @@ -192,12 +192,12 @@ class Proposal(base): if not data: from funding.bin.daemon import Daemon try: - data = Daemon().get_transfers_in(index=self.id, proposal_id=self.id) + data = Daemon().get_transfers_in(proposal=self) if not isinstance(data, dict): print('error; get_transfers_in; %d' % self.id) return rtn cache.set(cache_key, data=data, expiry=300) - except: + except Exception as ex: print('error; get_transfers_in; %d' % self.id) return rtn @@ -237,7 +237,7 @@ class Proposal(base): if not data: from funding.bin.daemon import Daemon try: - data = Daemon().get_transfers_out(index=self.id, proposal_id=self.id) + data = Daemon().get_transfers_out(proposal=self) if not isinstance(data, dict): print('error; get_transfers_out; %d' % self.id) return rtn @@ -273,29 +273,21 @@ class Proposal(base): if cls.addr_donation: return cls.addr_donation - try: - addr_donation = Daemon().get_address(index=cls.id, proposal_id=cls.id) - if not isinstance(addr_donation, dict): - raise Exception('get_address, needs dict; %d' % cls.id) - except Exception as ex: - print('error: %s' % str(ex)) - return + # check if the current user has an account in the wallet + account = Daemon().get_accounts(cls.id) + if not account: + account = Daemon().create_account(cls.id) + index = account['account_index'] - if addr_donation.get('address'): - cls.addr_donation = addr_donation['address'] - db_session.commit() - db_session.flush() - return addr_donation['address'] + address = account.get('address') or account.get('base_address') + if not address: + raise Exception('Cannot generate account/address for pid %d' % cls.id) - @staticmethod - def generate_proposal_subaccount(pid): - from funding.bin.daemon import Daemon - - try: - Daemon().create_account(pid) - except Exception as ex: - print('error: %s' % str(ex)) - return + # assign donation address, commit to db + cls.addr_donation = address + db_session.commit() + db_session.flush() + return address @classmethod def find_by_args(cls, status: int = None, cat: str = None, limit: int = 20, offset=0): diff --git a/funding/routes.py b/funding/routes.py index b679434..27a6126 100644 --- a/funding/routes.py +++ b/funding/routes.py @@ -121,8 +121,6 @@ def proposal_api_add(title, content, pid, funds_target, addr_receiving, category except Exception as ex: return make_response(jsonify('markdown error'), 500) - - if pid: p = Proposal.find_by_id(pid=pid) if not p: @@ -149,8 +147,6 @@ def proposal_api_add(title, content, pid, funds_target, addr_receiving, category p.status = status p.last_edited = datetime.now() - - else: try: funds_target = float(funds_target) @@ -162,18 +158,18 @@ def proposal_api_add(title, content, pid, funds_target, addr_receiving, category return make_response(jsonify('Faulty address, should be of length 72'), 500) p = Proposal(headline=title, content=content, category='misc', user=current_user) - proposalID = current_user - addr_donation = Proposal.generate_proposal_subaccount(proposalID) - p.addr_donation = addr_donation p.html = html p.last_edited = datetime.now() p.funds_target = funds_target p.addr_receiving = addr_receiving p.category = category p.status = status - db_session.add(p) - + db_session.add(p) + db_session.commit() + db_session.flush() + + p.addr_donation = Proposal.generate_donation_addr(p) db_session.commit() db_session.flush() diff --git a/funding/static/css/wow.css b/funding/static/css/wow.css index 2756e31..0d3c59d 100644 --- a/funding/static/css/wow.css +++ b/funding/static/css/wow.css @@ -25,7 +25,7 @@ body { .navbar .navbar-brand img#text{ width:235px; height:13px; - margin-top: 8px; + margin-top: 0px; margin-left:8px; display: inline-block; } diff --git a/funding/templates/about.html b/funding/templates/about.html index 4b86737..8e1451b 100644 --- a/funding/templates/about.html +++ b/funding/templates/about.html @@ -25,6 +25,9 @@

When you encounter problems; please visit #wownero on chat.freenode.org

+

+ AEON (camthegeek) has contributed commits to upstream; WOW is grateful. +

{% include 'sidebar.html' %}