setup wallet functionality for posts and extending templates

This commit is contained in:
lza_menace 2020-08-09 22:47:53 -07:00
parent d2f93359b0
commit 2a8d60c36a
8 changed files with 200 additions and 12 deletions

40
README.md Normal file
View file

@ -0,0 +1,40 @@
# SuchWow!
TBD
## Setup
```
# initialize new wallet and retain seed
docker run --rm -it --name suchwow-wallet-init \
-v $(pwd)/data:/root \
lalanza808/wownero \
wownero-wallet-cli \
--daemon-address https://node.suchwow.xyz:443 \
--generate-new-wallet /root/wow \
--password zzzzzz \
# setup rpc process
docker run --rm -d --name suchwow-wallet \
-v $(pwd)/data:/root \
-p 8888:8888 \
lalanza808/wownero \
wownero-wallet-rpc \
--daemon-address https://node.suchwow.xyz:443 \
--wallet-file /root/wow \
--password zzzzzz \
--rpc-bind-port 8888 \
--rpc-bind-ip 0.0.0.0 \
--confirm-external-bind \
--rpc-login xxxx:yyyy \
--log-file /root/rpc.log
# install python dependencies
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# setup secrets in config file outside of git
cp suchwow/config.example.py suchwow/config.py
vim !$
```

View file

@ -4,6 +4,11 @@ OIDC_CLIENT_SECRET = 'xxxxxxxxxx',
OIDC_REDIRECT_URL = 'http://localhost:5000/auth'
SECRET_KEY = 'yyyyyyyyyyyyy',
SESSION_TYPE = 'filesystem'
UPLOAD_FOLDER = '/path/to/the/uploads'
DATA_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
MAX_CONTENT_LENGTH = 16 * 1024 * 1024
MAX_CONTENT_LENGTH = 16 * 1024 * 1024
WALLET_HOST = 'localhost'
WALLET_PORT = 8888
WALLET_PROTO = 'http'
WALLET_USER = 'suchwow'
WALLET_PASS = 'zzzzzzzzzzzzzzz'

View file

@ -1,8 +1,9 @@
from peewee import *
from datetime import datetime
from suchwow import config
db = SqliteDatabase('data/sqlite.db')
db = SqliteDatabase(f'{config.DATA_FOLDER}/db/sqlite.db')
class Post(Model):
id = AutoField()

View file

@ -2,6 +2,7 @@ from os import path
from flask import render_template, Blueprint, request, session, flash
from flask import send_from_directory, redirect, url_for, current_app
from werkzeug.utils import secure_filename
from suchwow import wownero
from suchwow.models import Post
from suchwow.utils.decorators import login_required
from suchwow.utils.helpers import allowed_file
@ -12,8 +13,13 @@ bp = Blueprint("post", "post")
@bp.route("/post/<id>")
def read(id):
if Post.filter(id=id):
post = Post.get(Post.id == id)
return render_template("post/read.html", post=post)
wallet = wownero.Wallet()
post = Post.get(id=id)
if wallet.connected:
address = wallet.addresses(account=post.account_index)[0]
else:
address = "?"
return render_template("post/read.html", post=post, address=address)
else:
return "no meme there brah"
@ -37,15 +43,21 @@ def create():
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
save_path = path.join(current_app.config["UPLOAD_FOLDER"], filename)
save_path_base = path.join(current_app.config["DATA_FOLDER"], "uploads")
save_path = path.join(save_path_base, filename)
file.save(save_path)
# gen wallet
try:
wallet = wownero.Wallet()
account_index = wallet.new_account()
except:
account_index = 0
post = Post(
title=post_title,
text=request.form.get("text", ""),
submitter=session["auth"]["preferred_username"],
image_name=filename,
account_index=0,
account_index=account_index,
address_index=0
)
post.save()
@ -54,4 +66,5 @@ def create():
@bp.route("/uploads/<path:filename>")
def uploaded_file(filename):
return send_from_directory(current_app.config["UPLOAD_FOLDER"], filename)
file_path = path.join(current_app.config["DATA_FOLDER"], "uploads")
return send_from_directory(file_path, filename)

View file

@ -2,7 +2,7 @@
{% block content %}
<div class="container" style="width:40%;text-align:center;">
<div class="container" style="text-align:center;">
<div class="about">
<h1>About</h1>
<p>Post memes! Have fun! <s>Comment and talk shit! Earn WOW!</s> (soon :tm:)</p>

View file

@ -40,6 +40,7 @@
<link href="/static/css/bootstrap-grid.min.css" rel="stylesheet">
<link href="/static/css/bootstrap-reboot.min.css" rel="stylesheet">
<link href="/static/css/wow.css" rel="stylesheet">
<title>SuchWow!</title>
</head>
<body>

View file

@ -2,8 +2,7 @@
{% block content %}
<div class="container" style="width:40%;">
<div class="container">
<div class="post" style="text-align:center;">
<a href="/">< Go Back</a>
{% if post.hidden %}
@ -11,8 +10,20 @@
{% else %}
<h1>{{ post.title }}</h1>
<p class="subtitle">{{ post.text }}</p>
<p class="subtext">Submitted by <i><u>{{ post.submitter }}</u></i> at <i>{{ post.timestamp }}</i></p>
<br>
<img src="{{ url_for('post.uploaded_file', filename=post.image_name) }}" width=500/ style="margin-bottom:1em;border-radius:4px;">
<p class="subtext">Submitted by <i>{{ post.submitter }}</i> at <i>{{ post.timestamp }}</i></p>
<hr>
<p style="word-break:break-all;">Vote for this post by sending WOW to the following address:<br><b><i>{{ address }}</i></b></p>
<hr>
<h4>Comments</h4>
{% if comments %}
{% for comment in comments %}
{{ comment.text }}
{% endfor %}
{% else %}
<p>No comments yet.</p>
{% endif %}
{% endif %}
</div>
</div>

117
suchwow/wownero.py Normal file
View file

@ -0,0 +1,117 @@
import requests
import six
import json
import operator
from suchwow import config
from decimal import Decimal
PICOWOW = Decimal('0.00000000001')
class Wallet(object):
def __init__(self):
self.host = config.WALLET_HOST
self.port = config.WALLET_PORT
self.proto = config.WALLET_PROTO
self.username = config.WALLET_USER
self.password = config.WALLET_PASS
self.endpoint = '{}://{}:{}/json_rpc'.format(
self.proto, self.host, self.port
)
self.auth = requests.auth.HTTPDigestAuth(
self.username, self.password
)
try:
r = self.height()
height = r['height']
self.connected = True
except:
self.connected = False
def make_wallet_rpc(self, method, params={}):
r = requests.get(
self.endpoint,
data=json.dumps({'method': method, 'params': params}),
auth=self.auth
)
# print(r.status_code)
if 'error' in r.json():
return r.json()['error']
else:
return r.json()['result']
def height(self):
return self.make_wallet_rpc('get_height', {})
def spend_key(self):
return self.make_wallet_rpc('query_key', {'key_type': 'spend_key'})['key']
def view_key(self):
return self.make_wallet_rpc('query_key', {'key_type': 'view_key'})['key']
def seed(self):
return self.make_wallet_rpc('query_key', {'key_type': 'mnemonic'})['key']
def accounts(self):
accounts = []
_accounts = self.make_wallet_rpc('get_accounts')
idx = 0
self.master_address = _accounts['subaddress_accounts'][0]['base_address']
for _acc in _accounts['subaddress_accounts']:
assert idx == _acc['account_index']
accounts.append(_acc['account_index'])
idx += 1
return accounts
def new_account(self, label=None):
_account = self.make_wallet_rpc('create_account', {'label': label})
return _account['account_index']
def addresses(self, account, addr_indices=None):
qdata = {'account_index': account}
if addr_indices:
qdata['address_index'] = addr_indices
_addresses = self.make_wallet_rpc('get_address', qdata)
addresses = [None] * (max(map(operator.itemgetter('address_index'), _addresses['addresses'])) + 1)
for _addr in _addresses['addresses']:
addresses[_addr['address_index']] = _addr['address']
return addresses
def new_address(self, account, label=None):
data = {'account_index': account, 'label': label}
_address = self.make_wallet_rpc('create_address', data)
return (_address['address_index'], _address['address'])
def balances(self, account):
data = {'account_index': account}
_balance = self.make_wallet_rpc('get_balance', data)
return (from_atomic(_balance['balance']), from_atomic(_balance['unlocked_balance']))
def transfer(self, dest_address, amount, priority, account):
data = {
'account_index': account,
'destinations': [{'address': dest_address, 'amount': to_atomic(amount)}],
'priority': priority,
'unlock_time': 0,
'get_tx_key': True,
'get_tx_hex': True,
'new_algorithm': True,
'do_not_relay': False,
'ring_size': 22
}
transfer = self.make_wallet_rpc('transfer', data)
return transfer
def to_atomic(amount):
if not isinstance(amount, (Decimal, float) + six.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)