diff --git a/wowstash/blueprints/wallet/routes.py b/wowstash/blueprints/wallet/routes.py index 4e3de0f..337b5df 100644 --- a/wowstash/blueprints/wallet/routes.py +++ b/wowstash/blueprints/wallet/routes.py @@ -39,6 +39,10 @@ def dashboard(): username=current_user.id, password=current_user.wallet_password ) + if not docker.container_exists(current_user.wallet_container): + current_user.clear_wallet_data() + return redirect(url_for('wallet.loading')) + if not wallet.connected: return redirect(url_for('wallet.loading')) @@ -51,6 +55,9 @@ def dashboard(): qr_uri = f'wownero:{address}?tx_description={current_user.email}' address_qr = qrcode_make(qr_uri).save(_address_qr) qrcode = b64encode(_address_qr.getvalue()).decode() + seed = wallet.seed() + spend_key = wallet.spend_key() + view_key = wallet.view_key() return render_template( 'wallet/dashboard.html', transfers=all_transfers, @@ -58,7 +65,10 @@ def dashboard(): address=address, qrcode=qrcode, send_form=send_form, - user=current_user + user=current_user, + seed=seed, + spend_key=spend_key, + view_key=view_key, ) @wallet_bp.route('/wallet/connect') diff --git a/wowstash/library/docker.py b/wowstash/library/docker.py index fde56da..3240895 100644 --- a/wowstash/library/docker.py +++ b/wowstash/library/docker.py @@ -1,5 +1,5 @@ from docker import from_env, APIClient -from docker.errors import NotFound +from docker.errors import NotFound, NullResource, APIError from socket import socket from wowstash import config from wowstash.models import User @@ -42,6 +42,7 @@ class Docker(object): def start_wallet(self, user_id): u = User.query.get(user_id) + container_name = f'start_wallet_{u.id}' command = f"""wownero-wallet-rpc \ --non-interactive \ --rpc-bind-port {self.listen_port} \ @@ -54,24 +55,29 @@ class Docker(object): --daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \ --log-file /wallet/{u.id}-rpc.log """ - container = self.client.containers.run( - self.wownero_image, - command=command, - auto_remove=True, - name=f'start_wallet_{u.id}', - remove=True, - detach=True, - ports={ - f'{self.listen_port}/tcp': ('127.0.0.1', None) - }, - volumes={ - f'{self.wallet_dir}/{u.id}': { - 'bind': '/wallet', - 'mode': 'rw' + try: + container = self.client.containers.run( + self.wownero_image, + command=command, + auto_remove=True, + name=container_name, + remove=True, + detach=True, + ports={ + f'{self.listen_port}/tcp': ('127.0.0.1', None) + }, + volumes={ + f'{self.wallet_dir}/{u.id}': { + 'bind': '/wallet', + 'mode': 'rw' + } } - } - ) - return container.short_id + ) + return container.short_id + except APIError as e: + if str(e).startswith('409'): + container = self.client.containers.get(container_name) + return container.short_id def get_port(self, container_id): client = APIClient() @@ -85,6 +91,8 @@ class Docker(object): return True except NotFound: return False + except NullResource: + return False def stop_container(self, container_id): if self.container_exists(container_id): diff --git a/wowstash/library/jsonrpc.py b/wowstash/library/jsonrpc.py index 72a475f..bb6d9e8 100644 --- a/wowstash/library/jsonrpc.py +++ b/wowstash/library/jsonrpc.py @@ -49,6 +49,15 @@ class Wallet(JSONRPC): def height(self): return self.make_rpc('get_height', {}) + def spend_key(self): + return self.make_rpc('query_key', {'key_type': 'spend_key'})['key'] + + def view_key(self): + return self.make_rpc('query_key', {'key_type': 'view_key'})['key'] + + def seed(self): + return self.make_rpc('query_key', {'key_type': 'mnemonic'})['key'] + def new_address(self, account_index=0, label=None): data = {'account_index': account_index, 'label': label} _address = self.make_rpc('create_address', data) diff --git a/wowstash/templates/wallet/dashboard.html b/wowstash/templates/wallet/dashboard.html index dc7aa39..0c8db66 100644 --- a/wowstash/templates/wallet/dashboard.html +++ b/wowstash/templates/wallet/dashboard.html @@ -20,10 +20,13 @@
{{ balances[1] | from_atomic }} WOW ({{ balances[0] | from_atomic }} locked)
@@ -96,6 +99,24 @@ +You need to save the secrets below; write them down on a physical medium and keep it in a safe location. These can be used to restore your funds to another device in the future.
+{{ seed }}
+{{ spend_key }}
+{{ view_key }}
+