def start_wallet(self, user_id): u = User.query.get(user_id) container_name = f'rpc_wallet_{u.id}' volume_name = self.get_user_volume(u.id) command = f"""wownero-wallet-rpc \ --non-interactive \ --rpc-bind-port {self.listen_port} \ --rpc-bind-ip 0.0.0.0 \ --confirm-external-bind \ --wallet-file /wallet/{u.id}.wallet \ --rpc-login {u.id}:{u.wallet_password} \ --password {u.wallet_password} \ --daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \ --daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \ --log-file /wallet/{u.id}-rpc.log """ 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={volume_name: { 'bind': '/wallet', 'mode': 'rw' }}) send_es({'type': 'start_wallet', 'user': u.email}) 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 create_wallet(self, user_id): 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 not self.volume_exists(volume_name): self.client.volumes.create(name=volume_name, driver='local') container = self.client.containers.run( self.wownero_image, command=command, auto_remove=True, name=f'create_wallet_{u.id}', remove=True, detach=True, volumes={volume_name: { 'bind': '/wallet', 'mode': 'rw' }}) send_es({'type': 'create_wallet', 'user': u.email}) return container.short_id
def login(): form = Login() if current_user.is_authenticated: flash('Already registered and authenticated.') return redirect(url_for('wallet.dashboard')) if form.validate_on_submit(): # Check if user doesn't exist user = User.query.filter_by(email=form.email.data).first() if not user: flash('Invalid username or password.') return redirect(url_for('auth.login')) # Check if password is correct password_matches = bcrypt.check_password_hash(user.password, form.password.data) if not password_matches: flash('Invalid username or password.') return redirect(url_for('auth.login')) # Capture event, login user, and redirect to wallet page send_es({'type': 'login', 'user': user.email}) login_user(user) return redirect(url_for('wallet.dashboard')) return render_template("auth/login.html", form=form)
def register(): form = Register() if current_user.is_authenticated: flash('Already registered and authenticated.') return redirect(url_for('wallet.dashboard')) if form.validate_on_submit(): # Check if email already exists user = User.query.filter_by(email=form.email.data).first() if user: flash('This email is already registered.') return redirect(url_for('auth.login')) # Save new user user = User( email=form.email.data, password=bcrypt.generate_password_hash( form.password.data).decode('utf8'), ) db.session.add(user) db.session.commit() # 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 render_template("auth/register.html", form=form)
def logout(): if current_user.is_authenticated: docker.stop_container(current_user.wallet_container) send_es({'type': 'stop_container', 'user': current_user.email}) current_user.clear_wallet_data() send_es({'type': 'logout', 'user': current_user.email}) logout_user() return redirect(url_for('meta.index'))
def send(): send_form = Send() redirect_url = url_for('wallet.dashboard') + '#send' wallet = Wallet(proto='http', host='127.0.0.1', port=current_user.wallet_port, username=current_user.id, password=current_user.wallet_password) if send_form.validate_on_submit(): address = str(send_form.address.data) user = User.query.get(current_user.id) # Check if Wownero wallet is available if wallet.connected is False: flash( 'Wallet RPC interface is unavailable at this time. Try again later.' ) send_es({'type': 'tx_fail_rpc_unavailable', 'user': user.email}) return redirect(redirect_url) # Quick n dirty check to see if address is WOW if len(address) not in [97, 108]: flash('Invalid Wownero address provided.') send_es({'type': 'tx_fail_address_invalid', 'user': user.email}) return redirect(redirect_url) # Check if we're sweeping or not if send_form.amount.data == 'all': tx = wallet.transfer(address, None, 'sweep_all') else: # Make sure the amount provided is a number try: amount = to_atomic(Decimal(send_form.amount.data)) except: flash('Invalid Wownero amount specified.') send_es({'type': 'tx_fail_amount_invalid', 'user': user.email}) return redirect(redirect_url) # Send transfer tx = wallet.transfer(address, amount) # Inform user of result and redirect if 'message' in tx: msg = tx['message'].capitalize() msg_lower = tx['message'].replace(' ', '_').lower() flash(f'There was a problem sending the transaction: {msg}') send_es({'type': f'tx_fail_{msg_lower}', 'user': user.email}) else: flash('Successfully sent transfer.') send_es({'type': 'tx_success', 'user': user.email}) return redirect(redirect_url) else: for field, errors in send_form.errors.items(): flash(f'{send_form[field].label}: {", ".join(errors)}') return redirect(redirect_url)
def delete(): form = Delete() if form.validate_on_submit(): docker.stop_container(current_user.wallet_container) send_es({'type': 'stop_container', 'user': current_user.email}) sleep(1) docker.delete_wallet_data(current_user.id) send_es({'type': 'delete_wallet', 'user': current_user.email}) current_user.clear_wallet_data(reset_password=True, reset_wallet=True) flash('Successfully deleted wallet data') return redirect(url_for('meta.index')) else: flash('Please confirm deletion of the account') return redirect(url_for('wallet.dashboard'))
def dashboard(): send_form = Send() delete_form = Delete() _address_qr = BytesIO() all_transfers = list() wallet = Wallet(proto='http', host='127.0.0.1', port=current_user.wallet_port, 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')) address = wallet.get_address() transfers = wallet.get_transfers() for type in transfers: for tx in transfers[type]: all_transfers.append(tx) balances = wallet.get_balances() 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() send_es({'type': 'load_dashboard', 'user': current_user.email}) return render_template( 'wallet/dashboard.html', transfers=all_transfers, balances=balances, address=address, qrcode=qrcode, send_form=send_form, delete_form=delete_form, user=current_user, seed=seed, spend_key=spend_key, view_key=view_key, )