mirror of
https://git.wownero.com/lza_menace/wowstash.git
synced 2024-08-15 00:33:15 +00:00
improving wallet dashboard page, added transfer table, heights, and balances
This commit is contained in:
parent
fb5e93232a
commit
3e0cc311f7
10 changed files with 110 additions and 112 deletions
|
@ -9,13 +9,21 @@ from wowstash.models import User
|
||||||
@wallet_bp.route("/wallet/dashboard")
|
@wallet_bp.route("/wallet/dashboard")
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard():
|
def dashboard():
|
||||||
|
all_transfers = list()
|
||||||
user = User.query.get(current_user.id)
|
user = User.query.get(current_user.id)
|
||||||
wallet_height = wallet.height()['height']
|
wallet_height = wallet.height()['height']
|
||||||
daemon_height = daemon.height()['height']
|
daemon_height = daemon.height()['height']
|
||||||
subaddress = wallet.get_address(0, user.subaddress_index)['addresses'][0]['address']
|
subaddress = wallet.get_address(0, user.subaddress_index)
|
||||||
|
balances = wallet.get_balance(0, user.subaddress_index)
|
||||||
|
transfers = wallet.get_transfers(0, user.subaddress_index)
|
||||||
|
for type in transfers:
|
||||||
|
for tx in transfers[type]:
|
||||||
|
all_transfers.append(tx)
|
||||||
return render_template(
|
return render_template(
|
||||||
"wallet/dashboard.html",
|
"wallet/dashboard.html",
|
||||||
wallet_height=wallet_height,
|
wallet_height=wallet_height,
|
||||||
daemon=daemon_height,
|
daemon_height=daemon_height,
|
||||||
subaddress=subaddress
|
subaddress=subaddress,
|
||||||
|
balances=balances,
|
||||||
|
all_transfers=all_transfers
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,6 +4,7 @@ from flask_session import Session
|
||||||
from flask_bcrypt import Bcrypt
|
from flask_bcrypt import Bcrypt
|
||||||
from flask_login import LoginManager
|
from flask_login import LoginManager
|
||||||
from redis import Redis
|
from redis import Redis
|
||||||
|
from datetime import datetime
|
||||||
from wowstash import config
|
from wowstash import config
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +62,12 @@ def create_app():
|
||||||
from wowstash.models import User
|
from wowstash.models import User
|
||||||
return User.query.get(user_id)
|
return User.query.get(user_id)
|
||||||
|
|
||||||
|
# template filters
|
||||||
|
@app.template_filter('datestamp')
|
||||||
|
def datestamp(s):
|
||||||
|
d = datetime.fromtimestamp(s)
|
||||||
|
return d.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
# Routes
|
# Routes
|
||||||
from wowstash.blueprints.auth import auth_bp
|
from wowstash.blueprints.auth import auth_bp
|
||||||
from wowstash.blueprints.wallet import wallet_bp
|
from wowstash.blueprints.wallet import wallet_bp
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
import operator
|
from six import integer_types
|
||||||
|
from decimal import Decimal
|
||||||
from wowstash import config
|
from wowstash import config
|
||||||
|
|
||||||
|
|
||||||
|
PICOWOW = Decimal('0.00000000001')
|
||||||
|
|
||||||
class JSONRPC(object):
|
class JSONRPC(object):
|
||||||
def __init__(self, proto, host, port, username='', password=''):
|
def __init__(self, proto, host, port, username='', password=''):
|
||||||
self.endpoint = '{}://{}:{}/'.format(
|
self.endpoint = '{}://{}:{}/'.format(
|
||||||
|
@ -53,7 +56,27 @@ class Wallet(JSONRPC):
|
||||||
|
|
||||||
def get_address(self, account_index, subaddress_index):
|
def get_address(self, account_index, subaddress_index):
|
||||||
data = {'account_index': account_index, 'address_index': [subaddress_index]}
|
data = {'account_index': account_index, 'address_index': [subaddress_index]}
|
||||||
return self.make_rpc('get_address', data)
|
subaddress = self.make_rpc('get_address', data)['addresses'][0]['address']
|
||||||
|
return subaddress
|
||||||
|
|
||||||
|
def get_balance(self, account_index, subaddress_index):
|
||||||
|
data = {'account_index': account_index, 'address_indices': [subaddress_index]}
|
||||||
|
_balance = self.make_rpc('get_balance', data)
|
||||||
|
locked = from_atomic(_balance['per_subaddress'][0]['balance'])
|
||||||
|
unlocked = from_atomic(_balance['per_subaddress'][0]['unlocked_balance'])
|
||||||
|
return (float(locked), float(unlocked))
|
||||||
|
|
||||||
|
def get_transfers(self, account_index, subaddress_index):
|
||||||
|
data = {
|
||||||
|
'account_index': account_index,
|
||||||
|
'subaddr_indices': [subaddress_index],
|
||||||
|
'in': True,
|
||||||
|
'out': True,
|
||||||
|
'pending': True,
|
||||||
|
'failed': True,
|
||||||
|
'pool': True
|
||||||
|
}
|
||||||
|
return self.make_rpc('get_transfers', data)
|
||||||
|
|
||||||
|
|
||||||
class Daemon(JSONRPC):
|
class Daemon(JSONRPC):
|
||||||
|
@ -67,6 +90,19 @@ class Daemon(JSONRPC):
|
||||||
return self.make_rpc('get_height', {}, json_rpc=False)
|
return self.make_rpc('get_height', {}, json_rpc=False)
|
||||||
|
|
||||||
|
|
||||||
|
def to_atomic(amount):
|
||||||
|
if not isinstance(amount, (Decimal, float) + integer_types):
|
||||||
|
raise ValueError("Amount '{}' doesn't have numeric type. Only Decimal, int, long and "
|
||||||
|
"float (not recommended) are accepted as amounts.")
|
||||||
|
return int(amount * 10**11)
|
||||||
|
|
||||||
|
def from_atomic(amount):
|
||||||
|
return (Decimal(amount) * PICOWOW).quantize(PICOWOW)
|
||||||
|
|
||||||
|
def as_wownero(amount):
|
||||||
|
return Decimal(amount).quantize(PICOWOW)
|
||||||
|
|
||||||
|
|
||||||
daemon = Daemon(
|
daemon = Daemon(
|
||||||
proto=config.DAEMON_PROTO,
|
proto=config.DAEMON_PROTO,
|
||||||
host=config.DAEMON_HOST,
|
host=config.DAEMON_HOST,
|
||||||
|
|
|
@ -501,3 +501,16 @@ footer ul li a:hover, footer ul li a:focus, footer ul li a:active, footer ul li
|
||||||
header.masthead .header-content-lg {
|
header.masthead .header-content-lg {
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.tx-table {
|
||||||
|
display: inline-table;
|
||||||
|
margin: 0 auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slim {
|
||||||
|
width: 75%;
|
||||||
|
line-break: anywhere;
|
||||||
|
margin: auto;
|
||||||
|
}
|
|
@ -58,46 +58,6 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- <header class="masthead">
|
|
||||||
<div class="container h-100">
|
|
||||||
<div class="row h-100">
|
|
||||||
<div class="col-lg-12 my-auto">
|
|
||||||
<div class="header-content mx-auto">
|
|
||||||
<form method="POST" action="{{ url_for('auth.register') }}">
|
|
||||||
{{ form.csrf_token }}
|
|
||||||
{% for f in form %}
|
|
||||||
{% if f.name != 'csrf_token' %}
|
|
||||||
{% if f.type == 'BooleanField' %}
|
|
||||||
<div class="form-group-span">
|
|
||||||
{{ f.label }}
|
|
||||||
{{ f }}
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="form-group">
|
|
||||||
{{ f.label }}
|
|
||||||
{{ f }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
<ul>
|
|
||||||
{% for field, errors in form.errors.items() %}
|
|
||||||
<li>{{ form[field].label }}: {{ ', '.join(errors) }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
<div>
|
|
||||||
<a href="{{ url_for('meta.faq') }}">FAQ</a> -
|
|
||||||
<a href="{{ url_for('meta.terms') }}">Terms</a> -
|
|
||||||
<a href="{{ url_for('meta.privacy') }}">Privacy</a>
|
|
||||||
</div><br>
|
|
||||||
<input type="submit" value="Register" class="btn btn-link btn-outline btn-xl">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header> -->
|
|
||||||
|
|
||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
|
|
||||||
{% include 'scripts.html' %}
|
{% include 'scripts.html' %}
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
<p>© {{ config.SITE_NAME }} 2020. All Rights Reserved.</p>
|
<p>© {{ config.SITE_NAME }} 2020. All Rights Reserved.</p>
|
||||||
<ul class="list-inline">
|
<ul class="list-inline">
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a href="#">Privacy</a>
|
<a href="{{ url_for('meta.privacy') }}">Privacy</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a href="#">Terms</a>
|
<a href="{{ url_for('meta.terms') }}">Terms</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a href="#">FAQ</a>
|
<a href="{{ url_for('meta.faq') }}">FAQ</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
<link rel="stylesheet" href="/static/vendor/bootstrap/css/bootstrap.min.css">
|
<link rel="stylesheet" href="/static/vendor/bootstrap/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="/static/vendor/font-awesome/css/font-awesome.min.css">
|
<link rel="stylesheet" href="/static/vendor/font-awesome/css/font-awesome.min.css">
|
||||||
<link rel="stylesheet" href="/static/css/new-age.css">
|
<link rel="stylesheet" href="/static/css/main.css">
|
||||||
<link rel="stylesheet" href="/static/css/noty.css">
|
<link rel="stylesheet" href="/static/css/noty.css">
|
||||||
<link rel="stylesheet" href="/static/css/noty-relax.css">
|
<link rel="stylesheet" href="/static/css/noty-relax.css">
|
||||||
<title>{{ config.SITE_NAME }}</title>
|
<title>{{ config.SITE_NAME }}</title>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script src="/static/vendor/jquery/jquery.min.js"></script>
|
<script src="/static/vendor/jquery/jquery.min.js"></script>
|
||||||
<script src="/static/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="/static/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="/static/vendor/jquery-easing/jquery.easing.min.js"></script>
|
<script src="/static/vendor/jquery-easing/jquery.easing.min.js"></script>
|
||||||
<script src="/static/js/new-age.js"></script>
|
<script src="/static/js/main.js"></script>
|
||||||
<script src="/static/js/noty.js"></script>
|
<script src="/static/js/noty.js"></script>
|
||||||
|
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
|
|
|
@ -7,59 +7,20 @@
|
||||||
|
|
||||||
{% include 'navbar.html' %}
|
{% include 'navbar.html' %}
|
||||||
|
|
||||||
<!-- Height ({{ daemon_height }} / {{ wallet_height }})
|
|
||||||
|
|
||||||
Transactions - Send - Receive
|
|
||||||
|
|
||||||
Your Address
|
|
||||||
|
|
||||||
Transaction History
|
|
||||||
|
|
||||||
Balance: -->
|
|
||||||
|
|
||||||
<!-- <header class="masthead">
|
|
||||||
<div class="container h-100">
|
|
||||||
<div class="row h-100">
|
|
||||||
<div class="col-lg-4 my-auto">
|
|
||||||
<div class="header-content mx-auto">
|
|
||||||
<h2 class="mb-5">Welcome Back {{ current_user.email }}</h2>
|
|
||||||
<h3 class="sm">Account Address</h3>
|
|
||||||
<p class="small">address</p>
|
|
||||||
<h3 class="sm">Wallet Persistence</h3>
|
|
||||||
{% if wallet %}
|
|
||||||
<h3 class="sm">Account Balance</h3>
|
|
||||||
<p class="small">{{ h }}</p>
|
|
||||||
<h3 class="sm">Wallet File</h3>
|
|
||||||
<p class="small">{{ config.WALLET_PATH }}</p>
|
|
||||||
{% else %}
|
|
||||||
<h3 class="sm">Wallet Status</h3>
|
|
||||||
<p class="small">Not Connected</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<a href="/account/wallet/" class="btn btn-outline btn-xl">Connect Wallet</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 my-auto">
|
|
||||||
<div class="header-content mx-auto">
|
|
||||||
<h1 class="mb-5">Logs</h1>
|
|
||||||
<h3 class="sm">Transaction Log</h3>
|
|
||||||
<p class="small">asd</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header> -->
|
|
||||||
|
|
||||||
<section class="section2" id="">
|
<section class="section2" id="">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- <div class="section-heading text-center">
|
<div class="section-heading text-center">
|
||||||
<h2>Welcome</h2>
|
<h2>Wallet Info</h2>
|
||||||
<p>Prices and network information</p>
|
</div>
|
||||||
<hr>
|
<div>
|
||||||
</div> -->
|
<p class="slim"><strong>Address:</strong> {{ subaddress }}</p>
|
||||||
|
<p>Balance: {{ balances.1 }} WOW (locked {{ balances.0 }} WOW)</p>
|
||||||
|
<p>Height ({{ wallet_height }} / {{ daemon_height }})</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row fp-row">
|
<div class="row fp-row">
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<a class="btn btn-lg btn-link btn-outline btn-xl" href="#">Transactions</a>
|
<a class="btn btn-lg btn-link btn-outline btn-xl js-scroll-trigger" href="#transfers">Transfers</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<a class="btn btn-lg btn-link btn-outline btn-xl" href="#">Send</a>
|
<a class="btn btn-lg btn-link btn-outline btn-xl" href="#">Send</a>
|
||||||
|
@ -68,26 +29,39 @@
|
||||||
<a class="btn btn-lg btn-link btn-outline btn-xl" href="#">Receive</a>
|
<a class="btn btn-lg btn-link btn-outline btn-xl" href="#">Receive</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row fp-row">
|
|
||||||
<p>Your address: {{ subaddress }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- <section class="section1" id="seed">
|
<section class="section1" id="transfers">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section-heading text-center">
|
<div class="section-heading text-center">
|
||||||
<h2>Manage your funds</h2>
|
<h2>Transfers</h2>
|
||||||
<p class="text-muted">This is your mnemonic seed and account password.</p>
|
<p></p>
|
||||||
<p class="text-muted">Store it securely and never share it with anyone. Use this to log into {{ config.SITE_NAME }}.</p>
|
|
||||||
<p class="text-muted">If you'd like a new seed, refresh the page.</p>
|
<table class="table table-striped table-hover table-responsive table-responsive-sm tx-table">
|
||||||
<hr><br>
|
<tr>
|
||||||
<p>{{ seed }}</p>
|
<th>Date</th>
|
||||||
<hr><br>
|
<th>Type</th>
|
||||||
<a href="/login" class="btn btn-outline-inverse btn-xl">Login</a>
|
<th>Tx ID</th>
|
||||||
|
<th>Amount</th>
|
||||||
|
<th>Confirmations</th>
|
||||||
|
<th>Fee</th>
|
||||||
|
</tr>
|
||||||
|
{% for tx in all_transfers | sort(attribute='timestamp', reverse=True) %}
|
||||||
|
{% if tx.type == 'pool' %}<tr class="table-warning">{% else %}<tr>{% endif %}
|
||||||
|
<td>{{ tx.timestamp | datestamp }}</td>
|
||||||
|
<td>{{ tx.type }}</td>
|
||||||
|
<td><a href="https://wownero.club/transaction/{{ tx.txid }}" target="_blank">{{ tx.txid | truncate(12) }}</a></td>
|
||||||
|
<td>{{ tx.amount / 100000000000 }}</td>
|
||||||
|
<td>{{ tx.confirmations }}</td>
|
||||||
|
<td>{{ tx.fee / 100000000000 }} WOW</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section> -->
|
</section>
|
||||||
|
|
||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue