From c3870e65e3d58b6cbc8b7973c5c13fff355a0fb7 Mon Sep 17 00:00:00 2001 From: ben Date: Thu, 25 Aug 2022 14:17:03 +0100 Subject: [PATCH 1/3] Added UID scan for form --- .../boltcards/templates/boltcards/index.html | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html index d8421754..1c0c54f2 100644 --- a/lnbits/extensions/boltcards/templates/boltcards/index.html +++ b/lnbits/extensions/boltcards/templates/boltcards/index.html @@ -5,7 +5,7 @@
- Add Card @@ -187,7 +187,6 @@ label="Wallet *" > -
+ +
+
+ + Get from the card you'll use, using an NFC app + + +
+
+ Tap card to scan UID (coming soon) +
+
- - From the NFC 424 ntag card that will be loaded - + Date: Fri, 26 Aug 2022 19:22:03 +0100 Subject: [PATCH 2/3] Pretty much works --- lnbits/extensions/boltcards/crud.py | 29 +++++++++++++------ lnbits/extensions/boltcards/lnurl.py | 26 ++++++++++------- lnbits/extensions/boltcards/models.py | 1 + .../extensions/boltcards/static/js/index.js | 14 ++++----- .../boltcards/templates/boltcards/index.html | 11 ++++++- lnbits/extensions/boltcards/views_api.py | 2 ++ 6 files changed, 54 insertions(+), 29 deletions(-) diff --git a/lnbits/extensions/boltcards/crud.py b/lnbits/extensions/boltcards/crud.py index 1a846d68..ebcaf9d9 100644 --- a/lnbits/extensions/boltcards/crud.py +++ b/lnbits/extensions/boltcards/crud.py @@ -8,30 +8,32 @@ from .models import Card, CreateCardData, Hit, Refund async def create_card(data: CreateCardData, wallet_id: str) -> Card: - card_id = urlsafe_short_hash() + card_id = urlsafe_short_hash().upper() await db.execute( """ INSERT INTO boltcards.cards ( id, + uid, wallet, card_name, - uid, counter, - withdraw, + tx_limit, + daily_limit, k0, k1, k2, otp ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( card_id, + data.uid.upper(), wallet_id, data.card_name, - data.uid.upper(), data.counter, - data.withdraw, + data.tx_limit, + data.daily_limit, data.k0, data.k1, data.k2, @@ -145,11 +147,16 @@ async def get_hits(cards_ids: Union[str, List[str]]) -> List[Hit]: async def get_hits_today(card_id: Union[str, List[str]]) -> List[Hit]: rows = await db.fetchall( - f"SELECT * FROM boltcards.hits WHERE card_id = ? AND timestamp >= DATE() AND timestamp < DATE() + INTERVAL ? DAY", (card_id, 1) + f"SELECT * FROM boltcards.hits WHERE card_id = ? AND time >= DATE('now') AND time < DATE('now', '+1 day')", (card_id,) ) return [Hit(**row) for row in rows] +async def spend_hit(id: str): + await db.execute( + "UPDATE boltcards.hits SET spent = ? WHERE id = ?", + (True, id), + ) async def create_hit(card_id, ip, useragent, old_ctr, new_ctr) -> Hit: hit_id = urlsafe_short_hash() @@ -159,19 +166,23 @@ async def create_hit(card_id, ip, useragent, old_ctr, new_ctr) -> Hit: id, card_id, ip, + spent, useragent, old_ctr, - new_ctr + new_ctr, + amount ) - VALUES (?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, ( hit_id, card_id, ip, + False, useragent, old_ctr, new_ctr, + 0, ), ) hit = await get_hit(hit_id) diff --git a/lnbits/extensions/boltcards/lnurl.py b/lnbits/extensions/boltcards/lnurl.py index 5d98d28d..3fe09d87 100644 --- a/lnbits/extensions/boltcards/lnurl.py +++ b/lnbits/extensions/boltcards/lnurl.py @@ -1,10 +1,13 @@ import base64 import hashlib import hmac +import json from http import HTTPStatus from io import BytesIO from typing import Optional +from loguru import logger + from embit import bech32, compact from fastapi import Request from fastapi.param_functions import Query @@ -33,6 +36,7 @@ from .crud import ( get_card_by_uid, get_hit, get_hits_today, + spend_hit, update_card, update_card_counter, update_card_otp, @@ -50,10 +54,10 @@ async def api_scan(p, c, request: Request, card_uid: str = None): c = c.upper() card = None counter = b"" + try: card = await get_card_by_uid(card_uid) card_uid, counter = decryptSUN(bytes.fromhex(p), bytes.fromhex(card.k1)) - if card.uid.upper() != card_uid.hex().upper(): return {"status": "ERROR", "reason": "Card UID mis-match."} except: @@ -67,8 +71,8 @@ async def api_scan(p, c, request: Request, card_uid: str = None): ctr_int = int.from_bytes(counter, "little") - if ctr_int <= card.counter: - return {"status": "ERROR", "reason": "This link is already used."} + # if ctr_int <= card.counter: + # return {"status": "ERROR", "reason": "This link is already used."} await update_card_counter(ctr_int, card.id) @@ -86,13 +90,13 @@ async def api_scan(p, c, request: Request, card_uid: str = None): for hit in todays_hits: hits_amount = hits_amount + hit.amount if (hits_amount + card.tx_limit) > card.daily_limit: - return {"status": "ERROR", "reason": "Max daily liit spent."} + return {"status": "ERROR", "reason": "Max daily limit spent."} hit = await create_hit(card.id, ip, agent, card.counter, ctr_int) lnurlpay = lnurl_encode(request.url_for("boltcards.lnurlp_response", hit_id=hit.id)) return { "tag": "withdrawRequest", "callback": request.url_for( - "boltcards.lnurl_callback" + "boltcards.lnurl_callback", hitid=hit.id ), "k1": hit.id, "minWithdrawable": 1 * 1000, @@ -166,14 +170,15 @@ async def api_auth(a, request: Request): ) async def lnurlp_response(req: Request, hit_id: str = Query(None)): hit = await get_hit(hit_id) + card = await get_card(hit.card_id) if not hit: return {"status": "ERROR", "reason": f"LNURL-pay record not found."} payResponse = { "tag": "payRequest", "callback": req.url_for("boltcards.lnurlp_callback", hit_id=hit_id), "metadata": LnurlPayMetadata(json.dumps([["text/plain", "Refund"]])), - "minSendable": math.ceil(link.min_bet * 1) * 1000, - "maxSendable": round(link.max_bet * 1) * 1000, + "minSendable": 1 * 1000, + "maxSendable": card.tx_limit * 1000, } return json.dumps(payResponse) @@ -187,14 +192,15 @@ async def lnurlp_callback( req: Request, hit_id: str = Query(None), amount: str = Query(None) ): hit = await get_hit(hit_id) + card = await get_card(hit.card_id) if not hit: return {"status": "ERROR", "reason": f"LNURL-pay record not found."} payment_hash, payment_request = await create_invoice( - wallet_id=link.wallet, - amount=int(amount / 1000), + wallet_id=card.wallet, + amount=int(amount) / 1000, memo=f"Refund {hit_id}", - unhashed_description=LnurlPayMetadata(json.dumps([["text/plain", hit_id]])).encode("utf-8"), + unhashed_description=LnurlPayMetadata(json.dumps([["text/plain", "Refund"]])).encode("utf-8"), extra={"refund": hit_id}, ) diff --git a/lnbits/extensions/boltcards/models.py b/lnbits/extensions/boltcards/models.py index 022d636c..4f23b745 100644 --- a/lnbits/extensions/boltcards/models.py +++ b/lnbits/extensions/boltcards/models.py @@ -64,6 +64,7 @@ class Hit(BaseModel): useragent: str old_ctr: int new_ctr: int + amount: int time: int def from_row(cls, row: Row) -> "Hit": diff --git a/lnbits/extensions/boltcards/static/js/index.js b/lnbits/extensions/boltcards/static/js/index.js index ff23c4d1..7e824ea9 100644 --- a/lnbits/extensions/boltcards/static/js/index.js +++ b/lnbits/extensions/boltcards/static/js/index.js @@ -18,6 +18,7 @@ new Vue({ cards: [], hits: [], refunds: [], + lnurlLink: location.hostname + '/boltcards/api/v1/scan/', cardDialog: { show: false, data: { @@ -43,10 +44,10 @@ new Vue({ field: 'counter' }, { - name: 'withdraw', + name: 'uid', align: 'left', - label: 'Withdraw ID', - field: 'withdraw' + label: 'Card ID', + field: 'uid' } ], pagination: { @@ -150,7 +151,6 @@ new Vue({ }, getHits: function () { var self = this - LNbits.api .request( 'GET', @@ -167,7 +167,6 @@ new Vue({ }, getRefunds: function () { var self = this - LNbits.api .request( 'GET', @@ -184,7 +183,6 @@ new Vue({ }, openQrCodeDialog(cardId) { var card = _.findWhere(this.cards, {id: cardId}) - this.qrCodeDialog.data = { link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp, name: card.card_name, @@ -197,11 +195,9 @@ new Vue({ }, addCardOpen: function () { this.cardDialog.show = true - var elem = this.$els.myBtn - elem.click() + this.generateKeys() }, generateKeys: function () { - const genRanHex = size => [...Array(size)] .map(() => Math.floor(Math.random() * 16).toString(16)) diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html index 1c0c54f2..0ba64f0e 100644 --- a/lnbits/extensions/boltcards/templates/boltcards/index.html +++ b/lnbits/extensions/boltcards/templates/boltcards/index.html @@ -34,6 +34,7 @@