Skip to content

Commit 2287171

Browse files
committed
back
1 parent d6f145e commit 2287171

31 files changed

+278
-182
lines changed

lnbits/app.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,7 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
4848
origins = ["*"]
4949

5050
app.add_middleware(
51-
CORSMiddleware,
52-
allow_origins=origins,
53-
allow_methods=["*"],
54-
allow_headers=["*"],
51+
CORSMiddleware, allow_origins=origins, allow_methods=["*"], allow_headers=["*"]
5552
)
5653

5754
g().config = lnbits.settings

lnbits/bolt11.py

+61-46
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ def decode(pr: str) -> Invoice:
116116
return invoice
117117

118118

119-
120119
def encode(options):
121120
""" Convert options into LnAddr and pass it to the encoder
122121
"""
@@ -131,80 +130,91 @@ def encode(options):
131130
addr.paymenthash = unhexlify(options.paymenthash)
132131

133132
if options.description:
134-
addr.tags.append(('d', options.description))
133+
addr.tags.append(("d", options.description))
135134
if options.description_hashed:
136-
addr.tags.append(('h', options.description_hashed))
135+
addr.tags.append(("h", options.description_hashed))
137136
if options.expires:
138-
addr.tags.append(('x', options.expires))
137+
addr.tags.append(("x", options.expires))
139138

140139
if options.fallback:
141-
addr.tags.append(('f', options.fallback))
140+
addr.tags.append(("f", options.fallback))
142141

143142
for r in options.route:
144-
splits = r.split('/')
145-
route=[]
143+
splits = r.split("/")
144+
route = []
146145
while len(splits) >= 5:
147-
route.append((unhexlify(splits[0]),
148-
unhexlify(splits[1]),
149-
int(splits[2]),
150-
int(splits[3]),
151-
int(splits[4])))
146+
route.append(
147+
(
148+
unhexlify(splits[0]),
149+
unhexlify(splits[1]),
150+
int(splits[2]),
151+
int(splits[3]),
152+
int(splits[4]),
153+
)
154+
)
152155
splits = splits[5:]
153-
assert(len(splits) == 0)
154-
addr.tags.append(('r', route))
156+
assert len(splits) == 0
157+
addr.tags.append(("r", route))
155158
return lnencode(addr, options.privkey)
156159

157160

158161
def lnencode(addr, privkey):
159162
if addr.amount:
160163
amount = Decimal(str(addr.amount))
161164
# We can only send down to millisatoshi.
162-
if amount * 10**12 % 10:
163-
raise ValueError("Cannot encode {}: too many decimal places".format(
164-
addr.amount))
165+
if amount * 10 ** 12 % 10:
166+
raise ValueError(
167+
"Cannot encode {}: too many decimal places".format(addr.amount)
168+
)
165169

166170
amount = addr.currency + shorten_amount(amount)
167171
else:
168-
amount = addr.currency if addr.currency else ''
172+
amount = addr.currency if addr.currency else ""
169173

170-
hrp = 'ln' + amount
174+
hrp = "ln" + amount
171175

172176
# Start with the timestamp
173-
data = bitstring.pack('uint:35', addr.date)
177+
data = bitstring.pack("uint:35", addr.date)
174178

175179
# Payment hash
176-
data += tagged_bytes('p', addr.paymenthash)
180+
data += tagged_bytes("p", addr.paymenthash)
177181
tags_set = set()
178182

179183
for k, v in addr.tags:
180184

181185
# BOLT #11:
182186
#
183187
# A writer MUST NOT include more than one `d`, `h`, `n` or `x` fields,
184-
if k in ('d', 'h', 'n', 'x'):
188+
if k in ("d", "h", "n", "x"):
185189
if k in tags_set:
186190
raise ValueError("Duplicate '{}' tag".format(k))
187191

188-
if k == 'r':
192+
if k == "r":
189193
route = bitstring.BitArray()
190194
for step in v:
191195
pubkey, channel, feebase, feerate, cltv = step
192-
route.append(bitstring.BitArray(pubkey) + bitstring.BitArray(channel) + bitstring.pack('intbe:32', feebase) + bitstring.pack('intbe:32', feerate) + bitstring.pack('intbe:16', cltv))
193-
data += tagged('r', route)
194-
elif k == 'f':
196+
route.append(
197+
bitstring.BitArray(pubkey)
198+
+ bitstring.BitArray(channel)
199+
+ bitstring.pack("intbe:32", feebase)
200+
+ bitstring.pack("intbe:32", feerate)
201+
+ bitstring.pack("intbe:16", cltv)
202+
)
203+
data += tagged("r", route)
204+
elif k == "f":
195205
data += encode_fallback(v, addr.currency)
196-
elif k == 'd':
197-
data += tagged_bytes('d', v.encode())
198-
elif k == 'x':
206+
elif k == "d":
207+
data += tagged_bytes("d", v.encode())
208+
elif k == "x":
199209
# Get minimal length by trimming leading 5 bits at a time.
200-
expirybits = bitstring.pack('intbe:64', v)[4:64]
201-
while expirybits.startswith('0b00000'):
210+
expirybits = bitstring.pack("intbe:64", v)[4:64]
211+
while expirybits.startswith("0b00000"):
202212
expirybits = expirybits[5:]
203-
data += tagged('x', expirybits)
204-
elif k == 'h':
205-
data += tagged_bytes('h', hashlib.sha256(v.encode('utf-8')).digest())
206-
elif k == 'n':
207-
data += tagged_bytes('n', v)
213+
data += tagged("x", expirybits)
214+
elif k == "h":
215+
data += tagged_bytes("h", hashlib.sha256(v.encode("utf-8")).digest())
216+
elif k == "n":
217+
data += tagged_bytes("n", v)
208218
else:
209219
# FIXME: Support unknown tags?
210220
raise ValueError("Unknown tag {}".format(k))
@@ -215,40 +225,45 @@ def lnencode(addr, privkey):
215225
#
216226
# A writer MUST include either a `d` or `h` field, and MUST NOT include
217227
# both.
218-
if 'd' in tags_set and 'h' in tags_set:
228+
if "d" in tags_set and "h" in tags_set:
219229
raise ValueError("Cannot include both 'd' and 'h'")
220-
if not 'd' in tags_set and not 'h' in tags_set:
230+
if not "d" in tags_set and not "h" in tags_set:
221231
raise ValueError("Must include either 'd' or 'h'")
222-
232+
223233
# We actually sign the hrp, then data (padded to 8 bits with zeroes).
224234
privkey = secp256k1.PrivateKey(bytes(unhexlify(privkey)))
225-
sig = privkey.ecdsa_sign_recoverable(bytearray([ord(c) for c in hrp]) + data.tobytes())
235+
sig = privkey.ecdsa_sign_recoverable(
236+
bytearray([ord(c) for c in hrp]) + data.tobytes()
237+
)
226238
# This doesn't actually serialize, but returns a pair of values :(
227239
sig, recid = privkey.ecdsa_recoverable_serialize(sig)
228240
data += bytes(sig) + bytes([recid])
229241

230242
return bech32_encode(hrp, bitarray_to_u5(data))
231243

244+
232245
class LnAddr(object):
233-
def __init__(self, paymenthash=None, amount=None, currency='bc', tags=None, date=None):
246+
def __init__(
247+
self, paymenthash=None, amount=None, currency="bc", tags=None, date=None
248+
):
234249
self.date = int(time.time()) if not date else int(date)
235250
self.tags = [] if not tags else tags
236251
self.unknown_tags = []
237-
self.paymenthash=paymenthash
252+
self.paymenthash = paymenthash
238253
self.signature = None
239254
self.pubkey = None
240255
self.currency = currency
241256
self.amount = amount
242257

243258
def __str__(self):
244259
return "LnAddr[{}, amount={}{} tags=[{}]]".format(
245-
hexlify(self.pubkey.serialize()).decode('utf-8'),
246-
self.amount, self.currency,
247-
", ".join([k + '=' + str(v) for k, v in self.tags])
260+
hexlify(self.pubkey.serialize()).decode("utf-8"),
261+
self.amount,
262+
self.currency,
263+
", ".join([k + "=" + str(v) for k, v in self.tags]),
248264
)
249265

250266

251-
252267
def _unshorten_amount(amount: str) -> int:
253268
"""Given a shortened amount, return millisatoshis"""
254269
# BOLT #11:

lnbits/core/crud.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ async def get_account(
3030
user_id: str, conn: Optional[Connection] = None
3131
) -> Optional[User]:
3232
row = await (conn or db).fetchone(
33-
"SELECT id, email, pass as password FROM accounts WHERE id = ?", (
34-
user_id,)
33+
"SELECT id, email, pass as password FROM accounts WHERE id = ?", (user_id,)
3534
)
3635

3736
return User(**row) if row else None
@@ -305,8 +304,7 @@ async def delete_expired_invoices(conn: Optional[Connection] = None,) -> None:
305304
except:
306305
continue
307306

308-
expiration_date = datetime.datetime.fromtimestamp(
309-
invoice.date + invoice.expiry)
307+
expiration_date = datetime.datetime.fromtimestamp(invoice.date + invoice.expiry)
310308
if expiration_date > datetime.datetime.utcnow():
311309
continue
312310

lnbits/core/services.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def pay_invoice(
9595
if max_sat and invoice.amount_msat > max_sat * 1000:
9696
raise ValueError("Amount in invoice is too high.")
9797

98-
wallet = await get_wallet(wallet_id, conn=conn)
98+
wallet = await get_wallet(wallet_id, conn=conn)
9999

100100
# put all parameters that don't change here
101101
PaymentKwargs = TypedDict(
@@ -141,15 +141,19 @@ async def pay_invoice(
141141

142142
# do the balance check if internal payment
143143
if internal_checking_id:
144-
wallet = await get_wallet(wallet_id, conn=conn)
144+
wallet = await get_wallet(wallet_id, conn=conn)
145145
assert wallet
146146
if wallet.balance_msat < 0:
147147
raise PermissionError("Insufficient balance.")
148148

149149
# do the balance check if external payment
150150
else:
151-
if invoice.amount_msat > wallet.balance_msat - (wallet.balance_msat / 100 * 2):
152-
raise PermissionError("LNbits requires you keep at least 2% reserve to cover potential routing fees.")
151+
if invoice.amount_msat > wallet.balance_msat - (
152+
wallet.balance_msat / 100 * 2
153+
):
154+
raise PermissionError(
155+
"LNbits requires you keep at least 2% reserve to cover potential routing fees."
156+
)
153157

154158
if internal_checking_id:
155159
# mark the invoice from the other side as not pending anymore
@@ -326,8 +330,7 @@ async def check_invoice_status(
326330
if not payment.pending:
327331
return status
328332
if payment.is_out and status.failed:
329-
print(
330-
f" - deleting outgoing failed payment {payment.checking_id}: {status}")
333+
print(f" - deleting outgoing failed payment {payment.checking_id}: {status}")
331334
await payment.delete()
332335
elif not status.pending:
333336
print(

lnbits/core/views/api.py

+15-14
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ async def api_update_wallet(
7777
@core_app.get("/api/v1/payments")
7878
async def api_payments(wallet: WalletTypeInfo = Depends(get_key_type)):
7979
await get_payments(wallet_id=wallet.wallet.id, pending=True, complete=True)
80-
pendingPayments = await get_payments(wallet_id=wallet.wallet.id, pending=True, exclude_uncheckable=True)
80+
pendingPayments = await get_payments(
81+
wallet_id=wallet.wallet.id, pending=True, exclude_uncheckable=True
82+
)
8183
for payment in pendingPayments:
8284
await check_invoice_status(
8385
wallet_id=payment.wallet_id, payment_hash=payment.payment_hash
@@ -198,8 +200,7 @@ async def api_payments_create(
198200
invoiceData: CreateInvoiceData = Body(...),
199201
):
200202
if wallet.wallet_type < 0 or wallet.wallet_type > 2:
201-
raise HTTPException(
202-
status_code=HTTPStatus.BAD_REQUEST, detail="Key is invalid")
203+
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Key is invalid")
203204

204205
if invoiceData.out is True and wallet.wallet_type == 0:
205206
if not invoiceData.bolt11:
@@ -379,16 +380,14 @@ async def api_lnurlscan(code: str):
379380
params.update(callback=url) # with k1 already in it
380381

381382
lnurlauth_key = g().wallet.lnurlauth_key(domain)
382-
params.update(
383-
pubkey=lnurlauth_key.verifying_key.to_string("compressed").hex())
383+
params.update(pubkey=lnurlauth_key.verifying_key.to_string("compressed").hex())
384384
else:
385385
async with httpx.AsyncClient() as client:
386386
r = await client.get(url, timeout=5)
387387
if r.is_error:
388388
raise HTTPException(
389389
status_code=HTTPStatus.SERVICE_UNAVAILABLE,
390-
detail={"domain": domain,
391-
"message": "failed to get parameters"},
390+
detail={"domain": domain, "message": "failed to get parameters"},
392391
)
393392

394393
try:
@@ -418,8 +417,7 @@ async def api_lnurlscan(code: str):
418417

419418
if tag == "withdrawRequest":
420419
params.update(kind="withdraw")
421-
params.update(fixed=data["minWithdrawable"]
422-
== data["maxWithdrawable"])
420+
params.update(fixed=data["minWithdrawable"] == data["maxWithdrawable"])
423421

424422
# callback with k1 already in it
425423
parsed_callback: ParseResult = urlparse(data["callback"])
@@ -509,18 +507,21 @@ async def api_list_currencies_available():
509507

510508

511509
class ConversionData(BaseModel):
512-
from_: str = Field('sat', alias="from")
510+
from_: str = Field("sat", alias="from")
513511
amount: float
514-
to: str = Query('usd')
512+
to: str = Query("usd")
513+
515514

516515
@core_app.post("/api/v1/conversion")
517516
async def api_fiat_as_sats(data: ConversionData):
518517
output = {}
519-
if data.from_ == 'sat':
518+
if data.from_ == "sat":
520519
output["sats"] = int(data.amount)
521520
output["BTC"] = data.amount / 100000000
522-
for currency in data.to.split(','):
523-
output[currency.strip().upper()] = await satoshis_amount_as_fiat(data.amount, currency.strip())
521+
for currency in data.to.split(","):
522+
output[currency.strip().upper()] = await satoshis_amount_as_fiat(
523+
data.amount, currency.strip()
524+
)
524525
return output
525526
else:
526527
output[data.from_.upper()] = data.amount

lnbits/core/views/generic.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ async def home(request: Request, lightning: str = None):
4343

4444

4545
@core_html_routes.get(
46-
"/extensions",
47-
name="core.extensions",
48-
response_class=HTMLResponse,
46+
"/extensions", name="core.extensions", response_class=HTMLResponse
4947
)
5048
async def extensions(
5149
request: Request,

lnbits/decorators.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ async def require_admin_key(
171171
else:
172172
return wallet
173173

174+
174175
async def require_invoice_key(
175176
r: Request,
176177
api_key_header: str = Security(api_key_header),
@@ -184,7 +185,8 @@ async def require_invoice_key(
184185
# If wallet type is not invoice then return the unauthorized status
185186
# This also covers when the user passes an invalid key type
186187
raise HTTPException(
187-
status_code=status.HTTP_401_UNAUTHORIZED, detail="Invoice (or Admin) key required."
188+
status_code=status.HTTP_401_UNAUTHORIZED,
189+
detail="Invoice (or Admin) key required.",
188190
)
189191
else:
190192
return wallet

lnbits/extensions/lnaddress/lnurl.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async def lnurl_callback(address_id, amount: int = Query(...)):
5252
amount_received = amount
5353

5454
domain = await get_domain(address.domain)
55-
55+
5656
base_url = (
5757
address.wallet_endpoint[:-1]
5858
if address.wallet_endpoint.endswith("/")
@@ -71,7 +71,9 @@ async def lnurl_callback(address_id, amount: int = Query(...)):
7171
"out": False,
7272
"amount": int(amount_received / 1000),
7373
"description_hash": hashlib.sha256(
74-
(await address.lnurlpay_metadata(domain=domain.domain)).encode("utf-8")
74+
(await address.lnurlpay_metadata(domain=domain.domain)).encode(
75+
"utf-8"
76+
)
7577
).hexdigest(),
7678
"extra": {"tag": f"Payment to {address.username}@{domain.domain}"},
7779
},

lnbits/extensions/lnaddress/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ async def lnurlpay_metadata(self, domain) -> LnurlPayMetadata:
5353
text = f"Payment to {self.username}"
5454
identifier = f"{self.username}@{domain}"
5555
metadata = [["text/plain", text], ["text/identifier", identifier]]
56-
56+
5757
return LnurlPayMetadata(json.dumps(metadata))

0 commit comments

Comments
 (0)