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 @@
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.