Browse Source

refactor: breaking bad

fee_issues
Eneko Illarramendi 5 years ago
parent
commit
49addb8d56
  1. 8
      .env.example
  2. 2
      Pipfile
  3. 75
      lnbits/__init__.py
  4. 5
      lnbits/core/__init__.py
  5. 4
      lnbits/core/crud.py
  6. 0
      lnbits/core/migrations/0001_initial.py
  7. 0
      lnbits/core/migrations/__init__.py
  8. 13
      lnbits/core/static/js/lnurl.js
  9. 30
      lnbits/core/templates/core/index.html
  10. 22
      lnbits/core/templates/core/lnurl.html
  11. 0
      lnbits/core/views/__init__.py
  12. 2
      lnbits/core/views/api.py
  13. 2
      lnbits/core/views/generic.py
  14. 55
      lnbits/core/views/lnurl.py
  15. 4
      lnbits/settings.py
  16. 6
      lnbits/templates/base.html
  17. 15
      lnbits/templates/lnurl.html
  18. 4
      requirements.txt

8
.env.example

@ -1,6 +1,10 @@
FLASK_APP=lnbits
FLASK_ENV=development
LNBITS_WITH_ONION=0
LNBITS_DEFAULT_WALLET_NAME="LNbits wallet"
LNBITS_FEE_RESERVE=0
LND_API_ENDPOINT=https://mylnd.io/rest/
LND_ADMIN_MACAROON=LND_ADMIN_MACAROON
LND_INVOICE_MACAROON=LND_INVOICE_MACAROON
@ -15,9 +19,7 @@ OPENNODE_ADMIN_KEY=OPENNODE_ADMIN_KEY
OPENNODE_INVOICE_KEY=OPENNODE_INVOICE_KEY
LNPAY_API_ENDPOINT=https://lnpay.co/v1/
LNPAY_API_KEY=LNPAY_API_KEY
LNPAY_ADMIN_KEY=LNPAY_ADMIN_KEY
LNPAY_INVOICE_KEY=LNPAY_INVOICE_KEY
LNPAY_READ_KEY=LNPAY_READ_KEY
LNPAY_API_KEY=LNPAY_API_KEY
FEE_RESERVE=0

2
Pipfile

@ -12,6 +12,8 @@ lnurl = "*"
flask = "*"
flask-assets = "*"
flask-compress = "*"
flask-limiter = "*"
flask-seasurf = "*"
flask-talisman = "*"
gevent = "*"
greenlet = "*"

75
lnbits/__init__.py

@ -1,18 +1,14 @@
import importlib
import json
import requests
import uuid
from flask import Flask, redirect, render_template, request, url_for
from flask import Flask
from flask_assets import Environment, Bundle
from flask_compress import Compress
from flask_talisman import Talisman
from lnurl import Lnurl, LnurlWithdrawResponse
from os import getenv
from .core import core_app
from .db import init_databases, open_db
from .db import init_databases
from .helpers import ExtensionManager, megajson
from .settings import WALLET, DEFAULT_USER_WALLET_NAME
app = Flask(__name__)
@ -25,6 +21,7 @@ valid_extensions = [ext for ext in ExtensionManager().extensions if ext.is_valid
Compress(app)
Talisman(
app,
force_https=getenv("LNBITS_WITH_ONION", 0) == 0,
content_security_policy={
"default-src": [
"'self'",
@ -81,69 +78,5 @@ def init():
init_databases()
# vvvvvvvvvvvvvvvvvvvvvvvvvvv
# move the rest to `core_app`
# vvvvvvvvvvvvvvvvvvvvvvvvvvv
# vvvvvvvvvvvvvvvvvvvvvvvvvvv
@app.route("/lnurl")
def lnurl():
lnurl = request.args.get("lightning")
return render_template("lnurl.html", lnurl=lnurl)
@app.route("/lnurlwallet")
def lnurlwallet():
lnurl = Lnurl(request.args.get("lightning"))
r = requests.get(lnurl.url)
if not r.ok:
return redirect(url_for("home"))
data = json.loads(r.text)
if data.get("status") == "ERROR":
return redirect(url_for("home"))
withdraw_res = LnurlWithdrawResponse(**data)
_, pay_hash, pay_req = WALLET.create_invoice(withdraw_res.max_sats, "LNbits lnurl funding")
r = requests.get(
withdraw_res.callback.base,
params={**withdraw_res.callback.query_params, **{"k1": withdraw_res.k1, "pr": pay_req}},
)
if not r.ok:
return redirect(url_for("home"))
data = json.loads(r.text)
for i in range(10):
r = WALLET.get_invoice_status(pay_hash).raw_response
if not r.ok:
continue
data = r.json()
break
with open_db() as db:
wallet_id = uuid.uuid4().hex
user_id = uuid.uuid4().hex
wallet_name = DEFAULT_USER_WALLET_NAME
adminkey = uuid.uuid4().hex
inkey = uuid.uuid4().hex
db.execute("INSERT INTO accounts (id) VALUES (?)", (user_id,))
db.execute(
"INSERT INTO wallets (id, name, user, adminkey, inkey) VALUES (?, ?, ?, ?, ?)",
(wallet_id, wallet_name, user_id, adminkey, inkey),
)
db.execute(
"INSERT INTO apipayments (payhash, amount, wallet, pending, memo) VALUES (?, ?, ?, 0, ?)",
(pay_hash, withdraw_res.max_sats * 1000, wallet_id, "LNbits lnurl funding",),
)
return redirect(url_for("wallet", usr=user_id, wal=wallet_id))
if __name__ == '__main__':
app.run()

5
lnbits/core/__init__.py

@ -4,5 +4,6 @@ from flask import Blueprint
core_app = Blueprint("core", __name__, template_folder="templates", static_folder="static")
from .views_api import * # noqa
from .views import * # noqa
from .views.api import * # noqa
from .views.generic import * # noqa
from .views.lnurl import * # noqa

4
lnbits/core/crud.py

@ -1,7 +1,7 @@
from uuid import uuid4
from lnbits.db import open_db
from lnbits.settings import DEFAULT_USER_WALLET_NAME, FEE_RESERVE
from lnbits.settings import DEFAULT_WALLET_NAME, FEE_RESERVE
from typing import List, Optional
from .models import User, Wallet, Payment
@ -71,7 +71,7 @@ def create_wallet(*, user_id: str, wallet_name: Optional[str]) -> Wallet:
INSERT INTO wallets (id, name, user, adminkey, inkey)
VALUES (?, ?, ?, ?, ?)
""",
(wallet_id, wallet_name or DEFAULT_USER_WALLET_NAME, user_id, uuid4().hex, uuid4().hex),
(wallet_id, wallet_name or DEFAULT_WALLET_NAME, user_id, uuid4().hex, uuid4().hex),
)
return get_wallet(wallet_id=wallet_id)

0
lnbits/core/migrations/0001_initial.py

0
lnbits/core/migrations/__init__.py

13
lnbits/core/static/js/lnurl.js

@ -0,0 +1,13 @@
new Vue({
el: '#vue',
mixins: [windowMixin],
methods: {
notify: function () {
this.$q.notify({
timeout: 0,
message: 'Processing...',
icon: null
});
}
}
});

30
lnbits/core/templates/core/index.html

@ -15,20 +15,22 @@
<div class="row q-col-gutter-md justify-between">
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<q-card>
<q-card-section>
<q-form class="q-gutter-md">
<q-input filled dense
v-model="walletName"
label="Name your LNbits wallet *"
></q-input>
<q-btn unelevated
color="deep-purple"
:disable="walletName == ''"
@click="createWallet">Add a new wallet</q-btn>
</q-form>
</q-card-section>
</q-card>
{% block call_to_action %}
<q-card>
<q-card-section>
<q-form class="q-gutter-md">
<q-input filled dense
v-model="walletName"
label="Name your LNbits wallet *"
></q-input>
<q-btn unelevated
color="deep-purple"
:disable="walletName == ''"
@click="createWallet">Add a new wallet</q-btn>
</q-form>
</q-card-section>
</q-card>
{% endblock %}
<q-card>
<q-card-section>

22
lnbits/core/templates/core/lnurl.html

@ -0,0 +1,22 @@
{% extends "core/index.html" %}
{% block scripts %}
{% assets filters='rjsmin', output='__bundle__/core/lnurl.js',
'core/js/lnurl.js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% endblock %}
{% block call_to_action %}
<q-card>
<q-card-section>
<q-btn unelevated
color="deep-purple"
@click="notify"
type="a" href="{{ url_for('core.lnurlwallet', lightning=lnurl) }}">
Press to claim bitcoin
</q-btn>
</q-card-section>
</q-card>
{% endblock %}

0
lnbits/core/views/__init__.py

2
lnbits/core/views_api.py → lnbits/core/views/api.py

@ -6,7 +6,7 @@ from lnbits.decorators import api_check_wallet_macaroon, api_validate_post_reque
from lnbits.helpers import Status
from lnbits.settings import FEE_RESERVE, WALLET
from .crud import create_payment
from ..crud import create_payment
@core_app.route("/api/v1/payments", methods=["GET"])

2
lnbits/core/views.py → lnbits/core/views/generic.py

@ -5,7 +5,7 @@ from lnbits.core import core_app
from lnbits.decorators import check_user_exists, validate_uuids
from lnbits.helpers import Status
from .crud import (
from ..crud import (
create_account,
get_user,
update_user_extension,

55
lnbits/core/views/lnurl.py

@ -0,0 +1,55 @@
import json
import requests
from flask import redirect, render_template, request, url_for
from lnurl import LnurlWithdrawResponse, handle as handle_lnurl
from lnurl.exceptions import LnurlException
from time import sleep
from lnbits.core import core_app
from lnbits.settings import WALLET
from ..crud import create_account, get_user, create_wallet, create_payment
@core_app.route("/lnurl")
def lnurl():
lnurl = request.args.get("lightning")
return render_template("core/lnurl.html", lnurl=lnurl)
@core_app.route("/lnurlwallet")
def lnurlwallet():
try:
withdraw_res = handle_lnurl(request.args.get("lightning"), response_class=LnurlWithdrawResponse)
except LnurlException:
return redirect(url_for("core.home"))
_, payhash, payment_request = WALLET.create_invoice(withdraw_res.max_sats, "LNbits LNURL funding")
r = requests.get(
withdraw_res.callback.base,
params={**withdraw_res.callback.query_params, **{"k1": withdraw_res.k1, "pr": payment_request}},
)
if not r.ok:
return redirect(url_for("core.home")) # TODO: custom error
data = json.loads(r.text)
for i in range(10):
r = WALLET.get_invoice_status(payhash).raw_response
sleep(i)
if not r.ok:
continue
break
user = get_user(create_account().id)
wallet = create_wallet(user_id=user.id)
create_payment( # TODO: not pending?
wallet_id=wallet.id,
payhash=payhash,
amount=withdraw_res.max_sats * 1000,
memo="LNbits lnurl funding",
)
return redirect(url_for("core.wallet", usr=user.id, wal=wallet.id))

4
lnbits/settings.py

@ -11,5 +11,5 @@ WALLET = OpenNodeWallet(endpoint=os.getenv("OPENNODE_API_ENDPOINT"),admin_key=os
LNBITS_PATH = os.path.dirname(os.path.realpath(__file__))
LNBITS_DATA_FOLDER = os.getenv("LNBITS_DATA_FOLDER", os.path.join(LNBITS_PATH, "data"))
DEFAULT_USER_WALLET_NAME = os.getenv("DEFAULT_USER_WALLET_NAME", "LNbits wallet")
FEE_RESERVE = float(os.getenv("FEE_RESERVE", 0))
DEFAULT_WALLET_NAME = os.getenv("LNBITS_DEFAULT_WALLET_NAME", "LNbits wallet")
FEE_RESERVE = float(os.getenv("LNBITS_FEE_RESERVE", 0))

6
lnbits/templates/base.html

@ -31,8 +31,10 @@
</q-header>
<q-drawer v-model="w.visibleDrawer" side="left" :width="($q.screen.lt.md) ? 260 : 230" show-if-above :elevated="$q.screen.lt.md">
<lnbits-wallet-list></lnbits-wallet-list>
<lnbits-extension-list class="q-pb-xl"></lnbits-extension-list>
{% block drawer %}
<lnbits-wallet-list></lnbits-wallet-list>
<lnbits-extension-list class="q-pb-xl"></lnbits-extension-list>
{% endblock %}
</q-drawer>
<q-page-container>

15
lnbits/templates/lnurl.html

@ -1,15 +0,0 @@
<!-- @format -->
{% extends "index.html" %} {% block call_to_action %}
<button
class="btn btn-block btn-primary btn-lg"
onclick="processing()"
data-toggle="modal"
data-target=".proc"
>
Press to claim bitcoin!
</button>
<div id="processing">
</div>
{% endblock %}

4
requirements.txt

@ -5,6 +5,8 @@ chardet==3.0.4
click==7.0
flask-assets==2.0
flask-compress==1.4.0
flask-limiter==1.2.1
flask-seasurf==0.2.2
flask-talisman==0.7.0
flask==1.1.1
gevent==1.4.0
@ -13,6 +15,7 @@ gunicorn==20.0.4
idna==2.9
itsdangerous==1.1.0
jinja2==2.11.1
limits==1.5.1
lnurl==0.3.3
markupsafe==1.1.1
pydantic==1.4
@ -23,4 +26,3 @@ typing-extensions==3.7.4.1 ; python_version < '3.8'
urllib3==1.25.8
webassets==2.0
werkzeug==1.0.0
python-dotenv==0.12.0

Loading…
Cancel
Save