diff --git a/README.md b/README.md index 3d6b736..20cca07 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ Will be adding client side application to tie the whole thing together. * https://github.com/vtnerd/monero-lws/blob/feature/no_auth_admin/docs/administration.md * https://github.com/monero-project/meta/blob/master/api/lightwallet_rest.md * https://github.com/CryptoGrampy/monero-lws-admin +* https://www.npmjs.com/package/@mymonero/mymonero-wallet-manager/v/3.0.0 +* https://github.com/mymonero/mymonero-utils/tree/master/packages/mymonero-lws-client +* https://github.com/mymonero/mymonero-utils/tree/master/packages/mymonero-monero-client +* https://github.com/mymonero/mymonero-utils/tree/master/packages/mymonero-wallet-manager ## Notes diff --git a/lws-web/lws/factory.py b/lws-web/lws/factory.py index 9410628..ea110af 100644 --- a/lws-web/lws/factory.py +++ b/lws-web/lws/factory.py @@ -1,4 +1,4 @@ -from quart import Quart, redirect +from quart import Quart, redirect, request from quart_auth import ( AuthManager, Unauthorized ) @@ -33,7 +33,7 @@ def create_app(): @app.errorhandler(Unauthorized) async def redirect_to_login(*_): - return redirect("/login") + return redirect(f"/login?next={request.path}") return app bcrypt = Bcrypt(create_app()) \ No newline at end of file diff --git a/lws-web/lws/models.py b/lws-web/lws/models.py index 3392376..8a8696c 100644 --- a/lws-web/lws/models.py +++ b/lws-web/lws/models.py @@ -81,6 +81,26 @@ class Wallet(Model): print(f"Failed to add wallet {self.address}: {e}") return False + def disable_wallet_lws(self): + endpoint = f"{config.LWS_ADMIN_URL}/modify_account_status" + data = { + "auth": self.user.view_key, + "params": { + "addresses": [self.address], + "status": "inactive" + } + } + try: + req = requests.post(endpoint, json=data, timeout=5) + req.raise_for_status() + if req.ok: + return True + return False + except Exception as e: + print(f"Failed to add wallet {self.address}: {e}") + return False + + def get_wallet_info(self): endpoint = f"{config.LWS_URL}/get_address_info" data = { @@ -97,6 +117,22 @@ class Wallet(Model): print(f"Failed to get wallet info {self.address}: {e}") return False + def get_wallet_txes(self): + endpoint = f"{config.LWS_URL}/get_address_txs" + data = { + "address": self.address, + "view_key": self.view_key + } + try: + req = requests.post(endpoint, json=data, timeout=5) + req.raise_for_status() + if req.ok: + return req.json() + return {} + except Exception as e: + print(f"Failed to get wallet info {self.address}: {e}") + return False + def rescan(self): endpoint = f"{config.LWS_ADMIN_URL}/rescan" data = { diff --git a/lws-web/lws/routes/auth.py b/lws-web/lws/routes/auth.py index 860e749..b200df7 100644 --- a/lws-web/lws/routes/auth.py +++ b/lws-web/lws/routes/auth.py @@ -33,6 +33,9 @@ async def login(): await flash("invalid password") return redirect("/login") login_user(AuthUser(user.id)) + nxt = request.args.get("next") + if nxt: + return redirect(nxt) return redirect("/") return await render_template("login.html") diff --git a/lws-web/lws/routes/wallet.py b/lws-web/lws/routes/wallet.py index 8414bc5..3cbd8df 100644 --- a/lws-web/lws/routes/wallet.py +++ b/lws-web/lws/routes/wallet.py @@ -2,7 +2,7 @@ import monero.address from quart import Blueprint, render_template, request, flash, redirect from quart_auth import login_required, current_user -from lws.models import Wallet +from lws.models import Wallet, User bp = Blueprint('wallet', 'wallet') @@ -26,10 +26,10 @@ async def add(): restore_height = form.get("restore_height", 0) valid_view_key = False if not address: - await flash("must provide an LWS admin address") + await flash("must provide an address") return redirect("/wallet/add") if not view_key: - await flash("must provide an LWS admin view_key") + await flash("must provide a view_key") return redirect("/wallet/add") try: _a = monero.address.Address(address) @@ -52,7 +52,7 @@ async def add(): wallet.name = f"wallet-{id}" wallet.add_wallet_lws() await flash("wallet added") - return redirect(f"/wallet/{wallet.id}") + return redirect(f"/wallet/{wallet.id}/rescan") return await render_template("wallet/add.html") @@ -62,7 +62,7 @@ async def show(id): wallet = Wallet.select().where(Wallet.id == id).first() if not wallet: await flash("wallet does not exist") - return redirect("/") + return redirect("/wallets") return await render_template( "wallet/show.html", wallet=wallet @@ -74,21 +74,18 @@ async def rescan(id): wallet = Wallet.select().where(Wallet.id == id).first() if not wallet: await flash("wallet does not exist") - return redirect("/") + return redirect("/wallets") wallet.rescan() return redirect(f"/wallet/{id}") -# / - redirect to /setup if user not setup, to /login if not authenticated -# /setup - first time setup user account, encrypted session -# /login - log into encrypted session -# /wallet/add - add a wallet to LWS -# /wallet/:id - show wallet details (balances, txes, etc) -# /wallet/:id/remove - remove a wallet from LWS -# /wallet/:id/resync - resync wallet -# get_address_info -# get_address_txs -# get_random_outs -# get_unspent_outs -# import_request -# submit_raw_tx \ No newline at end of file +@bp.route("/wallet//disable") +@login_required +async def disable(id): + wallet = Wallet.select().where(Wallet.id == id).first() + if not wallet: + await flash("wallet does not exist") + return redirect("/wallets") + wallet.disable_wallet_lws() + return redirect(f"/wallet/{id}") + diff --git a/lws-web/lws/static/main.css b/lws-web/lws/static/main.css index 81965c8..3a9a904 100644 --- a/lws-web/lws/static/main.css +++ b/lws-web/lws/static/main.css @@ -2,4 +2,25 @@ color: #666; font-size: .9em; user-select: all; +} + +.smol { + font-size: .8em; + color: #666; +} + +.content { + padding-top: 2em; +} + +.subtext { + font-size: 1em; + display: block; + color: #666; +} + +input { + display: block; + padding-bottom: .5em; + margin-bottom: 1em; } \ No newline at end of file diff --git a/lws-web/lws/templates/index.html b/lws-web/lws/templates/index.html index ecc477d..d39a84d 100644 --- a/lws-web/lws/templates/index.html +++ b/lws-web/lws/templates/index.html @@ -1,12 +1,11 @@ {% extends 'includes/base.html' %} {% block content %} -
-

LWS Web Admin

-

LWS Admin: {{ config.LWS_ADMIN_URL }}

-

LWS RPC: {{ config.LWS_URL }}

-

{{ wallets.count() }} wallet{% if wallets.count() > 1 %}s{% endif %} being tracked

- Manage Wallets -
+

LWS Web Admin

+Manage Wallets +
+

LWS Admin: {{ config.LWS_ADMIN_URL }}

+

LWS RPC: {{ config.LWS_URL }}

+

{{ wallets.count() }} wallet{% if wallets.count() > 1 %}s{% endif %} being scanned by LWS

{% endblock %} diff --git a/lws-web/lws/templates/login.html b/lws-web/lws/templates/login.html index cd7c818..ebb39d9 100644 --- a/lws-web/lws/templates/login.html +++ b/lws-web/lws/templates/login.html @@ -1,21 +1,12 @@ {% extends 'includes/base.html' %} {% block content %} -
-
- - - - - -
-
- - +

Login

+
+ + + + + +
{% endblock %} \ No newline at end of file diff --git a/lws-web/lws/templates/setup.html b/lws-web/lws/templates/setup.html index dc142b1..cbab7f8 100644 --- a/lws-web/lws/templates/setup.html +++ b/lws-web/lws/templates/setup.html @@ -1,32 +1,17 @@ {% extends 'includes/base.html' %} {% block content %} -
-

Setup your Monero light wallet

-

The LWS address and view key must be generated from monero-lws using the initialization scripts.

-
- - - - - - - - - -
-
- - +

Setup your Monero LWS

+

The LWS address and view key must be generated from monero-lws using the initialization scripts.

+
+ + + + + + + + + +
{% endblock %} diff --git a/lws-web/lws/templates/utils/mnemonic.html b/lws-web/lws/templates/utils/mnemonic.html index 154ce4d..9b98d08 100644 --- a/lws-web/lws/templates/utils/mnemonic.html +++ b/lws-web/lws/templates/utils/mnemonic.html @@ -1,21 +1,13 @@ {% extends 'includes/base.html' %} {% block content %} -
-

Parse Mnemonic Seed

-
- - - -
-
- +Go Back +

Parse Mnemonic Seed

+
+ + + +
{% if results %}

Results

Public Address: {{ results.public_address() }}

diff --git a/lws-web/lws/templates/wallet/add.html b/lws-web/lws/templates/wallet/add.html index 9168b2a..ec1e44b 100644 --- a/lws-web/lws/templates/wallet/add.html +++ b/lws-web/lws/templates/wallet/add.html @@ -1,28 +1,21 @@ {% extends 'includes/base.html' %} {% block content %} -
-
- - - - - - - - - - - -
-
- +Go Back +

Add a Wallet

+
+ + + + + + + + + + + +
{% endblock %} diff --git a/lws-web/lws/templates/wallet/list.html b/lws-web/lws/templates/wallet/list.html index 411c710..5b1135e 100644 --- a/lws-web/lws/templates/wallet/list.html +++ b/lws-web/lws/templates/wallet/list.html @@ -3,14 +3,9 @@ {% block content %}

Manage Wallets

Add a Wallet -
+
{% for wallet in wallets %}

{{ wallet.id }} - {{ wallet.name }} - {{ wallet.description }} - {{ wallet.date }}

{% endfor %}
- {% endblock %} \ No newline at end of file diff --git a/lws-web/lws/templates/wallet/show.html b/lws-web/lws/templates/wallet/show.html index dfd114f..b09c9e4 100644 --- a/lws-web/lws/templates/wallet/show.html +++ b/lws-web/lws/templates/wallet/show.html @@ -1,27 +1,21 @@ {% extends 'includes/base.html' %} {% block content %} +Go Back {% set info = wallet.get_wallet_info() %}

{{ wallet.name }}

{{ wallet.description }}
{{ wallet.date }}

Restore Height: {{ wallet.restore_height }}

-

Address: {{ wallet.address }}

-

Locked: {{ info['locked_funds'] }}

-

Received: {{ info['total_received'] }}

-

Sent: {{ info['total_sent'] }}

-

Scanned Height: {{ info['scanned_height'] }} ({{ info['blockchain_height'] - info['scanned_height'] }} blocks away from top)

+

Address: {{ wallet.address }}

+

Scanned Height: {{ info['scanned_height'] }} ({{ info['blockchain_height'] - info['scanned_height'] }} blocks away from top)

Chain Height: {{ info['blockchain_height'] }}

Spent Outputs: {{ info['spent_outputs'] | length }}

- - +rescan +{% if request.args.get('disable') %} + are you sure? +{% else %} + disable +{% endif %} {% endblock %} \ No newline at end of file