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_APP=lnbits
FLASK_ENV=development 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_API_ENDPOINT=https://mylnd.io/rest/
LND_ADMIN_MACAROON=LND_ADMIN_MACAROON LND_ADMIN_MACAROON=LND_ADMIN_MACAROON
LND_INVOICE_MACAROON=LND_INVOICE_MACAROON LND_INVOICE_MACAROON=LND_INVOICE_MACAROON
@ -15,9 +19,7 @@ OPENNODE_ADMIN_KEY=OPENNODE_ADMIN_KEY
OPENNODE_INVOICE_KEY=OPENNODE_INVOICE_KEY OPENNODE_INVOICE_KEY=OPENNODE_INVOICE_KEY
LNPAY_API_ENDPOINT=https://lnpay.co/v1/ LNPAY_API_ENDPOINT=https://lnpay.co/v1/
LNPAY_API_KEY=LNPAY_API_KEY
LNPAY_ADMIN_KEY=LNPAY_ADMIN_KEY LNPAY_ADMIN_KEY=LNPAY_ADMIN_KEY
LNPAY_INVOICE_KEY=LNPAY_INVOICE_KEY LNPAY_INVOICE_KEY=LNPAY_INVOICE_KEY
LNPAY_READ_KEY=LNPAY_READ_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 = "*"
flask-assets = "*" flask-assets = "*"
flask-compress = "*" flask-compress = "*"
flask-limiter = "*"
flask-seasurf = "*"
flask-talisman = "*" flask-talisman = "*"
gevent = "*" gevent = "*"
greenlet = "*" greenlet = "*"

75
lnbits/__init__.py

@ -1,18 +1,14 @@
import importlib 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_assets import Environment, Bundle
from flask_compress import Compress from flask_compress import Compress
from flask_talisman import Talisman from flask_talisman import Talisman
from lnurl import Lnurl, LnurlWithdrawResponse from os import getenv
from .core import core_app from .core import core_app
from .db import init_databases, open_db from .db import init_databases
from .helpers import ExtensionManager, megajson from .helpers import ExtensionManager, megajson
from .settings import WALLET, DEFAULT_USER_WALLET_NAME
app = Flask(__name__) app = Flask(__name__)
@ -25,6 +21,7 @@ valid_extensions = [ext for ext in ExtensionManager().extensions if ext.is_valid
Compress(app) Compress(app)
Talisman( Talisman(
app, app,
force_https=getenv("LNBITS_WITH_ONION", 0) == 0,
content_security_policy={ content_security_policy={
"default-src": [ "default-src": [
"'self'", "'self'",
@ -81,69 +78,5 @@ def init():
init_databases() 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__': if __name__ == '__main__':
app.run() 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") core_app = Blueprint("core", __name__, template_folder="templates", static_folder="static")
from .views_api import * # noqa from .views.api import * # noqa
from .views 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 uuid import uuid4
from lnbits.db import open_db 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 typing import List, Optional
from .models import User, Wallet, Payment 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) INSERT INTO wallets (id, name, user, adminkey, inkey)
VALUES (?, ?, ?, ?, ?) 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) 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="row q-col-gutter-md justify-between">
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md"> <div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<q-card> {% block call_to_action %}
<q-card-section> <q-card>
<q-form class="q-gutter-md"> <q-card-section>
<q-input filled dense <q-form class="q-gutter-md">
v-model="walletName" <q-input filled dense
label="Name your LNbits wallet *" v-model="walletName"
></q-input> label="Name your LNbits wallet *"
<q-btn unelevated ></q-input>
color="deep-purple" <q-btn unelevated
:disable="walletName == ''" color="deep-purple"
@click="createWallet">Add a new wallet</q-btn> :disable="walletName == ''"
</q-form> @click="createWallet">Add a new wallet</q-btn>
</q-card-section> </q-form>
</q-card> </q-card-section>
</q-card>
{% endblock %}
<q-card> <q-card>
<q-card-section> <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.helpers import Status
from lnbits.settings import FEE_RESERVE, WALLET 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"]) @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.decorators import check_user_exists, validate_uuids
from lnbits.helpers import Status from lnbits.helpers import Status
from .crud import ( from ..crud import (
create_account, create_account,
get_user, get_user,
update_user_extension, 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_PATH = os.path.dirname(os.path.realpath(__file__))
LNBITS_DATA_FOLDER = os.getenv("LNBITS_DATA_FOLDER", os.path.join(LNBITS_PATH, "data")) 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") DEFAULT_WALLET_NAME = os.getenv("LNBITS_DEFAULT_WALLET_NAME", "LNbits wallet")
FEE_RESERVE = float(os.getenv("FEE_RESERVE", 0)) FEE_RESERVE = float(os.getenv("LNBITS_FEE_RESERVE", 0))

6
lnbits/templates/base.html

@ -31,8 +31,10 @@
</q-header> </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"> <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> {% block drawer %}
<lnbits-extension-list class="q-pb-xl"></lnbits-extension-list> <lnbits-wallet-list></lnbits-wallet-list>
<lnbits-extension-list class="q-pb-xl"></lnbits-extension-list>
{% endblock %}
</q-drawer> </q-drawer>
<q-page-container> <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 click==7.0
flask-assets==2.0 flask-assets==2.0
flask-compress==1.4.0 flask-compress==1.4.0
flask-limiter==1.2.1
flask-seasurf==0.2.2
flask-talisman==0.7.0 flask-talisman==0.7.0
flask==1.1.1 flask==1.1.1
gevent==1.4.0 gevent==1.4.0
@ -13,6 +15,7 @@ gunicorn==20.0.4
idna==2.9 idna==2.9
itsdangerous==1.1.0 itsdangerous==1.1.0
jinja2==2.11.1 jinja2==2.11.1
limits==1.5.1
lnurl==0.3.3 lnurl==0.3.3
markupsafe==1.1.1 markupsafe==1.1.1
pydantic==1.4 pydantic==1.4
@ -23,4 +26,3 @@ typing-extensions==3.7.4.1 ; python_version < '3.8'
urllib3==1.25.8 urllib3==1.25.8
webassets==2.0 webassets==2.0
werkzeug==1.0.0 werkzeug==1.0.0
python-dotenv==0.12.0

Loading…
Cancel
Save