Black/prettier

This commit is contained in:
ben 2022-08-29 14:18:18 +01:00
parent 9e3cd3f00e
commit 7bfc0848ef
10 changed files with 161 additions and 136 deletions

View File

@ -16,9 +16,11 @@ boltcards_static_files = [
boltcards_ext: APIRouter = APIRouter(prefix="/boltcards", tags=["boltcards"])
def boltcards_renderer():
return template_renderer(["lnbits/extensions/boltcards/templates"])
from .lnurl import * # noqa
from .tasks import * # noqa
from .views import * # noqa

View File

@ -2,5 +2,5 @@
"name": "Bolt Cards",
"short_description": "Self custody Bolt Cards with one time LNURLw",
"icon": "payment",
"contributors": ["iwarpbtc"]
"contributors": ["iwarpbtc", "arcbtc", "leesalminen"]
}

View File

@ -116,7 +116,9 @@ async def delete_card(card_id: str) -> None:
# Delete refunds
refunds = await get_refunds([hit])
for refund in refunds:
await db.execute("DELETE FROM boltcards.refunds WHERE id = ?", (refund.hit_id,))
await db.execute(
"DELETE FROM boltcards.refunds WHERE id = ?", (refund.hit_id,)
)
async def update_card_counter(counter: int, id: str):
@ -125,6 +127,7 @@ async def update_card_counter(counter: int, id: str):
(counter, id),
)
async def enable_disable_card(enable: bool, id: str) -> Optional[Card]:
row = await db.execute(
"UPDATE boltcards.cards SET enable = ? WHERE id = ?",
@ -132,6 +135,7 @@ async def enable_disable_card(enable: bool, id: str) -> Optional[Card]:
)
return await get_card(id)
async def update_card_otp(otp: str, id: str):
await db.execute(
"UPDATE boltcards.cards SET otp = ? WHERE id = ?",
@ -157,19 +161,23 @@ async def get_hits(cards_ids: Union[str, List[str]]) -> List[Hit]:
return [Hit(**row) for row in rows]
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 time >= DATE('now') AND time < DATE('now', '+1 day')", (card_id,)
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()
await db.execute(
@ -201,6 +209,7 @@ async def create_hit(card_id, ip, useragent, old_ctr, new_ctr) -> Hit:
assert hit, "Newly recorded hit couldn't be retrieved"
return hit
async def create_refund(hit_id, refund_amount) -> Refund:
refund_id = urlsafe_short_hash()
await db.execute(
@ -224,13 +233,17 @@ async def create_refund(hit_id, refund_amount) -> Refund:
assert refund, "Newly recorded hit couldn't be retrieved"
return refund
async def get_refund(refund_id: str) -> Optional[Refund]:
row = await db.fetchone(f"SELECT * FROM boltcards.refunds WHERE id = ?", (refund_id))
row = await db.fetchone(
f"SELECT * FROM boltcards.refunds WHERE id = ?", (refund_id)
)
if not row:
return None
refund = dict(**row)
return Refund.parse_obj(refund)
async def get_refunds(hits_ids: Union[str, List[str]]) -> List[Refund]:
q = ",".join(["?"] * len(hits_ids))
rows = await db.fetchall(

View File

@ -95,15 +95,14 @@ async def api_scan(p, c, request: Request, card_uid: str = None):
lnurlpay = lnurl_encode(request.url_for("boltcards.lnurlp_response", hit_id=hit.id))
return {
"tag": "withdrawRequest",
"callback": request.url_for(
"boltcards.lnurl_callback", hitid=hit.id
),
"callback": request.url_for("boltcards.lnurl_callback", hitid=hit.id),
"k1": hit.id,
"minWithdrawable": 1 * 1000,
"maxWithdrawable": card.tx_limit * 1000,
"defaultDescription": f"Boltcard (refund address {lnurlpay})",
}
@boltcards_ext.get(
"/api/v1/lnurl/cb/{hitid}",
status_code=HTTPStatus.OK,
@ -158,8 +157,10 @@ async def api_auth(a, request: Request):
return response
###############LNURLPAY REFUNDS#################
@boltcards_ext.get(
"/api/v1/lnurlp/{hit_id}",
response_class=HTMLResponse,
@ -199,14 +200,12 @@ async def lnurlp_callback(
wallet_id=card.wallet,
amount=int(amount) / 1000,
memo=f"Refund {hit_id}",
unhashed_description=LnurlPayMetadata(json.dumps([["text/plain", "Refund"]])).encode("utf-8"),
unhashed_description=LnurlPayMetadata(
json.dumps([["text/plain", "Refund"]])
).encode("utf-8"),
extra={"refund": hit_id},
)
payResponse = {"pr": payment_request, "successAction": success_action, "routes": []}
return json.dumps(payResponse)

View File

@ -36,14 +36,13 @@ class Card(BaseModel):
return cls(**dict(row))
def lnurl(self, req: Request) -> Lnurl:
url = req.url_for(
"boltcard.lnurl_response", device_id=self.id, _external=True
)
url = req.url_for("boltcard.lnurl_response", device_id=self.id, _external=True)
return lnurl_encode(url)
async def lnurlpay_metadata(self) -> LnurlPayMetadata:
return LnurlPayMetadata(json.dumps([["text/plain", self.title]]))
class CreateCardData(BaseModel):
card_name: str = Query(...)
uid: str = Query(...)
@ -58,6 +57,7 @@ class CreateCardData(BaseModel):
prev_k1: str = Query(ZERO_KEY)
prev_k2: str = Query(ZERO_KEY)
class Hit(BaseModel):
id: str
card_id: str
@ -72,6 +72,7 @@ class Hit(BaseModel):
def from_row(cls, row: Row) -> "Hit":
return cls(**dict(row))
class Refund(BaseModel):
id: str
hit_id: str

View File

@ -9,7 +9,6 @@ const mapCards = obj => {
return obj
}
new Vue({
el: '#vue',
mixins: [windowMixin],
@ -23,11 +22,12 @@ new Vue({
cardDialog: {
show: false,
data: {
counter:1,
counter: 1,
k0: '',
k1: '',
k2: '',
card_name:''},
card_name: ''
},
temp: {}
},
cardsTable: {
@ -190,7 +190,7 @@ new Vue({
})
})
},
openQrCodeDialog(cardId) {
openQrCodeDialog (cardId) {
var card = _.findWhere(this.cards, {id: cardId})
this.qrCodeDialog.data = {
link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp,
@ -352,7 +352,7 @@ new Vue({
},
exportRefundsCSV: function () {
LNbits.utils.exportCSV(this.refundsTable.columns, this.refunds)
},
}
},
created: function () {
if (this.g.user.wallets.length) {

View File

@ -27,8 +27,9 @@ async def on_invoice_paid(payment: Payment) -> None:
if payment.extra.get("wh_status"):
# this webhook has already been sent
return
hit = await get_hit(payment.extra.get("tag")[7:len(payment.extra.get("tag"))])
hit = await get_hit(payment.extra.get("tag")[7 : len(payment.extra.get("tag"))])
if hit:
refund = await create_refund(hit_id=hit.id, refund_amount=payment.extra.get("amount"))
refund = await create_refund(
hit_id=hit.id, refund_amount=payment.extra.get("amount")
)
await mark_webhook_sent(payment, 1)

View File

@ -15,10 +15,6 @@
>More details</a
>
<br />
<small>
Created by,
<a href="https://twitter.com/btcslovnik">iWarp</a></small
>
</p>
</q-card-section>
</q-card>

View File

@ -8,11 +8,18 @@
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<div class="row justify-start" style="width:150px">
<div class="col" >
<div class="col">
<h5 class="text-subtitle1 q-my-none">Cards</h5>
</div>
<div class="col">
<q-btn round size="sm" icon="add" unelevated color="primary" @click="addCardOpen">
<q-btn
round
size="sm"
icon="add"
unelevated
color="primary"
@click="addCardOpen"
>
<q-tooltip>Add card</q-tooltip>
</q-btn>
</div>
@ -53,14 +60,18 @@
icon="qr_code"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
@click="openQrCodeDialog(props.row.id)"
><q-tooltip>Card key credentials</q-tooltip></q-btn>
><q-tooltip>Card key credentials</q-tooltip></q-btn
>
</q-td>
<q-td auto-width>
<q-btn
outline
color="grey"
@click="copyText(lnurlLink + props.row.uid)"
lnurlLink >lnurl://...<q-tooltip>Click to copy, then add to NFC card</q-tooltip>
lnurlLink
>lnurl://...<q-tooltip
>Click to copy, then add to NFC card</q-tooltip
>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
@ -72,13 +83,15 @@
dense
@click="enableCard(props.row.wallet, props.row.id, false)"
color="pink"
>DISABLE</q-btn>
>DISABLE</q-btn
>
<q-btn
v-else
dense
@click="enableCard(props.row.wallet, props.row.id, true)"
color="green"
>ENABLE</q-btn>
>ENABLE</q-btn
>
</q-td>
<q-td auto-width>
<q-btn
@ -88,7 +101,8 @@
@click="updateCardDialog(props.row.id)"
icon="edit"
color="light-blue"
><q-tooltip>Edit card</q-tooltip></q-btn>
><q-tooltip>Edit card</q-tooltip></q-btn
>
</q-td>
<q-td auto-width>
<q-btn
@ -98,7 +112,10 @@
@click="deleteCard(props.row.id)"
icon="cancel"
color="pink"
><q-tooltip>Deleting card will also delete all records</q-tooltip></q-btn>
><q-tooltip
>Deleting card will also delete all records</q-tooltip
></q-btn
>
</q-td>
</q-tr>
</template>
@ -243,8 +260,6 @@
></q-input>
<div class="row">
<div class="col-10">
<q-input
filled
dense
@ -252,9 +267,10 @@
v-model.trim="cardDialog.data.uid"
type="text"
label="Card UID "
><q-tooltip>Get from the card you'll use, using an NFC app</q-tooltip></q-input>
><q-tooltip
>Get from the card you'll use, using an NFC app</q-tooltip
></q-input
>
</div>
<div class="col-2 q-pl-sm">
<q-btn
@ -263,11 +279,11 @@
color="grey"
icon="nfc"
:disable="nfcTagReading"
><q-tooltip>Tap card to scan UID (coming soon)</q-tooltip></q-btn>
><q-tooltip>Tap card to scan UID (coming soon)</q-tooltip></q-btn
>
</div>
</div>
<q-toggle
v-model="toggleAdvanced"
label="Show advanced options"
@ -276,7 +292,6 @@
<q-input
filled
dense
v-model.trim="cardDialog.data.k0"
type="text"
label="Card Auth key (K0)"
@ -287,7 +302,6 @@
<q-input
filled
dense
v-model.trim="cardDialog.data.k1"
type="text"
label="Card Meta key (K1)"
@ -296,7 +310,6 @@
<q-input
filled
dense
v-model.trim="cardDialog.data.k2"
type="text"
label="Card File key (K2)"

View File

@ -29,6 +29,7 @@ from .nxp424 import decryptSUN, getSunMAC
from loguru import logger
@boltcards_ext.get("/api/v1/cards")
async def api_cards(
g: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
@ -89,6 +90,7 @@ async def api_card_create_or_update(
card = await create_card(wallet_id=wallet.wallet.id, data=data)
return card.dict()
@boltcards_ext.get("/api/v1/cards/enable/{card_id}/{enable}", status_code=HTTPStatus.OK)
async def enable_card(
card_id,
@ -97,16 +99,13 @@ async def enable_card(
):
card = await get_card(card_id)
if not card:
raise HTTPException(
detail="No card found.", status_code=HTTPStatus.NOT_FOUND
)
raise HTTPException(detail="No card found.", status_code=HTTPStatus.NOT_FOUND)
if card.wallet != wallet.wallet.id:
raise HTTPException(
detail="Not your card.", status_code=HTTPStatus.FORBIDDEN
)
raise HTTPException(detail="Not your card.", status_code=HTTPStatus.FORBIDDEN)
card = await enable_disable_card(enable=enable, id=card_id)
return card.dict()
@boltcards_ext.delete("/api/v1/cards/{card_id}")
async def api_card_delete(card_id, wallet: WalletTypeInfo = Depends(require_admin_key)):
card = await get_card(card_id)
@ -139,6 +138,7 @@ async def api_hits(
return [hit.dict() for hit in await get_hits(cards_ids)]
@boltcards_ext.get("/api/v1/refunds")
async def api_hits(
g: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)