mirror of
https://git.wownero.com/wownero/wownero-funding-system.git
synced 2024-08-15 00:53:45 +00:00
commit
d42932b3d9
10 changed files with 213 additions and 52 deletions
|
@ -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': []}
|
||||
|
|
|
@ -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
|
||||
return 'Error', 404
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -4,7 +4,8 @@
|
|||
<div class="container api_documentation">
|
||||
<div class="row" style="margin-bottom:4px;">
|
||||
<div class="col-lg-8">
|
||||
<h3>API documentation</h3>
|
||||
<h2>API documentation</h2>
|
||||
<hr>
|
||||
<p>
|
||||
Requests are made using standard HTTP and responses are returned in JSON format.
|
||||
</p>
|
||||
|
|
50
funding/templates/devfund.html
Normal file
50
funding/templates/devfund.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<div class="container page_devfund">
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<h2>Development Fund</h2>
|
||||
<p>
|
||||
Ongoing development is supported by donations and sponsorships *cough*.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row content">
|
||||
<div class="col-lg-8">
|
||||
<hr>
|
||||
<h3>Donating Wownero</h3>
|
||||
<p>
|
||||
Donations may be send to: <code style="word-wrap: break-word">Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP</code>
|
||||
</p>
|
||||
<img style="margin-bottom:20px;" src="/api/1/qr?address=Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP"/>
|
||||
|
||||
<h3>View-only wallet</h3>
|
||||
<p>
|
||||
<code style="word-wrap: break-word">e62e40bfd5ca7e3a7f199602a3c97df511780489e1c1861884b00c28abaea406</code>
|
||||
</p>
|
||||
<h3>Donations</h3>
|
||||
<p>
|
||||
Current balance: <code>{{ txs_in['sum']|round(4) }} WOW</code>
|
||||
</p>
|
||||
<p>
|
||||
50 most recent donations:
|
||||
</p>
|
||||
{% from 'proposal/macros/transaction.html' import tx_item %}
|
||||
|
||||
<ul class="list-group">
|
||||
{% for tx in txs_in['txs'] %}
|
||||
{{ tx_item(tx) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% include 'sidebar.html' %}
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
</div>
|
||||
<!-- /.container -->
|
||||
{% endblock %}
|
|
@ -25,6 +25,9 @@
|
|||
<li class="nav-item">
|
||||
<a class="nav-link" href="/about">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/donate">Donate</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/api">API</a>
|
||||
</li>
|
||||
|
|
28
funding/templates/proposal/macros/transaction.html
Normal file
28
funding/templates/proposal/macros/transaction.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% macro tx_item(tx) %}
|
||||
<li class="list-group-item tx_item">
|
||||
<span class="datetime">
|
||||
{{tx['datetime'].strftime('%Y-%m-%d %H:%M')}}
|
||||
</span>
|
||||
|
||||
<span class="height">
|
||||
<b>Blockheight</b>: {{tx['height']}}</span>
|
||||
<br>
|
||||
|
||||
<a target="_blank" href="https://explore.wownero.com/tx/{{tx['txid']}}">{{tx['txid'][:32]}}...</a>
|
||||
<span class="amount{% if tx['type'] == 'in' %} in{% endif %}">
|
||||
{% if tx['type'] == 'in' %}
|
||||
+
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
|
||||
{{tx['amount_human']|round(3)}} WOW
|
||||
|
||||
{% if 'amount_usd' in tx %}
|
||||
<small style="color: black">
|
||||
➞ $ {{tx['amount_usd']}}
|
||||
</small>
|
||||
{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{% endmacro %}
|
|
@ -165,12 +165,7 @@
|
|||
|
||||
{% include 'comments.html' %}
|
||||
|
||||
<style>
|
||||
#incoming_txs li.list-group-item {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
</style>
|
||||
{% from 'proposal/macros/transaction.html' import tx_item %}
|
||||
|
||||
{% if proposal.balance['txs'] %}
|
||||
<div class="row">
|
||||
|
@ -180,20 +175,7 @@
|
|||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
{% for tx in proposal.balance['txs'] %}
|
||||
<li class="list-group-item">
|
||||
{{tx['datetime'].strftime('%Y-%m-%d %H:%M')}}
|
||||
<span style="float:right"><b>Blockheight</b>: {{tx['height']}}</span>
|
||||
<br>
|
||||
<a target="_blank" href="https://explore.wownero.com/tx/{{tx['txid']}}">{{tx['txid'][:32]}}...</a>
|
||||
<span style="float:right;color:#008926;font-weight:bold;">
|
||||
+ {{tx['amount_human']|round(3)}} WOW
|
||||
{% if 'amount_usd' in tx %}
|
||||
<small style="color: black">
|
||||
➞ $ {{tx['amount_usd']}}
|
||||
</small>
|
||||
{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{{ tx_item(tx) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -203,7 +185,6 @@
|
|||
<!-- /.row -->
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if proposal.spends['txs'] %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
@ -212,20 +193,7 @@
|
|||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
{% for tx in proposal.spends['txs'] %}
|
||||
<li class="list-group-item">
|
||||
{{tx['datetime'].strftime('%Y-%m-%d %H:%M')}}
|
||||
<span style="float:right"><b>Blockheight</b>: {{tx['height']}}</span>
|
||||
<br>
|
||||
<a target="_blank" href="https://explore.wownero.com/tx/{{tx['txid']}}">{{tx['txid'][:32]}}...</a>
|
||||
<span style="float:right;color:#890000;font-weight:bold;">
|
||||
- {{tx['amount_human']|round(3)}} WOW
|
||||
{% if 'amount_usd' in tx %}
|
||||
<small style="color: black">
|
||||
➞ $ {{tx['amount_usd']}}
|
||||
</small>
|
||||
{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{{ tx_item(tx) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in a new issue