Skip to content

Commit

Permalink
feat: update to 1.0.0 (#37)
Browse files Browse the repository at this point in the history
* feat: update to 1.0.0

---------

Co-authored-by: Tiago Vasconcelos <[email protected]>
  • Loading branch information
dni and talvasconcelos authored Oct 22, 2024
1 parent 9127997 commit 7bb4856
Show file tree
Hide file tree
Showing 7 changed files with 1,053 additions and 997 deletions.
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"short_description": "Access LNbits from BlueWallet or Zeus",
"tile": "/lndhub/static/image/lndhub.png",
"contributors": ["fiatjaf", "dni"],
"min_lnbits_version": "0.12.11"
"min_lnbits_version": "1.0.0"
}
39 changes: 15 additions & 24 deletions decorators.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
from base64 import b64decode

from fastapi import Request, status
from fastapi.param_functions import Security
from fastapi import Request, Security
from fastapi.security.api_key import APIKeyHeader
from lnbits.core.models import WalletTypeInfo
from lnbits.decorators import get_key_type
from starlette.exceptions import HTTPException
from lnbits.decorators import require_admin_key, require_invoice_key

api_key_header_auth = APIKeyHeader(
name="Authorization",
Expand All @@ -14,31 +12,24 @@
)


async def check_wallet(
r: Request, api_key: str = Security(api_key_header_auth)
) -> WalletTypeInfo:
if not api_key:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid auth key"
)
async def sanitize_token(api_key: str) -> str:
if api_key.startswith("Bearer "):
t = api_key.split(" ")[1]
_, token = b64decode(t).decode().split(":")
else:
token = api_key

return await get_key_type(r, api_key_header=token)
return token


async def require_admin_key(
r: Request, api_key_header_auth: str = Security(api_key_header_auth)
async def lndhub_require_admin_key(
request: Request, api_key_header_auth: str = Security(api_key_header_auth)
):
wallet = await check_wallet(r, api_key_header_auth)
if wallet.key_type != 0:
# If wallet type is not admin then return the unauthorized status
# This also covers when the user passes an invalid key type
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Admin key required."
)
else:
return wallet
token = await sanitize_token(api_key_header_auth)
return await require_admin_key(request, token)


async def lndhub_require_invoice_key(
request: Request, api_key_header_auth: str = Security(api_key_header_auth)
) -> WalletTypeInfo:
token = await sanitize_token(api_key_header_auth)
return await require_invoice_key(request, token)
1,923 changes: 995 additions & 928 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Alan Bits <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.10 | ^3.9"
lnbits = "*"
lnbits = {version = "*", allow-prereleases = true}

[tool.poetry.group.dev.dependencies]
black = "^24.3.0"
Expand Down
45 changes: 20 additions & 25 deletions templates/lndhub/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %} {% raw %}
%} {% block page %}
<div class="row q-col-gutter-md">
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<div class="row q-col-gutter-md">
Expand All @@ -10,14 +10,13 @@
>
<q-card-section class="q-pa-none">
<div class="text-center">
<span class="text-capitalize" v-text="type"></span>
<a class="text-secondary" :href="selectedWallet[type]">
<q-responsive :ratio="1" class="q-mx-sm">
<qrcode
:value="selectedWallet[type]"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive>
<lnbits-qrcode
:value="selectedWallet[type]"
:options="{width: 350}"
class="rounded-borders"
></lnbits-qrcode>
</a>
</div>
<div class="row q-mt-lg items-center justify-center">
Expand All @@ -26,7 +25,7 @@
color="grey"
@click="copyText(selectedWallet[type])"
class="text-center q-mb-md"
>Copy LndHub {{type}} URL</q-btn
>Copy LndHub <span v-text="type"></span> URL</q-btn
>
</div>
</q-card-section>
Expand All @@ -47,8 +46,6 @@
</q-card>
</div>

{% endraw %}

<div class="col-12 col-md-4 col-lg-5 q-gutter-y-md">
<q-card>
<q-card-section>
Expand All @@ -70,23 +67,21 @@ <h6 class="text-subtitle1 q-my-none">

{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script>
Vue.component(VueQrcode.name, VueQrcode)

new Vue({
window.app = Vue.createApp({
el: '#vue',
mixins: [windowMixin],
data: function () {
var wallets = JSON.parse('{{ user.wallets | tojson }}')
.map(LNbits.map.wallet)
.map(wallet => ({
label: wallet.name,
admin: `lndhub://admin:${wallet.adminkey}@${location.protocol}//${location.host}/lndhub/ext/`,
invoice: `lndhub://invoice:${wallet.inkey}@${location.protocol}//${location.host}/lndhub/ext/`
}))

data() {
const {wallets} = JSON.parse({{ user | tojson | safe }})
const mappedWallets = wallets
.map(LNbits.map.wallet)
.map(wallet => ({
label: wallet.name,
admin: `lndhub://admin:${wallet.adminkey}@${location.protocol}//${location.host}/lndhub/ext/`,
invoice: `lndhub://invoice:${wallet.inkey}@${location.protocol}//${location.host}/lndhub/ext/`
}))
return {
wallets: wallets,
selectedWallet: wallets[0]
wallets: mappedWallets,
selectedWallet: mappedWallets[0]
}
}
})
Expand Down
2 changes: 1 addition & 1 deletion views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ def lndhub_renderer():
@lndhub_generic_router.get("/")
async def lndhub_index(request: Request, user: User = Depends(check_user_exists)):
return lndhub_renderer().TemplateResponse(
"lndhub/index.html", {"request": request, "user": user.dict()}
"lndhub/index.html", {"request": request, "user": user.json()}
)
37 changes: 20 additions & 17 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from lnbits.core.services import create_invoice, pay_invoice
from lnbits.settings import settings

from .decorators import check_wallet, require_admin_key
from .decorators import lndhub_require_admin_key, lndhub_require_invoice_key
from .models import LndhubAddInvoice, LndhubAuthData, LndhubCreateInvoice
from .utils import decoded_as_lndhub, to_buffer

Expand All @@ -34,10 +34,10 @@ async def lndhub_auth(data: LndhubAuthData):

@lndhub_api_router.post("/addinvoice")
async def lndhub_addinvoice(
data: LndhubAddInvoice, wallet: WalletTypeInfo = Depends(check_wallet)
data: LndhubAddInvoice, wallet: WalletTypeInfo = Depends(lndhub_require_invoice_key)
):
try:
payment_hash, pr = await create_invoice(
payment = await create_invoice(
wallet_id=wallet.wallet.id,
amount=data.amt,
memo=data.memo or settings.lnbits_site_title,
Expand All @@ -47,18 +47,18 @@ async def lndhub_addinvoice(
return {"error": f"Failed to create invoice: {exc!s}"}

return {
"pay_req": pr,
"payment_request": pr,
"pay_req": payment.bolt11,
"payment_request": payment.bolt11,
"add_index": "500",
"r_hash": to_buffer(payment_hash),
"hash": payment_hash,
"r_hash": to_buffer(payment.payment_hash),
"hash": payment.payment_hash,
}


@lndhub_api_router.post("/payinvoice")
async def lndhub_payinvoice(
r_invoice: LndhubCreateInvoice,
key_type: WalletTypeInfo = Depends(require_admin_key),
key_type: WalletTypeInfo = Depends(lndhub_require_admin_key),
):
try:
invoice = bolt11_decode(r_invoice.invoice)
Expand Down Expand Up @@ -87,14 +87,14 @@ async def lndhub_payinvoice(

@lndhub_api_router.get("/balance")
async def lndhub_balance(
key_type: WalletTypeInfo = Depends(check_wallet),
key_type: WalletTypeInfo = Depends(lndhub_require_invoice_key),
):
return {"BTC": {"AvailableBalance": key_type.wallet.balance}}


@lndhub_api_router.get("/gettxs")
async def lndhub_gettxs(
key_type: WalletTypeInfo = Depends(check_wallet),
key_type: WalletTypeInfo = Depends(lndhub_require_invoice_key),
limit: int = Query(20, ge=1, le=200),
offset: int = Query(0, ge=0),
):
Expand All @@ -108,7 +108,7 @@ async def lndhub_gettxs(
"value": int(payment.amount / 1000),
"timestamp": payment.time,
"memo": (
payment.extra.get("comment") or payment.memo
payment.extra and payment.extra.get("comment") or payment.memo
if not payment.pending
else "Payment in transition"
),
Expand All @@ -129,7 +129,7 @@ async def lndhub_gettxs(

@lndhub_api_router.get("/getuserinvoices")
async def lndhub_getuserinvoices(
key_type: WalletTypeInfo = Depends(check_wallet),
key_type: WalletTypeInfo = Depends(lndhub_require_invoice_key),
limit: int = Query(20, ge=1, le=200),
offset: int = Query(0, ge=0),
):
Expand All @@ -138,10 +138,11 @@ async def lndhub_getuserinvoices(
"r_hash": to_buffer(payment.payment_hash),
"payment_request": payment.bolt11,
"add_index": "500",
"description": payment.extra.get("comment") or payment.memo,
"description": (
payment.extra and payment.extra.get("comment") or payment.memo
),
"payment_hash": payment.payment_hash,
# todo it works for lnbits 0.12.11 but not for 0.12.10
"ispaid": payment.success, # type: ignore
"ispaid": payment.success,
"amt": int(payment.amount / 1000),
"expire_time": int(time.time() + 1800),
"timestamp": payment.time,
Expand All @@ -161,13 +162,15 @@ async def lndhub_getuserinvoices(
]


@lndhub_api_router.get("/getbtc", dependencies=[Depends(check_wallet)])
@lndhub_api_router.get("/getbtc", dependencies=[Depends(lndhub_require_invoice_key)])
async def lndhub_getbtc():
"load an address for incoming onchain btc"
return []


@lndhub_api_router.get("/getpending", dependencies=[Depends(check_wallet)])
@lndhub_api_router.get(
"/getpending", dependencies=[Depends(lndhub_require_invoice_key)]
)
async def lndhub_getpending():
"pending onchain transactions"
return []
Expand Down

0 comments on commit 7bb4856

Please sign in to comment.