diff --git a/funding/bin/daemon.py b/funding/bin/daemon.py index cc89bbc..5736a63 100644 --- a/funding/bin/daemon.py +++ b/funding/bin/daemon.py @@ -1,15 +1,25 @@ -import settings +from datetime import datetime + import requests from requests.auth import HTTPDigestAuth +import settings from funding.orm.orm import User class Daemon: - def __init__(self): - self.url = settings.RPC_LOCATION - self.username = settings.RPC_USERNAME - self.password = settings.RPC_PASSWORD + def __init__(self, url=None, username=None, password=None): + self.url = url + self.username = username + self.password = password + + if url is None: + self.url = settings.RPC_LOCATION + if username is None: + self.username = settings.RPC_USERNAME + if password is None: + self.password = settings.RPC_PASSWORD + self.headers = {"User-Agent": "Mozilla"} def create_address(self, account_index, label_name): @@ -82,14 +92,12 @@ class Daemon: return def get_transfers_in(self, proposal): - daemon = Daemon() - - account = daemon.get_accounts(proposal.id) + account = self.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) + address = self.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': []} @@ -115,16 +123,38 @@ class Daemon: 'sum': sum([float(z['amount'])/1e11 for z in txs]), 'txs': txs } - - def get_transfers_out(self, proposal): - daemon = Daemon() - account = daemon.get_accounts(proposal.id) + def get_transfers_in_simple(self): + data = { + "method": "get_transfers", + "params": {"pool": True, "in": True}, + "jsonrpc": "2.0", + "id": "0", + } + + data = self._make_request(data) + data = data['result'] + data = data.get('in', []) + data.get('pool', []) + + for d in data: + d['datetime'] = datetime.fromtimestamp(d['timestamp']) + d['amount_human'] = float(d['amount'])/1e11 + + # most recent tx first + data = sorted(data, key=lambda k: k['datetime'], reverse=True) + + return { + 'sum': sum([float(z['amount'])/1e11 for z in data]), + 'txs': data + } + + def get_transfers_out(self, proposal): + account = self.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) + address = self.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': []} diff --git a/funding/bin/utils_request.py b/funding/bin/utils_request.py index d7e968a..26f1dab 100644 --- a/funding/bin/utils_request.py +++ b/funding/bin/utils_request.py @@ -1,10 +1,11 @@ from datetime import datetime -from flask import session, g +from flask import session, g, request import settings from funding.bin.utils import Summary from funding.factory import app, db_session from funding.orm.orm import Proposal, User, Comment + @app.context_processor def templating(): from flask.ext.login import current_user @@ -19,15 +20,21 @@ def templating(): recent_comments=recent_comments, newest_users=newest_users) + @app.before_request def before_request(): pass + @app.after_request def after_request(res): if hasattr(g, 'funding_prices'): delattr(g, 'funding_prices') res.headers.add('Accept-Ranges', 'bytes') + + if request.full_path.startswith('/api/'): + res.headers.add('Access-Control-Allow-Origin', '*') + if settings.DEBUG: res.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' res.headers['Pragma'] = 'no-cache' @@ -35,10 +42,12 @@ def after_request(res): res.headers['Cache-Control'] = 'public, max-age=0' return res + @app.teardown_appcontext def shutdown_session(**kwargs): db_session.remove() + @app.errorhandler(404) def error(err): - return 'Error', 404 \ No newline at end of file + return 'Error', 404 diff --git a/funding/routes.py b/funding/routes.py index 985c681..d96ca25 100644 --- a/funding/routes.py +++ b/funding/routes.py @@ -1,6 +1,8 @@ from datetime import datetime + from flask import request, redirect, Response, abort, render_template, url_for, flash, make_response, send_from_directory, jsonify from flask.ext.login import login_user , logout_user , current_user, login_required, current_user +from dateutil.parser import parse as dateutil_parse from flask_yoloapi import endpoint, parameter import settings @@ -236,6 +238,34 @@ def proposals(status, page, cat): proposals=proposals, status=status, cat=cat)) +@app.route('/donate') +def donate(): + from funding.bin.daemon import Daemon + from funding.factory import cache, db_session + + data_default = {'sum': 0, 'txs': []} + cache_key = 'devfund_txs_in' + data = cache.get(cache_key) + if not data: + daemon = Daemon(url=settings.RPC_LOCATION_DEVFUND, + username=settings.RPC_USERNAME_DEVFUND, + password=settings.RPC_PASSWORD_DEVFUND + ) + + txs_in = daemon.get_transfers_in_simple() + if not txs_in['txs']: + cache.set(cache_key, data=data_default, expiry=60) + else: + txs_in['txs'] = txs_in['txs'][:50] # truncate to last 50 + cache.set(cache_key, data=txs_in, expiry=60) + else: + for tx in data['txs']: + tx['datetime'] = dateutil_parse(tx['datetime']) + txs_in = data + + return make_response(render_template('devfund.html', txs_in=txs_in)) + + @app.route('/register', methods=['GET', 'POST']) def register(): if settings.USER_REG_DISABLED: diff --git a/funding/static/css/wow.css b/funding/static/css/wow.css index 50151aa..e6b5d74 100644 --- a/funding/static/css/wow.css +++ b/funding/static/css/wow.css @@ -616,4 +616,40 @@ ul.b { .table-proposal tr { background: #00000005; +} + +.tx_item { + padding-top: 4px; + padding-bottom: 4px; + background: #ffffff80; +} + +.tx_item .amount { + float:right; + font-weight:bold; + color:#890000; +} + +.tx_item .amount.in { + color:#008926; +} + +.tx_item .datetime { + font-size: 14px; + color: #999; +} + +.tx_item .height { + float:right +} + +.tx_item .height b { + font-size:14px; +} + +.container>.content h1, +.container>.content h2, +.container>.content h3, +.container>.content h4{ + margin-bottom:20px; } \ No newline at end of file diff --git a/funding/templates/api.html b/funding/templates/api.html index 753765b..4a5e504 100644 --- a/funding/templates/api.html +++ b/funding/templates/api.html @@ -4,7 +4,8 @@
-

API documentation

+

API documentation

+

Requests are made using standard HTTP and responses are returned in JSON format.

diff --git a/funding/templates/devfund.html b/funding/templates/devfund.html new file mode 100644 index 0000000..bf590b9 --- /dev/null +++ b/funding/templates/devfund.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} +{% block content %} + +
+
+
+

Development Fund

+

+ Ongoing development is supported by donations and sponsorships *cough*. +

+
+
+
+
+
+

Donating Wownero

+

+ Donations may be send to: Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP +

+ + +

View-only wallet

+

+ e62e40bfd5ca7e3a7f199602a3c97df511780489e1c1861884b00c28abaea406 +

+

Donations

+

+ Current balance: {{ txs_in['sum']|round(4) }} WOW +

+

+ 50 most recent donations: +

+ {% from 'proposal/macros/transaction.html' import tx_item %} + +
    + {% for tx in txs_in['txs'] %} + {{ tx_item(tx) }} + {% endfor %} +
+
+ + {% include 'sidebar.html' %} + +
+ +
+ +
+ +{% endblock %} diff --git a/funding/templates/navbar.html b/funding/templates/navbar.html index da1f024..a231ed9 100644 --- a/funding/templates/navbar.html +++ b/funding/templates/navbar.html @@ -25,6 +25,9 @@ + diff --git a/funding/templates/proposal/macros/transaction.html b/funding/templates/proposal/macros/transaction.html new file mode 100644 index 0000000..3b2866e --- /dev/null +++ b/funding/templates/proposal/macros/transaction.html @@ -0,0 +1,28 @@ +{% macro tx_item(tx) %} +
  • + + {{tx['datetime'].strftime('%Y-%m-%d %H:%M')}} + + + + Blockheight: {{tx['height']}} +
    + + {{tx['txid'][:32]}}... + + {% if tx['type'] == 'in' %} + + + {% else %} + - + {% endif %} + + {{tx['amount_human']|round(3)}} WOW + + {% if 'amount_usd' in tx %} + + ➞ $ {{tx['amount_usd']}} + + {% endif %} + +
  • +{% endmacro %} diff --git a/funding/templates/proposal/proposal.html b/funding/templates/proposal/proposal.html index bcd7cec..bff2ed4 100644 --- a/funding/templates/proposal/proposal.html +++ b/funding/templates/proposal/proposal.html @@ -165,12 +165,7 @@ {% include 'comments.html' %} - + {% from 'proposal/macros/transaction.html' import tx_item %} {% if proposal.balance['txs'] %}
    @@ -180,20 +175,7 @@
      {% for tx in proposal.balance['txs'] %} -
    • - {{tx['datetime'].strftime('%Y-%m-%d %H:%M')}} - Blockheight: {{tx['height']}} -
      - {{tx['txid'][:32]}}... - - + {{tx['amount_human']|round(3)}} WOW - {% if 'amount_usd' in tx %} - - ➞ $ {{tx['amount_usd']}} - - {% endif %} - -
    • + {{ tx_item(tx) }} {% endfor %}
    @@ -203,7 +185,6 @@ {% endif %} - {% if proposal.spends['txs'] %}
    @@ -212,20 +193,7 @@
      {% for tx in proposal.spends['txs'] %} -
    • - {{tx['datetime'].strftime('%Y-%m-%d %H:%M')}} - Blockheight: {{tx['height']}} -
      - {{tx['txid'][:32]}}... - - - {{tx['amount_human']|round(3)}} WOW - {% if 'amount_usd' in tx %} - - ➞ $ {{tx['amount_usd']}} - - {% endif %} - -
    • + {{ tx_item(tx) }} {% endfor %}
    diff --git a/settings.py_example b/settings.py_example index 37c6c2d..0132121 100644 --- a/settings.py_example +++ b/settings.py_example @@ -39,6 +39,12 @@ RPC_LOCATION = "http://{host}:{rpc_port}/json_rpc".format(host=RPC_HOST, rpc_por RPC_USERNAME = "" RPC_PASSWORD = "" +RPC_HOST_DEVFUND = '127.0.0.1' +RPC_PORT_DEVFUND = '45679' +RPC_LOCATION_DEVFUND = "http://{host}:{rpc_port}/json_rpc".format(host=RPC_HOST, rpc_port=RPC_PORT) +RPC_USERNAME_DEVFUND = None +RPC_PASSWORD_DEVFUND = None + FUNDING_CATEGORIES = [ 'wallets', 'marketing',