modify workflow to allow seed restoral

seed-restores
lza_menace 3 years ago
parent a43fae4a1b
commit 13b1b9e1a9

@ -35,7 +35,7 @@ def register():
# Capture event, login user and redirect to wallet page
send_es({'type': 'register', 'user': user.email})
login_user(user)
return redirect(url_for('wallet.dashboard'))
return redirect(url_for('wallet.setup'))
return render_template("auth/register.html", form=form)

@ -13,12 +13,31 @@ from wowstash.library.docker import docker
from wowstash.library.elasticsearch import send_es
from wowstash.library.jsonrpc import Wallet, to_atomic
from wowstash.library.cache import cache
from wowstash.forms import Send, Delete
from wowstash.forms import Send, Delete, Restore
from wowstash.factory import db
from wowstash.models import User
from wowstash import config
@wallet_bp.route('/wallet/setup', methods=['GET', 'POST'])
@login_required
def setup():
if current_user.wallet_created:
return redirect(url_for('wallet.dashboard'))
restore_form = Restore()
if restore_form.validate_on_submit():
if current_user.wallet_created is False:
docker.create_wallet(current_user.id, restore_form.seed.data)
current_user.wallet_created = True
db.session.commit()
return redirect(url_for('wallet.loading'))
else:
return redirect(url_for('wallet.dashboard'))
return render_template(
'wallet/setup.html',
restore_form=restore_form
)
@wallet_bp.route('/wallet/loading')
@login_required
def loading():

@ -1,6 +1,6 @@
from flask_wtf import FlaskForm
from wtforms import StringField, BooleanField
from wtforms.validators import DataRequired
from wtforms.validators import DataRequired, ValidationError
class Register(FlaskForm):
@ -20,3 +20,10 @@ class Send(FlaskForm):
class Delete(FlaskForm):
confirm = BooleanField('Confirm Account and Wallet Deletion:', validators=[DataRequired()], render_kw={"class": "form-control-span"})
class Restore(FlaskForm):
seed = StringField('Seed Phrase', validators=[DataRequired()], render_kw={"placeholder": "25 word mnemonic seed phrase", "class": "form-control"})
def validate_seed(self, seed):
if len(self.seed.data.split()) != 25:
raise ValidationError("Invalid seed provided; must be 25 word format")

@ -19,21 +19,36 @@ class Docker(object):
self.wallet_dir = expanduser(getattr(config, 'WALLET_DIR', '~/data/wallets'))
self.listen_port = 8888
def create_wallet(self, user_id):
def create_wallet(self, user_id, seed=None):
u = User.query.get(user_id)
volume_name = self.get_user_volume(u.id)
u.wallet_password = token_urlsafe(12)
db.session.commit()
command = f"""wownero-wallet-cli \
--generate-new-wallet /wallet/{u.id}.wallet \
--restore-height {daemon.info()['height']} \
--password {u.wallet_password} \
--mnemonic-language English \
--daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \
--daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \
--log-file /wallet/{u.id}-create.log
--command version
"""
if seed:
action = "restore"
command = f"""sh -c "yes '' | wownero-wallet-cli \
--restore-deterministic-wallet \
--generate-new-wallet /wallet/{u.id}.wallet \
--restore-height 0 \
--password {u.wallet_password} \
--daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \
--daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \
--electrum-seed '{seed}' \
--log-file /wallet/{u.id}-{action}.log \
--command refresh"
"""
else:
action = "create"
command = f"""wownero-wallet-cli \
--generate-new-wallet /wallet/{u.id}.wallet \
--restore-height {daemon.info()['height']} \
--password {u.wallet_password} \
--mnemonic-language English \
--daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \
--daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \
--log-file /wallet/{u.id}-{action}.log \
--command version
"""
if not self.volume_exists(volume_name):
self.client.volumes.create(
name=volume_name,
@ -43,7 +58,7 @@ class Docker(object):
self.wownero_image,
command=command,
auto_remove=True,
name=f'create_wallet_{u.id}',
name=f'{action}_wallet_{u.id}',
remove=True,
detach=True,
volumes={
@ -53,7 +68,7 @@ class Docker(object):
}
}
)
send_es({'type': 'create_wallet', 'user': u.email})
send_es({'type': f'{action}_wallet', 'user': u.email})
return container.short_id
def start_wallet(self, user_id):

@ -14,7 +14,7 @@
<div class="header-content mx-auto">
<h1 class="mb-5">Manage your Wownero funds securely and anonymously.</h1>
{% if current_user.is_authenticated %}
<a href="{{ url_for('wallet.dashboard') }}" class="btn btn-outline btn-xl">{% if current_user.wallet_created %}Wallet Dashboard{% else %}Create Wallet{% endif %}</a>
<a href="{{ url_for('wallet.setup') }}" class="btn btn-outline btn-xl">{% if current_user.wallet_created %}Wallet Dashboard{% else %}Setup Wallet{% endif %}</a>
{% else %}
<a href="{{ url_for('auth.register') }}" class="btn btn-outline btn-xl">Register</a>
<a href="{{ url_for('auth.login') }}" class="btn btn-outline btn-xl">Login</a>

@ -19,7 +19,7 @@
<li class="nav-item"><a class="nav-link" href="/#contact">Contact</a></li>
{% endif %}
{% if current_user.is_authenticated %}
<li class="nav-item"><a class="nav-link" href="{{ url_for('wallet.dashboard') }}">Wallet</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('wallet.setup') }}">Wallet</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('auth.logout') }}">Logout</a></li>
{% else %}
<li class="nav-item"><a class="nav-link" href="{{ url_for('auth.login') }}">Login</a></li>

@ -15,7 +15,7 @@
{% else %}
<h2>Your wallet is connecting</h2>
{% endif %}
<p>Go smoke a fatty. This page should auto-refresh when it's ready...if not, click the button below</p>
<p>Go smoke a fatty. This page should auto-refresh when it's ready...if not, click the button below. <br /><br />If you are restoring from a seed, please allow several minutes for the process to complete.</p>
<img src="/static/img/loading-cat.gif" width=300>
<span class="dashboard-buttons">
<div class="col-sm-12 dashboard-button">

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
{% include 'head.html' %}
<body id="page-top">
{% include 'navbar.html' %}
<section class="section2">
<div class="container">
<div class="section-heading text-center">
<h2>Pick An Option</h2>
<p>Alrighty there hoss, pick an option below...</p>
<a class="btn btn-lg btn-link btn-outline btn-xl" href="{{ url_for('wallet.dashboard') }}">Create new wallet</a>
<hr><br /><br />
<form method="POST" action="{{ url_for('wallet.setup') }}" class="send-form">
{{ restore_form.csrf_token }}
{% for f in restore_form %}
{% if f.name != 'csrf_token' %}
<div class="form-group">
{{ f.label }}
{{ f }}
</div>
{% endif %}
{% endfor %}
<ul>
{% for field, errors in restore_form.errors.items() %}
<li>{{ restore_form[field].label }}: {{ ', '.join(errors) }}</li>
{% endfor %}
</ul>
<input type="submit" value="Restore From Seed" class="btn btn-link btn-outline btn-xl">
</form>
</div>
</div>
</section>
{% include 'footer.html' %}
{% include 'scripts.html' %}
</body>
</html>