diff --git a/wowstash/blueprints/auth/routes.py b/wowstash/blueprints/auth/routes.py index c8cf5f0..7a7b7c7 100644 --- a/wowstash/blueprints/auth/routes.py +++ b/wowstash/blueprints/auth/routes.py @@ -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) diff --git a/wowstash/blueprints/wallet/routes.py b/wowstash/blueprints/wallet/routes.py index b26937a..1429c58 100644 --- a/wowstash/blueprints/wallet/routes.py +++ b/wowstash/blueprints/wallet/routes.py @@ -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(): diff --git a/wowstash/forms.py b/wowstash/forms.py index 65578fa..06511e8 100644 --- a/wowstash/forms.py +++ b/wowstash/forms.py @@ -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") diff --git a/wowstash/library/docker.py b/wowstash/library/docker.py index fc381ba..fad2e7f 100644 --- a/wowstash/library/docker.py +++ b/wowstash/library/docker.py @@ -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): diff --git a/wowstash/templates/meta/index.html b/wowstash/templates/meta/index.html index edb0f2b..d849882 100644 --- a/wowstash/templates/meta/index.html +++ b/wowstash/templates/meta/index.html @@ -14,7 +14,7 @@

Manage your Wownero funds securely and anonymously.

{% if current_user.is_authenticated %} - {% if current_user.wallet_created %}Wallet Dashboard{% else %}Create Wallet{% endif %} + {% if current_user.wallet_created %}Wallet Dashboard{% else %}Setup Wallet{% endif %} {% else %} Register Login diff --git a/wowstash/templates/navbar.html b/wowstash/templates/navbar.html index 72eb101..79a632d 100644 --- a/wowstash/templates/navbar.html +++ b/wowstash/templates/navbar.html @@ -19,7 +19,7 @@ {% endif %} {% if current_user.is_authenticated %} - + {% else %} diff --git a/wowstash/templates/wallet/loading.html b/wowstash/templates/wallet/loading.html index c617c52..0148065 100644 --- a/wowstash/templates/wallet/loading.html +++ b/wowstash/templates/wallet/loading.html @@ -15,7 +15,7 @@ {% else %}

Your wallet is connecting

{% endif %} -

Go smoke a fatty. This page should auto-refresh when it's ready...if not, click the button below

+

Go smoke a fatty. This page should auto-refresh when it's ready...if not, click the button below.

If you are restoring from a seed, please allow several minutes for the process to complete.

diff --git a/wowstash/templates/wallet/setup.html b/wowstash/templates/wallet/setup.html new file mode 100644 index 0000000..fbc2fa2 --- /dev/null +++ b/wowstash/templates/wallet/setup.html @@ -0,0 +1,47 @@ + + + + {% include 'head.html' %} + + + + {% include 'navbar.html' %} + +
+
+
+

Pick An Option

+

Alrighty there hoss, pick an option below...

+ + Create new wallet + +


+ +
+ {{ restore_form.csrf_token }} + {% for f in restore_form %} + {% if f.name != 'csrf_token' %} +
+ {{ f.label }} + {{ f }} +
+ {% endif %} + {% endfor %} +
    + {% for field, errors in restore_form.errors.items() %} +
  • {{ restore_form[field].label }}: {{ ', '.join(errors) }}
  • + {% endfor %} +
+ +
+
+
+
+ + {% include 'footer.html' %} + + {% include 'scripts.html' %} + + + +