reducing the PR

This commit is contained in:
Gene Takavic 2022-12-16 11:09:10 +01:00
parent afe07ad0ba
commit 3aee76be39
10 changed files with 23 additions and 128 deletions

View File

@ -2,7 +2,7 @@ import asyncio
import json import json
from binascii import unhexlify from binascii import unhexlify
from io import BytesIO from io import BytesIO
from typing import Dict, Optional, Tuple, Union from typing import Dict, Optional, Tuple
from urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
import httpx import httpx
@ -102,7 +102,6 @@ async def pay_invoice(
extra: Optional[Dict] = None, extra: Optional[Dict] = None,
description: str = "", description: str = "",
conn: Optional[Connection] = None, conn: Optional[Connection] = None,
webhook: Optional[Union[str, tuple]] = None,
) -> str: ) -> str:
""" """
Pay a Lightning invoice. Pay a Lightning invoice.
@ -232,35 +231,6 @@ async def pay_invoice(
f"didn't receive checking_id from backend, payment may be stuck in database: {temp_id}" f"didn't receive checking_id from backend, payment may be stuck in database: {temp_id}"
) )
additionals = None
if type(webhook) is str:
webhook_url = webhook
elif type(webhook) is tuple:
webhook_url = webhook[0]
additionals = webhook[1]
else:
webhook_url = None
if webhook_url:
async with httpx.AsyncClient() as client:
try:
json = {
"payment_hash": invoice.payment_hash,
"payment_request": payment_request,
"amount": int(invoice.amount_msat / 1000),
}
if type(additionals) is dict:
json.update(additionals)
r = await client.post(
webhook_url,
json=json,
timeout=40,
)
except Exception as exc:
# webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
logger.error("Caught exception when dispatching webhook url:", exc)
return invoice.payment_hash return invoice.payment_hash

View File

@ -27,10 +27,9 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
k0, k0,
k1, k1,
k2, k2,
otp, otp
webhook_url
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", """,
( (
card_id, card_id,
@ -46,7 +45,6 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
data.k1, data.k1,
data.k2, data.k2,
secrets.token_hex(16), secrets.token_hex(16),
data.webhook_url,
), ),
) )
card = await get_card(card_id) card = await get_card(card_id)
@ -179,9 +177,6 @@ async def get_hit(hit_id: str) -> Optional[Hit]:
async def get_hits(cards_ids: Union[str, List[str]]) -> List[Hit]: async def get_hits(cards_ids: Union[str, List[str]]) -> List[Hit]:
if len(cards_ids) == 0:
return []
q = ",".join(["?"] * len(cards_ids)) q = ",".join(["?"] * len(cards_ids))
rows = await db.fetchall( rows = await db.fetchall(
f"SELECT * FROM boltcards.hits WHERE card_id IN ({q})", (*cards_ids,) f"SELECT * FROM boltcards.hits WHERE card_id IN ({q})", (*cards_ids,)
@ -276,9 +271,6 @@ async def get_refund(refund_id: str) -> Optional[Refund]:
async def get_refunds(hits_ids: Union[str, List[str]]) -> List[Refund]: async def get_refunds(hits_ids: Union[str, List[str]]) -> List[Refund]:
if len(hits_ids) == 0:
return []
q = ",".join(["?"] * len(hits_ids)) q = ",".join(["?"] * len(hits_ids))
rows = await db.fetchall( rows = await db.fetchall(
f"SELECT * FROM boltcards.refunds WHERE hit_id IN ({q})", (*hits_ids,) f"SELECT * FROM boltcards.refunds WHERE hit_id IN ({q})", (*hits_ids,)

View File

@ -112,27 +112,11 @@ async def lnurl_callback(
invoice = bolt11.decode(pr) invoice = bolt11.decode(pr)
hit = await spend_hit(id=hit.id, amount=int(invoice.amount_msat / 1000)) hit = await spend_hit(id=hit.id, amount=int(invoice.amount_msat / 1000))
try: try:
webhook = (
(
card.webhook_url,
{
"notification": "card_payment",
"card_external_id": card.external_id,
"card_name": card.card_name,
"card_otp": card.otp[
-16:
], # actually only half of the OTP is sent (full otp reveals the keys)
},
)
if card.webhook_url
else None
)
await pay_invoice( await pay_invoice(
wallet_id=card.wallet, wallet_id=card.wallet,
payment_request=pr, payment_request=pr,
max_sat=card.tx_limit, max_sat=card.tx_limit,
extra={"tag": "boltcard", "tag": hit.id}, extra={"tag": "boltcard", "tag": hit.id},
webhook=webhook,
) )
return {"status": "OK"} return {"status": "OK"}

View File

@ -58,11 +58,3 @@ async def m001_initial(db):
); );
""" """
) )
async def m002_add_webhook(db):
await db.execute(
"""
ALTER TABLE boltcards.cards ADD COLUMN webhook_url TEXT NOT NULL DEFAULT '';
"""
)

View File

@ -30,7 +30,6 @@ class Card(BaseModel):
prev_k1: str prev_k1: str
prev_k2: str prev_k2: str
otp: str otp: str
webhook_url: str
time: int time: int
def from_row(cls, row: Row) -> "Card": def from_row(cls, row: Row) -> "Card":
@ -57,7 +56,6 @@ class CreateCardData(BaseModel):
prev_k0: str = Query(ZERO_KEY) prev_k0: str = Query(ZERO_KEY)
prev_k1: str = Query(ZERO_KEY) prev_k1: str = Query(ZERO_KEY)
prev_k2: str = Query(ZERO_KEY) prev_k2: str = Query(ZERO_KEY)
webhook_url: str = Query(...)
class Hit(BaseModel): class Hit(BaseModel):

View File

@ -23,7 +23,6 @@ new Vue({
cardDialog: { cardDialog: {
show: false, show: false,
data: { data: {
webhook_url: '',
counter: 1, counter: 1,
k0: '', k0: '',
k1: '', k1: '',
@ -273,8 +272,7 @@ new Vue({
k1: card.k1, k1: card.k1,
k2: card.k2, k2: card.k2,
k3: card.k1, k3: card.k1,
k4: card.k2, k4: card.k2
webhook_url: card.webhook_url
} }
this.qrCodeDialog.data_wipe = JSON.stringify({ this.qrCodeDialog.data_wipe = JSON.stringify({
action: 'wipe', action: 'wipe',

View File

@ -9,7 +9,7 @@ from lnbits.core.models import Payment
from lnbits.helpers import get_current_extension_name from lnbits.helpers import get_current_extension_name
from lnbits.tasks import register_invoice_listener from lnbits.tasks import register_invoice_listener
from .crud import create_refund, get_card, get_hit from .crud import create_refund, get_hit
async def wait_for_paid_invoices(): async def wait_for_paid_invoices():
@ -36,25 +36,6 @@ async def on_invoice_paid(payment: Payment) -> None:
) )
await mark_webhook_sent(payment, 1) await mark_webhook_sent(payment, 1)
card = await get_card(hit.card_id)
if card.webhook_url:
async with httpx.AsyncClient() as client:
try:
r = await client.post(
card.webhook_url,
json={
"notification": "card_refund",
"payment_hash": payment.payment_hash,
"payment_request": payment.bolt11,
"card_external_id": card.external_id,
"card_name": card.card_name,
"amount": int(payment.amount / 1000),
},
timeout=40,
)
except Exception as exc:
logger.error("Caught exception when dispatching webhook url:", exc)
async def mark_webhook_sent(payment: Payment, status: int) -> None: async def mark_webhook_sent(payment: Payment, status: int) -> None:
payment.extra["wh_status"] = status payment.extra["wh_status"] = status

View File

@ -324,14 +324,6 @@
>Zero if you don't know.</q-tooltip >Zero if you don't know.</q-tooltip
> >
</q-input> </q-input>
<q-input
filled
dense
v-model.number="cardDialog.data.webhook_url"
type="text"
label="Notification webhook"
>
</q-input>
<q-btn <q-btn
unelevated unelevated
color="primary" color="primary"
@ -431,8 +423,6 @@
<strong>Lock key:</strong> {{ qrCodeDialog.data.k0 }}<br /> <strong>Lock key:</strong> {{ qrCodeDialog.data.k0 }}<br />
<strong>Meta key:</strong> {{ qrCodeDialog.data.k1 }}<br /> <strong>Meta key:</strong> {{ qrCodeDialog.data.k1 }}<br />
<strong>File key:</strong> {{ qrCodeDialog.data.k2 }}<br /> <strong>File key:</strong> {{ qrCodeDialog.data.k2 }}<br />
<strong>Notification webhook:</strong> {{ qrCodeDialog.data.webhook_url
}}<br />
</p> </p>
<p> <p>
Always backup all keys that you're trying to write on the card. Without Always backup all keys that you're trying to write on the card. Without

View File

@ -113,22 +113,6 @@ async def enable_card(
return card.dict() return card.dict()
@boltcards_ext.post("/api/v1/disablecard")
async def disble_card_with_otp(a):
if len(a) < 16:
raise HTTPException(detail="Invalid OTP.", status_code=HTTPStatus.BAD_REQUEST)
card = await get_card_by_otp(a, half=True)
if not card:
raise HTTPException(detail="No card found.", status_code=HTTPStatus.NOT_FOUND)
new_otp = secrets.token_hex(16)
await update_card_otp(new_otp, card.id)
card = await enable_disable_card(enable=False, id=card.id)
return {"status": "OK"}
@boltcards_ext.delete("/api/v1/cards/{card_id}") @boltcards_ext.delete("/api/v1/cards/{card_id}")
async def api_card_delete(card_id, wallet: WalletTypeInfo = Depends(require_admin_key)): async def api_card_delete(card_id, wallet: WalletTypeInfo = Depends(require_admin_key)):
card = await get_card(card_id) card = await get_card(card_id)

View File

@ -3,6 +3,7 @@ import traceback
from datetime import datetime from datetime import datetime
from http import HTTPStatus from http import HTTPStatus
import httpx
import shortuuid # type: ignore import shortuuid # type: ignore
from fastapi import HTTPException from fastapi import HTTPException
from fastapi.param_functions import Query from fastapi.param_functions import Query
@ -132,24 +133,29 @@ async def api_lnurl_callback(
payment_request = pr payment_request = pr
webhook = ( payment_hash = await pay_invoice(
(
link.webhook_url,
{
"lnurlw": link.id,
},
)
if link.webhook_url
else None
)
await pay_invoice(
wallet_id=link.wallet, wallet_id=link.wallet,
payment_request=payment_request, payment_request=payment_request,
max_sat=link.max_withdrawable, max_sat=link.max_withdrawable,
extra={"tag": "withdraw"}, extra={"tag": "withdraw"},
webhook=webhook,
) )
if link.webhook_url:
async with httpx.AsyncClient() as client:
try:
r = await client.post(
link.webhook_url,
json={
"payment_hash": payment_hash,
"payment_request": payment_request,
"lnurlw": link.id,
},
timeout=40,
)
except Exception as exc:
# webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
logger.error("Caught exception when dispatching webhook url:", exc)
return {"status": "OK"} return {"status": "OK"}
except Exception as e: except Exception as e: